All pastes #10028 Raw Edit

Miscellany

public python v1 · immutable
#10028 ·published 2005-04-21 19:45 UTC
rendered paste body
"""MultiMixer, a sensor for controlling an array based display with multiplechannels available.by Justin "nagash" Jones <randomgalssuck@iinet.net.au>Credit goes to Martin Aspeli <optilude@gmx.net>, I used alot of his stuff.This is really just a modified version of his Mixer sensor, with support forarrays and hence, more than one channel.Thanks also go to the people who made StarterBar and SysInfo. I studied theirdesklets while figuring out how to use arrays. :)There is a couple of bugs with gdesklets <= 0.25.1pycage tells me they will be fixed for 0.26. They arent major, just a couple ofproblems with arrays.Also, this sensor is quite cpu intensive, especially when u start adding more than2 or 3 mixer channels. You have been warned.Parameters...- width: the width of your gauges, this is needed to calculate for the "click to set volume"- increment: the default amount (in %) you wish to set for "scroll to change volume"- device: the mixer device- interval: the update time (in ms). anything lower than 200 is a little too cpu intensive	for my liking. anything greater makes it feel lagged when u change the volume- fontnumber: the number of fonts u wish to use (ala FontSelector Sensor)- fontargs: ala FontSelectorThe only thing from Psi-Disp-Themes which this doesnt support is the gauges, due to thearrays. I was going to add the gauge setting into this sensor, but I dont think it's necessary.I'm almost positive my code isnt the nicest in the world. If someone wants to clean it up,be my guest. :)"""from sensor.Sensor import Sensorfrom utils.datatypes import *import ossaudiodevclass MultiMixer(Sensor):	CHANNELS = [	[ "Volume",		"Vol",		ossaudiodev.SOUND_MIXER_VOLUME ],			[ "PCM",		"PCM",		ossaudiodev.SOUND_MIXER_PCM ],			[ "Bass",		"Bass",		ossaudiodev.SOUND_MIXER_BASS ],			[ "Treble",		"Treb",		ossaudiodev.SOUND_MIXER_BASS ],			[ "Synth",		"Synth",	ossaudiodev.SOUND_MIXER_SYNTH ],			[ "PC Speaker", 	"PCS",		ossaudiodev.SOUND_MIXER_SPEAKER ],			[ "Line 1",		"Line1",	ossaudiodev.SOUND_MIXER_LINE1 ],			[ "Line 2",		"Line2",	ossaudiodev.SOUND_MIXER_LINE2 ],			[ "Line 3",		"Line3",	ossaudiodev.SOUND_MIXER_LINE3 ],			[ "Line Out",		"LiOut",	ossaudiodev.SOUND_MIXER_LINE ],			[ "Microphone",		"Mic",		ossaudiodev.SOUND_MIXER_MIC ],			[ "CD Audio",		"CDA",		ossaudiodev.SOUND_MIXER_CD ],			[ "Input Gain",		"IGain",	ossaudiodev.SOUND_MIXER_IGAIN ],			[ "Output Gain",	"OGain",	ossaudiodev.SOUND_MIXER_OGAIN ],			[ "Digital 1",		"Dig1",		ossaudiodev.SOUND_MIXER_DIGITAL1 ],			[ "Digital 2",		"Dig2",		ossaudiodev.SOUND_MIXER_DIGITAL2 ],			[ "Digital 3",		"Dig3",		ossaudiodev.SOUND_MIXER_DIGITAL3 ],			[ "Phone In",		"PhIn",		ossaudiodev.SOUND_MIXER_PHONEIN ],			[ "Phone Out",		"PhOut",	ossaudiodev.SOUND_MIXER_PHONEOUT ],			[ "Video",		"Video",	ossaudiodev.SOUND_MIXER_VIDEO ],			[ "Radio",		"Radio",	ossaudiodev.SOUND_MIXER_RADIO ],			[ "Monitor",		"Mon",		ossaudiodev.SOUND_MIXER_MONITOR ]	]		AVAILABLE_CHANNELS = []		def __init__(self, width, increment = 5, device = "/dev/dsp", interval = 200, fontnumber = 1, *fontargs):		self.__xpos = 0		self.__width = int(width)		self.__interval = int(interval)		self.__activeChannels = []				self.__size = 0		self.__size_changed = 0				self.__fontnumber = int(fontnumber)		self.__fonts = []		self.__colors = []		Sensor.__init__(self)				# Setup basic configuration entries		self._set_config_type("device", TYPE_STRING, device)		self._set_config_type("increment", TYPE_INT, int(increment))		# Setup font configuration entries		if (len(fontargs) == 1 and fontargs[0].find("  ") != -1):			fontargs = (fontargs[0].replace("   ", ",").replace("  ", ",")).split(",")			print "Using spaces to separate font entries is deprecated."			print "Use commas instead."            		fontargs = list(fontargs)		for font_n in xrange(self.__fontnumber):			if (fontargs): font = fontargs.pop(0)			else: font = "Sans 8"			if (fontargs): color = fontargs.pop(0)			else: color = "black"			self._set_config_type("font%i" % font_n, TYPE_STRING, font)			self._set_config_type("color%i" % font_n, TYPE_STRING, color)		# Setup channel configuration entries		mixer = ossaudiodev.openmixer(device)		i = 0		for channel in self.CHANNELS:			if mixer.controls() & (1 << channel[2]):				self.AVAILABLE_CHANNELS.append([ channel[0], channel[1], channel[2] ])				self._set_config_type(channel[1], TYPE_BOOL, 0)				i += 1		mixer.close()		self._watch_config(self.__on_watch_config)		self._add_timer(0, self.__channel_init)		self._add_timer(0, self.__font_init)		self._add_timer(0, self.__get_data)	def __channel_init(self):		output = self._new_output()		for channel in self.AVAILABLE_CHANNELS:			if self._get_config(channel[1]) == 1:				self.__size += 1				self.__size_changed = 1				self.__activeChannels.append([ channel[1], channel[2] ])							output = self._new_output()			output.set("size", self.__size)			self._send_output(output)		def __get_data(self):		output = self._new_output()		output.set("device", self._get_config("device"))				index = 0		for channel in self.__activeChannels:			output.set("channel[%d]" % index, channel[0])			output.set("volume[%d]" % index, self._get_volume(channel[1]))			index += 1		self._add_timer(self.__interval, self.__get_data)		self._send_output(output)	def __font_init(self):		fonts = []		colors = []		for font_n in xrange(self.__fontnumber):			fonts.append(self._get_config("font%i" % font_n))			colors.append(self._get_config("color%i" % font_n))		output = self._new_output()		for i in range(self.__size):			for font_n in xrange(self.__fontnumber):				output.set("font%i[%d]" % (font_n, i), fonts[font_n])				output.set("color%i[%d]" % (font_n, i), colors[font_n])					self._send_output(output)        		def get_configurator(self):		configurator = self._new_configurator()		configurator.set_name("Mixer")		# Basic Configuration		configurator.add_title("Audio Mixer")		configurator.add_entry("Device", "device", "Mixer Device")		configurator.add_spin("Wheel Increment", "increment", "Percent to increase/decrease", 1, 10)				# Fonts configuration		configurator.add_title("Fonts")		for font_n in xrange(self.__fontnumber):			configurator.add_font_selector("Font #%i:" % font_n, "font%i" % font_n, "Font #%i used in the labels" % font_n)			configurator.add_color_selector("Font color #%i:" % font_n, "color%i" % font_n, "Font color #%i used in the labels" % font_n)				# Mixer Configuration		configurator.add_title("Mixer Channels")		for channel in self.AVAILABLE_CHANNELS:			configurator.add_checkbox(channel[0] + " (" + channel[1] + ")", channel[1], "Enable this mixer channel?")		return configurator	def __on_watch_config(self, key, value):		for channel in self.AVAILABLE_CHANNELS:			if (key == channel[1]):				if value == "false":					self.__size -= 1					self.__size_changed = 1					self.__activeChannels.remove([ channel[1], channel[2] ])					self._add_timer(self.__interval + 50, self.__font_init)				elif value == "true":										self.__size += 1					self.__size_changed = 1					self.__activeChannels.append([ channel[1], channel[2] ])					self._add_timer(self.__interval + 50, self.__font_init)								output = self._new_output()				output.set("size", self.__size)				self._send_output(output)	def call_action(self, action, path, args = []):		if action == "move":			self.__xpos = args[0]		elif action == "click":				index = path[-1]			volume = (self.__xpos * 100) / self.__width			volume = ((self.__xpos - 45) * 100) / self.__width			self._set_volume(volume, index)		elif action == "scroll":			increment = 0						if args[0] == 0:   # Volume up				increment = self._get_config("increment")			elif args[0] == 1: # Volume down				increment = self._get_config("increment") * -1							if increment != 0:				index = path[-1]				self._change_volume(increment, index)	def _get_mixer(self):				device = self._get_config("device")		mixer = None		try:			mixer = ossaudiodev.openmixer(device)			if not mixer:				raise "Error opening mixer"		except:			return None		return mixer	def _get_volume(self, channel = None):				mixer = None		try:			mixer = self._get_mixer()			if mixer and channel >= 0:				volumes = mixer.get(channel)				volume = (volumes[0] + volumes[1]) / 2				return volume			else:				return -1				finally:			if mixer:				mixer.close()	def _get_channel(self, index):		channel = None		i = 0		for value in self.AVAILABLE_CHANNELS:			if self._get_config(value[1]) == 1:				if i == index:					channel = value[2]				i += 1		return channel	def _set_volume (self, volume, index):		"Set the volume to the given value (0-100)"			mixer = None		channel = self._get_channel(index)				try:			mixer = self._get_mixer()					if mixer and channel >= 0:				mixer.set(channel, (volume, volume))		finally:			if mixer:				mixer.close()	def _change_volume (self, increment, index):		"Change the volume by increment (may be negative), but stay within range 0-100"				mixer = None		channel = self._get_channel(index)				try:			mixer = self._get_mixer()				if mixer and channel >= 0:				volumes = mixer.get(channel)				volume = (volumes[0] + volumes[1])/2				new_volume = volume + increment				if new_volume < 0:					new_volume = 0				elif new_volume > 100:					new_volume = 100								mixer.set(channel, (new_volume, new_volume))		finally:			if mixer:				mixer.close()def new_sensor(args): return apply(MultiMixer, args)