#!/usr/bin/env python
# asoundconf-gtk - GTK GUI to select the default sound card
#
# (C) 2006 Toby Smithe
# asoundconf parts (C) 2005 Canonical Ltd.
# gourmet parts (C) 2005 Thomas Hinkle (and any other gourmet developers)
# Both the asoundconf and gourmet projects are also licenced under the 
# GPLv2 or any later version in exactly the same way as this project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

import sys, re, os, pygtk, gtk, string

######################################
#START small block of asoundconf code#
######################################

def getcards():
	cardspath = '/proc/asound/cards'
	if not os.path.exists(cardspath):
		return False
	procfile = open(cardspath, 'rb')
	cardline = re.compile('^\s*\d+\s*\[')
	card_lines = []
	lines = procfile.readlines()
	for l in lines:
		if cardline.match(l):
			card_lines.append(re.sub(r'^\s*\d+\s*\[(\w+)\s*\].+','\\1',l))
	return card_lines # Snipped here

####################################
#END small block of asoundconf code#
####################################

###################################
#START small block of gourmet code#
###################################

def cb_set_active_text (combobox, text, col=0):
    """Set the active text of combobox to text. We fail
    if the text is not already in the model. Column is the column
    of the model from which text is drawn."""
    model = combobox.get_model()
    n = 0
    for rw in model:
        if rw[col]==text:
            combobox.set_active(n)
            return n
       	n += 1
    return None

#################################
#END small block of gourmet code#
#################################

asoundconf = "/usr/bin/asoundconf"

# Kill the application if it cannot run
def die_on_error():
	if not os.path.exists("/proc/asound/cards"):
		print "You need at least one ALSA sound card for this to work!"
		sys.exit(-1)
	if os.system(asoundconf + " is-active"):
		print "You need to make sure asoundconf is active!"
		print "By default, asoundconf's configuration file is ~/.asoundrc.asoundconf"
		print "and must be included in ~/.asoundrc. Open this file to make sure it is!"
		sys.exit(-2)

# Get an asoundconf setting
def get(setting):
	cmd = asoundconf + " get " + setting
	output = os.popen(cmd).readlines()
	return output

# Get the default PCM card (but assume this is the default card for everything)
# This is just a very simple wrapper for get(...) as otherwise I'd have to repeat
# a load (well, two lines) of code.
def get_default_card():
	value_raw = get("defaults.pcm.card")
	if not value_raw:
		return 0
	value = string.strip(value_raw[0])
	return value

# Set the default card using asoundconf
def set_default_card(card):
	call = asoundconf + " set-default-card " + card
	return os.system(call)
	
class asoundconf_gtk:
	# The GUI
	def destroy(self, widget, data=None):
		# This is a stub function to allow for stuff to be done on close
		gtk.main_quit()

	def delete_event(self, widget, event, data=None):
		# Again, a stub to allow stuff to happen when widgets are deleted
		return False

	def choose(self, widget, data=None):
		card = self.combo.get_active_text()
		set_default_card(card)
	
	def reset(self, widget, data=None):
		set_default_card(get_default_card())
	
	def __init__(self):
		# Initiate the window
		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		self.window.set_title("Default Sound Card")
		# Create an HBox box
		self.selectionbox = gtk.HBox(False, 0)
		# Create a button
		self.button = gtk.Button("Quit")
		self.button.connect("clicked", self.reset, None)
		self.button.connect_object("clicked", gtk.Widget.destroy, self.window)
		# Create combobox
		self.combo = gtk.combo_box_new_text()
		self.liststore = self.combo.get_model()
		# Add cards to combobox liststore
		cards = getcards()
		if not cards:
			return False
		for card in cards:
			self.combo.append_text(card.strip())
		self.combo.connect("changed", self.choose, None)
		# Select current default card
		result = cb_set_active_text(self.combo, get_default_card())
		# Create a label
		self.label = gtk.Label("Select default card: ")
		# Add contents to HBox "selectionbox"
		self.selectionbox.pack_start(self.combo, True, True, 0)		
		self.selectionbox.pack_start(self.button, True, True, 0)
		# Create a VBox
		self.vbox = gtk.VBox(False, 0)
		self.window.add(self.vbox)
		self.vbox.pack_start(self.label, True, True, 0)
		self.vbox.pack_start(self.selectionbox, True, True, 0)
		# Connect up window events
		self.window.connect("destroy",self.destroy)
		self.window.connect("delete_event",self.delete_event)
		# Show window and contents
		self.window.show_all()

	def main(self):
		# Do the stuffs
		gtk.main()

# Main application code...
# Ensure the application *can* run
die_on_error()
aconf = asoundconf_gtk()
sys.exit(aconf.main())
