#!/usr/bin/python
#
#  Copyright Andrew Hunter, Luis de Bethencourt Guimera 2008
#
#    This program is free software; you may 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/>.

#Error message dialoge lifted from Terminator. http://launchpad.net/terminator
try:
  import gtk, changesettings, meminfo_total, sys, os, cPickle
  from gtk import glade
except:
  import_error = gtk.MessageDialog (None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, ('You need to install python bindings for gtk and/or glade ("python-gtk2 & python-glade2" in debian/ubuntu)'))
  import_error.run()
  sys.exit(1)

class Uscontrols:
  def __init__(self):
    #Set the Glade file
    self.gladefile = "/usr/share/ubuntustudio-controls/gui.glade" #Remove /usr/share/ubuntustudio-controls/ to run from src dir
    self.wTree = gtk.glade.XML(self.gladefile)

    #Get the Main Window, and connect the "destroy" event
    self.window = self.wTree.get_widget("mainWindow")
    self.aboutWidget = self.wTree.get_widget("about")
    self.raw1394Warning = self.wTree.get_widget("raw_dialog")

    #Create our dictionay and connect it
    dic = { "on_closeButton_clicked" : self.closeButton_clicked,
      "on_mainWindow_destroy" : gtk.main_quit,
      "on_about_button_clicked" : self.about,
      "on_apply_button_clicked" : self.apply_settings,
      "on_memlock_spinbutton_value_changed" : self.update_memlock_amount,
      "on_memlock_checkButton_toggled" : self.set_memlock_enable,
      "on_raw1394_checkbutton_toggled" : self.show_raw1394_warning,}
    self.wTree.signal_autoconnect(dic)

  #Determine how much memory is on the system
  memtotal = meminfo_total.meminfo_total()

  #Subclass ChangeSettings so that it reverts instead of removes
  class ChangeRaw1394(changesettings.ChangeSettings):
    def rm_setting(self):
      self.line_check = self.regex_search()
      if self.line_check:
        print 'Match found, returning to \"disk\"'
        self.newlines = [self.regex.sub('KERNEL==\"raw1394\",\t\t\tGROUP=\"disk\"', item) for item in self._open_file()]
        self._seek_write(self.newlines)
  
  #For each setting to change, create an instance
  memlock = changesettings.ChangeSettings("/etc/security/limits.conf", "@audio - memlock (\d*)", "")
  raw1394 = ChangeRaw1394("/etc/udev/rules.d/40-permissions.rules", "KERNEL==\"raw1394\",\s*GROUP=\".*\"", "KERNEL==\"raw1394\",\t\t\tGROUP=\"video\"")

  def closeButton_clicked(self, widget):
    gtk.main_quit()

  def about(self, widget):
    print 'showing widget'
    self.aboutWidget.run()
    self.aboutWidget.hide()

  def apply_settings(self, apply_button):
    #Get all the widgets and add those widgets to a diction in the format {widget : self.instance}
    self.active_settings = {self.wTree.get_widget('memlock_checkButton') : self.memlock, self.wTree.get_widget('raw1394_checkbutton') : self.raw1394}
    #Apply those settings
    for widget, instanceName in self.active_settings.items():
      if widget.get_active():
        print 'Applying settings'
        instanceName.ch_setting()
        apply_button.set_sensitive(False)
        print instanceName.line_replacement
      elif not widget.get_active():
        print 'Removing settings'
        instanceName.rm_setting()

  def update_memlock_amount(self, spin_object):   
    #Check to make sure that the value entered is an interger, then convert it to a string
    memlock_entry_amount = str(int(self.memtotal*(spin_object.get_value()/100)))
    self.memlock.line_replacement = "@audio - memlock " + memlock_entry_amount
    print self.memlock.line_replacement
    apply_button = self.wTree.get_widget('apply_button')
    apply_button.set_sensitive(True)

  def set_memlock_enable(self, memlock_checkButton):
    self.memlock_enabled = memlock_checkButton.get_active()
    memlock_spinbutton = self.wTree.get_widget('memlock_spinbutton')
    memlock_spinbutton.set_sensitive(memlock_checkButton.get_active())
    print self.memlock_enabled

  def show_raw1394_warning(self, toggled_button):
    if toggled_button.get_active():
      print 'Showing warning'
      self.raw1394Warning.run()
      self.raw1394Warning.hide()
      apply_button = self.wTree.get_widget('apply_button')
      apply_button.set_sensitive(True)

    else:
      print 'Not showing warning'
      pass

  def serialze_settings(self):
    self.settings_value = {}
    self.settings_value['memlock'] = { 'memlock_checkButton' : self.wTree.get_widget('memlock_checkButton').get_active(), 'memlock_spinbutton' : self.wTree.get_widget('memlock_spinbutton').get_value() }
    self.settings_value['raw1394'] = { 'raw1394_checkbutton' : self.wTree.get_widget('raw1394_checkbutton').get_active() } 
    us_config = open(os.path.expanduser('~/.us-controls'), 'w')
    cPickle.dump(self.settings_value, us_config)
    us_config.close()

  def load_settings(self):
    us_config = open(os.path.expanduser('~/.us-controls'), 'r')
    self.settings_value = cPickle.load(us_config)
    for key, value in self.settings_value.items():
      for widget, value in value.items():
        try:
          self.wTree.get_widget(widget).set_value(value)
        except:
          self.wTree.get_widget(widget).set_active(value)
    us_config.close()

print __name__
if __name__ == "__main__":
  #Make sure two instances are not running!
  if not os.path.exists('/var/lock/ubuntustudio-controls'):
    lockFile = open('/var/lock/ubuntustudio-controls', 'w')
  else:
    lock_error = gtk.MessageDialog (None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, ('Only one instance of Ubuntu Studio Controls can be run at a time'))
    lock_error.run()
    sys.exit(1)
 
  # Bring up error if not root.
  if not os.geteuid()==0:  
    root_error = gtk.MessageDialog (None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, ('You need to have admistrator privilages to run Ubuntu Studio Controls'))
    root_error.run()
    sys.exit(1)

  else:
    uscontrols = Uscontrols()
    try:
      uscontrols.load_settings()
    except IOError:
      pass
    gtk.main()
    uscontrols.serialze_settings()
    os.remove('/var/lock/ubuntustudio-controls')
