Logo Search packages:      
Sourcecode: earcandy version File versions  Download package

EarCandyPrefs.py

# Ear Candy - Pulseaduio sound managment tool
# Copyright (C) 2008 Jason Taylor
# 
# 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, see <http://www.gnu.org/licenses/>.


import sys
import gobject
import re
import time
try:
     import pygtk
     pygtk.require("2.0")
except:
      pass
try:
    import gtk
    import gtk.glade
except:
    sys.exit(1)


from Threads import threaded
from glade_window import GladeWindow
from EarCandyAppSelect import EarCandyAppSelect
from EarCandyClientProperties import EarCandyClientProperties

class EarCandayPref(GladeWindow):
    def __init__(self, core):
        
        self.core = core

        self.vals = {"" : 0, "music" : 1, "video" : 2, "phone": 3}

        GladeWindow.__init__(self, "pulseoptions.glade", "dialog_options")

        self.treeview_pulse_clients = self.wtree.get_widget("treeview_pulse_clients")
        self.label_pulse_client = self.wtree.get_widget("label_pulse_client")
        self.entry_pulse_client_description = self.wtree.get_widget("entry_pulse_client_description")
        self.comboboxentry_window_match = self.wtree.get_widget("comboboxentry_window_match")
        self.radiobutton_do_not_mute_others = self.wtree.get_widget("radiobutton_do_not_mute_others")
        self.radiobutton_mute_others_onfocus = self.wtree.get_widget("radiobutton_mute_others_onfocus")
        self.radiobutton_mute_others_focus = self.wtree.get_widget("radiobutton_mute_others_focus")
        self.checkbutton_mute_onblur = self.wtree.get_widget("checkbutton_mute_onblur")
        self.checkbutton_do_not_mute = self.wtree.get_widget("checkbutton_do_not_mute")
        self.vscale_volume = self.wtree.get_widget("vscale_volume")
        self.vscale_mute = self.wtree.get_widget("vscale_mute")
        self.combobox_profile = self.wtree.get_widget("combobox_profile")
        self.entry_application = self.wtree.get_widget("entry_application")
        self.entry_command = self.wtree.get_widget("entry_command")
        self.entry_window_title = self.wtree.get_widget("entry_window_title")
        self.checkbutton_channel_window = self.wtree.get_widget("checkbutton_channel_window")
        self.label_client = self.wtree.get_widget("label_client")
        self.hscale_fade = self.wtree.get_widget("hscale_fade")
        self.hscale_mute_level = self.wtree.get_widget("hscale_mute_level")
        self.checkbutton_tray = self.wtree.get_widget("checkbutton_tray")
        self.checkbutton_output = self.wtree.get_widget("checkbutton_output")
        self.combobox_view = self.wtree.get_widget("combobox_view")
        self.checkbutton_autostart = self.wtree.get_widget("checkbutton_autostart")

        signals = {
            "on_entry_pulse_client_description_changed" : self.on_entry_pulse_client_description_changed,
            "on_combobox_profile_changed" : self.on_combobox_profile_changed,
            "on_entry_application_changed" : self.on_entry_application_changed,
            "on_entry_command_changed" : self.on_entry_command_changed,
            "on_entry_window_title_changed" : self.on_entry_window_title_changed,
            "on_vscale_volume_change_value" : self.on_vscale_volume_change_value,
            "on_vscale_mute_change_value" : self.on_vscale_mute_change_value,
            "on_checkbutton_channel_window_toggled" : self.on_checkbutton_channel_window_toggled,

            "on_treeview_pulse_clients_cursor_changed" : self.on_treeview_pulse_clients_cursor_changed,
            "on_comboboxentry_window_match_changed" : self.on_comboboxentry_window_match_changed,
            "on_entry_pulse_client_description_changed" : self.on_entry_pulse_client_description_changed,
            "on_toolbutton_delete_clicked" : self.on_toolbutton_delete_clicked,
            "on_toolbutton_edit_clicked" : self.on_toolbutton_edit_clicked,
            
            "on_hscale_mute_level_value_changed" : self.on_hscale_mute_level_value_changed,   
            "on_hscale_fade_value_changed" : self.on_hscale_fade_value_changed,         

            "on_close_button_clicked" : self.on_close_button_clicked,
            "on_button_add_new_clicked" : self.on_button_add_new_clicked,

            "on_checkbutton_tray_toggled" : self.on_checkbutton_tray_toggled,
            "on_checkbutton_output_toggled" : self.on_checkbutton_output_toggled,

            "on_combobox_view_changed" : self.on_combobox_view_changed,
            "on_treeview_pulse_clients_row_activated" : self.on_toolbutton_edit_clicked,

            "on_button_reset_clicked" : self.on_button_reset_clicked,

            "on_checkbutton_autostart_toggled" : self.on_checkbutton_autostart_toggled
        }
        self.wtree.signal_autoconnect(signals)
                
        # Setup tree


        column = gtk.TreeViewColumn((''))
        column.set_spacing(4)
        cell = gtk.CellRendererPixbuf()
        column.pack_start(cell, False)
        column.set_attributes(cell, pixbuf=0)
        self.treeview_pulse_clients.append_column(column)

        column_label = gtk.TreeViewColumn(('Application'))
        cell = gtk.CellRendererText()
        column_label.pack_start(cell, True)
        column_label.set_attributes(cell, markup=1)
        self.treeview_pulse_clients.append_column(column_label)
        column_label.set_expand(True)

        #list store for cell renderer
        self.cb_model = gtk.ListStore(str)
        for key in self.core.display.keys():
            self.cb_model.append([self.core.display[key]])

        cell = gtk.CellRendererCombo()
        cell.connect('edited', self.on_client_category_changed)
        column = gtk.TreeViewColumn('Category', cell)
        cell.set_property("model",self.cb_model)
        cell.set_property('text-column', 0)
        cell.set_property('editable', True)
        cell.connect('editing-started', self.cell_edit_start)
        column.set_attributes(cell, text = 2)
        column.set_expand(False)
        self.treeview_pulse_clients.append_column(column)

        """column = gtk.TreeViewColumn('Fix')
        cell = gtk.CellRendererToggle()
        cell.set_property('activatable', True)
        cell.connect( 'toggled', self.on_client_fade_toggled)
        column.pack_start(cell, False)
        column.set_attributes(cell, active=3)
        self.treeview_pulse_clients.append_column(column)"""

        self.last_popup = None
        self.last_path = None
        #self.update_treeview()
        self.combobox_view.set_active(0)

        self.checkbutton_autostart.set_active( self.core.is_auto_start() )

    def on_checkbutton_autostart_toggled(self, widget):
        self.core.set_auto_start( widget.get_active() )

    def on_button_reset_clicked(self, widget):

        md = gtk.MessageDialog(self.window, flags=0, type=gtk.MESSAGE_WARNING, buttons=gtk.BUTTONS_YES_NO, message_format="Are you sure you want to reset all volume levels?") 
        result = md.run()
        md.destroy()
        if result == gtk.RESPONSE_YES:
            self.core.reset_all_volumes(False)

    def cell_edit_start(self,  editable, control, path):
        self.last_popup = control
        self.last_path = path

    def on_combobox_view_changed(self, widget):
        self.update_treeview()


    def on_checkbutton_tray_toggled(self, widget):
        self.core.tray.set_visible( widget.get_active() )
        if widget.get_active():
            self.core.move_all_sinks()

    def on_checkbutton_output_toggled(self, widget):
        self.core.follow_new_outputs = widget.get_active()

    def on_client_fade_toggled(self, cell, path):
        model =  self.treeview_pulse_clients.get_model()
        iter = model.get_iter((int(path),))
        if not iter: return

        model[path][3] = not model[path][3]

        self.selected_client = model.get_value(iter, 5)
        self.selected_client.apply_volume_meter_hack = model[path][3]
        
    def on_hscale_mute_level_value_changed(self, widget):
        self.core.mute_level = self.hscale_mute_level.get_value()
        print "Mute Level ", self.core.mute_level

    def on_hscale_fade_value_changed(self, widget):
        self.core.fade_timer_speed = self.hscale_fade.get_value()

    def on_client_category_changed(self, cell, row, newText):
        model, iter =  self.treeview_pulse_clients.get_selection().get_selected()
        if not iter: return
        self.selected_client = model.get_value(iter, 5)

        for key in self.core.display.keys():
            if self.core.display[key] == newText:
                self.selected_client.category = key
                self.store.set(iter,
                    2,  newText
                )
                break

    def on_toolbutton_delete_clicked(self, widget):
        model, iter =  self.treeview_pulse_clients.get_selection().get_selected()
        if not iter: return
        self.selected_client = model.get_value(iter, 5)
        md = gtk.MessageDialog(self.window, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_YES_NO, message_format="Are you sure you want to delete this rule?") 
        result = md.run()
        md.destroy()
        if result == gtk.RESPONSE_YES:
            self.selected_client.category = ""
            self.selected_client.iter = None
            self.store.remove(iter)
        self.core.save()


    def on_toolbutton_edit_clicked(self, widget, a=None, b=None):
        model, iter =  self.treeview_pulse_clients.get_selection().get_selected()
        if not iter: return
        self.selected_client = model.get_value(iter, 5)
        print self.selected_client
        
        eccp = EarCandyClientProperties(self.core, self.selected_client, self.window)
        eccp.run()
        self.update_client(self.selected_client)
        self.core.save()

    def on_button_add_new_clicked(self, widget):
        
        if len(self.core.get_unregistered_clients()) > 0:
        
            ecas = EarCandyAppSelect(self.core)
            client = ecas.run()
            if client:
                self.update_client( client )
        else:
            md = gtk.MessageDialog(self.window, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK, message_format="There are currently no pulseaudio streams unassigned,\n\nYou will need to start your sound application playing first") 
            result = md.run()
            md.destroy()

    def on_entry_pulse_client_description_changed(self, widget):
        self.current_client.description = widget.get_text()

    def on_entry_application_changed(self, widget):
        self.current_client.rule_re_application = re.compile(widget.get_text(), re.IGNORECASE)

    def on_entry_command_changed(self, widget):
        self.current_client.rule_re_command = re.compile(widget.get_text(), re.IGNORECASE)
    
    def on_entry_window_title_changed(self, widget):
        self.current_client.rule_re_window_title = re.compile(widget.get_text(), re.IGNORECASE)        

    def on_combobox_profile_changed(self, widget):
        for key in self.vals.keys():
            if self.vals[key] == self.combobox_profile.get_active():
                self.current_client.category = key
                self.core.save()

    def on_vscale_volume_change_value(self, widget, a, b):
        self.current_client.volume_default = self.vscale_volume.get_value()
        
    def on_vscale_mute_change_value(self, widget, a, b):
        self.current_client.volume_mute = self.vscale_mute.get_value()

    def update_label(self, cvh, model, iter):
        text = cvh.name
        if cvh.description:
            text = cvh.description
        model.set_value(iter,1, text)
        
    def on_entry_pulse_client_description_changed(self, widget):       
        model, iter =  self.treeview_pulse_clients.get_selection().get_selected()
        cvh = model.get_value(iter, 5) 
        #cvh.description = self.entry_pulse_client_description.get_text()
        self.update_label(cvh, model, iter)
        
    def on_comboboxentry_window_match_changed(self, widget):
        model, iter =  self.treeview_pulse_clients.get_selection().get_selected()
        cvh = model.get_value(iter, 5) 
        cvh.window_name_rule = self.comboboxentry_window_match.get_text()
        
    def on_treeview_pulse_clients_cursor_changed(self, widget):
        model, iter =  self.treeview_pulse_clients.get_selection().get_selected()
        if not iter: return
        self.selected_client = model.get_value(iter, 5)
        self.__update_detail( self.selected_client)
    
    def on_checkbutton_channel_window_toggled(self, widget):
        self.current_client.apply_volume_meter_hack = self.checkbutton_channel_window.get_active()

    def __update_detail(self, client):
        self.current_client = client


    def on_close_button_clicked(self,widget=None):
        self.stop()
        

    def __get_title(self, client):
        text = client.name
        if client.description:
            text = client.description
        return text

    def update_treeview(self):
        for client in self.core.pa_clients.values():
            client.iter = None

        self.store = gtk.ListStore(gtk.gdk.Pixbuf, str, str, bool, int, object)
        self.treeview_pulse_clients.set_model(self.store) 

        icon_theme = gtk.icon_theme_get_default()
        icon = icon_theme.lookup_icon("audio-volume-medium", 32, 0).load_icon()
        for client in self.core.pa_clients.values():
            if client.category and not (client.name in self.core.ignore):
                if client.is_active() or self.combobox_view.get_active() == 1:
                    client.iter = self.store.append(([client.icon or icon, self.__get_title(client), self.core.display[client.category], client.apply_volume_meter_hack, 50, client])) 

        self.store.set_sort_column_id(1, gtk.SORT_ASCENDING)  

    def update_client(self, client):

        # load saved icon
        if not client.icon and client.icon_name:
            print "load client icon", client.icon_name
            icon_theme = gtk.icon_theme_get_default()
            try:
                client.icon = icon_theme.load_icon(client.icon_name, 32, 0)
            except:
                client.icon = icon_theme.load_icon("audio-volume-medium", 32, 0)

        if client.iter:
            if client.is_active():
                self.store.set(client.iter,
                    0, client.icon,
                    1,  self.__get_title(client),
                    4, client.get_volume()
                )
                if client.category in self.core.display.keys():
                    self.store.set(client.iter,
                        2,  self.core.display[client.category]
                    )
            else:
                pass
                # This needs to be on a timer
                #self.store.remove(client.iter)
                #client.iter = None
        else:
            if client.has_rule() and not client.name in self.core.ignore:
                icon_theme = gtk.icon_theme_get_default()
                icon = icon_theme.lookup_icon("audio-volume-medium", 32, 0).load_icon()
                client.iter = self.store.append(([client.icon or icon, self.__get_title(client), self.core.display[client.category], client.apply_volume_meter_hack, client.get_volume(), client])) 

        self.store.set_sort_column_id(1,gtk.SORT_ASCENDING)

    def run(self):
        self.window.show()  
        self.hscale_mute_level.set_value(self.core.mute_level)
        self.hscale_fade.set_value(self.core.fade_timer_speed)
        self.checkbutton_tray.set_active( self.core.tray.get_visible() )
        self.checkbutton_output.set_active( self.core.follow_new_outputs )
        self.window.present()
        return self.return_value

    def stop(self):
        self.core.save()
        self.core.close_preferances()
        self.window.destroy()
    
    @threaded
    def remove_client_on_timer(self, client):
        #time.sleep(60)
        #gobject.idle_add(self.remove_client, client) 
        return
    
    def remove_client(self, client):
        if not client.is_active() and client.iter :
            self.store.remove(client.iter)
            client.iter = None






Generated by  Doxygen 1.6.0   Back to index