class AppMenu: def __init__(self, app, tray, widget, conf, build_icons): self.menu = QtGui.QMenu(widget) tray.setContextMenu(self.menu) self.conf = conf self.app = app self.build_icons = build_icons self.create_default_menu_items() def update(self, projects): projects.sort(key=self.sort_key) self.menu.clear() for project in projects: self.create_menu_item(project.name, self.build_icons.for_status(project.get_build_status()), project.url, project.get_last_build_time(), project.server_url) self.create_default_menu_items() def sort_key(self, p): if self.conf.get_sort_by_name(): return p.name return p.get_last_build_time() def create_default_menu_items(self): self.menu.addSeparator() self.menu.addAction(QtGui.QAction("About", self.menu, triggered=self.about_clicked)) self.menu.addAction(QtGui.QAction("Preferences", self.menu, triggered=self.preferences_clicked)) self.menu.addAction(QtGui.QAction("Exit", self.menu, triggered=self.exit)) def about_clicked(self, widget): QtGui.QMessageBox.about(self.menu, "About BuildNotify %s" % VERSION, "<b>BuildNotify %s</b> has been developed using PyQt4 and serves as a build notification tool for cruise control. In case of any suggestions/bugs," % VERSION + "please visit <a href=\"http://bitbucket.org/Anay/buildnotify\">http://bitbucket.org/Anay/buildnotify</a> and provide your feedback.") def preferences_clicked(self, widget): self.preferences_dialog = PreferencesDialog(self.conf, self.menu) if self.preferences_dialog.exec_() == QtGui.QDialog.Accepted: self.preferences_dialog.save() self.app.emit(QtCore.SIGNAL('reload_project_data')) def exit(self, widget): sys.exit() def create_menu_item(self, label, icon, url, last_build_time, server_url): menu_item_label = label if self.conf.get_value("lastBuildTimeForProject"): menu_item_label = label + ", " + DistanceOfTime(last_build_time, self.conf.get_project_timezone(url, server_url)).age() + " ago" action = self.menu.addAction(icon, menu_item_label) action.setIconVisibleInMenu(True) receiver = lambda url=url: self.open_url(self, url) QtCore.QObject.connect(action, QtCore.SIGNAL('triggered()'), receiver) def open_url(self, something, url): webbrowser.open(url)
def editPreferences(self, *ignored_arguments): """Show the preferences dialog.""" pref_dialog = PreferencesDialog(self, self.prefs) pref_dialog.show_all() response = pref_dialog.run() if response == gtk.RESPONSE_OK: pref_dialog.apply(self.prefs) pref_dialog.hide()
def __init__(self): self.pdialog = PreferencesDialog() self.pdialog.signals.settingsChanged.connect(self.initializeApi) self.signals = self.Signals() self.updateTimer = QTimer(); QObject.connect(self.updateTimer, SIGNAL("timeout()"), self.getFileList) self.initializeApi()
def preferences(self): try: PreferencesDialog(self.root) except ExceptionHandler.ExceptionType as e: ExceptionHandler.add(e)
class WordNotify_Window(QtGui.QMainWindow, Ui_MainWindow): def __init__(self): QtGui.QMainWindow.__init__(self) self.setupUi(self) # UI init self.initPreferences() # prefs init self.initDictList() # dicts init self.initSysTray() # sys tray init self.sysTray.show() # sys tray is visible self.connect(self.dictListView, QtCore.SIGNAL('clicked(QModelIndex)'), self.selectDict) self.connect(self.dictListView, QtCore.SIGNAL('doubleClicked(QModelIndex)'), self.editDict) self.connect(self.stopPushButton, QtCore.SIGNAL('clicked()'), self.stopClicked) self.connect(self.startPushButton, QtCore.SIGNAL('clicked()'), self.startClicked) self.connect(self.optionsPushButton, QtCore.SIGNAL('clicked()'), self.optionsClicked) self.connect(self.dictNewPushButton, QtCore.SIGNAL('clicked()'), self.newDict) self.connect(self.dictAddPushButton, QtCore.SIGNAL('clicked()'), self.addDict) self.connect(self.dictEditPushButton, QtCore.SIGNAL('clicked()'), self.editDict) self.connect(self.dictRemovePushButton, QtCore.SIGNAL('clicked()'), self.removeDict) self.connect(self.actionAbout, QtCore.SIGNAL('triggered()'), self.about) self.connect(self.actionAbout_Qt, QtCore.SIGNAL('triggered()'), self.aboutQt) self.connect(self.actionQuit, QtCore.SIGNAL('triggered()'), self.quit) self.connect(self.actionStart, QtCore.SIGNAL('triggered()'), self.startClicked) self.connect(self.actionStop, QtCore.SIGNAL('triggered()'), self.stopClicked) self.connect(self.actionShowHide, QtCore.SIGNAL('triggered()'), self.show_hideTriggered) self.connect(self.actionNew, QtCore.SIGNAL('triggered()'), self.newDict) self.connect(self.actionAdd, QtCore.SIGNAL('triggered()'), self.addDict) self.connect(self.actionEdit, QtCore.SIGNAL('triggered()'), self.editDict) self.connect(self.actionRemove, QtCore.SIGNAL('triggered()'), self.removeDict) self.connect(self.actionPreferences, QtCore.SIGNAL('triggered()'), self.optionsClicked) def initPreferences(self): self.preferences = QtCore.QSettings("preferences.cfg", QtCore.QSettings.IniFormat) # reading cfg ini file self.preferences.setIniCodec('UTF-8') def initSysTray(self): self.sysTray = QtGui.QSystemTrayIcon() # creating sys tray iconPath = os.path.join(os.getcwd(), "icon.png") # unicoded icon path iconPath = iconPath.decode('utf-8') # unicoded icon path self.sysTray.setIcon(QtGui.QIcon(iconPath)) # setting icon rightClickMenu = QtGui.QMenu() # creating menu rightClickMenu.addAction(self.actionStart) # adding actions to menu rightClickMenu.addAction(self.actionStop) # adding actions to menu rightClickMenu.addSeparator() # adding separator rightClickMenu.addAction(self.actionShowHide) # adding actions to menu rightClickMenu.addSeparator() # adding separator rightClickMenu.addAction(self.actionAbout) # adding actions to menu rightClickMenu.addAction(self.actionAbout_Qt) # adding actions to menu rightClickMenu.addSeparator() # separator self.actionQuit.setIcon(QtGui.QIcon("icons/exit.png")) rightClickMenu.addAction(self.actionQuit) # adding actions to menu self.sysTray.setContextMenu(rightClickMenu) # setting menu for systray self.sysTray.activated.connect(self.click_trap) # signal for icon left click def click_trap(self, value): if value == self.sysTray.Trigger: # left click! self.show_hideTriggered() # invoking show/hide event def show_hideTriggered(self): if self.isHidden(): # check if MainWindow is hidden self.show() # if True then Show else: self.hide() # else Hide def initDictList(self): dictsPath = os.path.join(os.getcwd(), "dicts") # setting path with current path + dicts dictsPath = dictsPath.decode('utf-8') self.model = QtGui.QFileSystemModel() # creating FS model self.modelIndex = QtCore.QModelIndex() # creating model index self.model.setRootPath(dictsPath) # setting path for model self.modelIndex = self.model.index(dictsPath) # getting model index self.dictListView.setModel(self.model) # setting model for ListView self.dictListView.setRootIndex(self.modelIndex) # setting index for ListView currentIndex = self.preferences.value("dict") # reading index from cfg currentIndex = currentIndex.toString() # translation to QString self.dictListView.setAutoScroll(True) # autoscrolling self.dictListView.setCurrentIndex(self.model.index(currentIndex)) # setting index self.dictListView.scrollTo(self.model.index(currentIndex)) # scroll to current index def selectDict(self): currentIndex = self.dictListView.currentIndex() # getting current index filePath = self.model.filePath(currentIndex) # getting file path from index self.debug("%d %s" % (currentIndex.row(), filePath)) # debug info current row & file path self.preferences.setValue("index", currentIndex.row()) # saving row to cfg self.preferences.setValue("dict", filePath) # saving file path to cfg self.preferences.sync() # updating cfg file def newDict(self): selectDialog = QtGui.QFileDialog() newDictPath = selectDialog.getSaveFileName(self, self.tr('Name of new dict...'), 'dicts', 'TXT Files (*.txt)') if newDictPath != "": self.editorForm = EditorForm() self.editorForm.filePathLabel.setText(newDictPath) self.editorForm.show() # QtGui.QMessageBox.information(self, "CREATED", newDictPath + "\nHas been created!") def addDict(self): selectDialog = QtGui.QFileDialog() addDictPath = selectDialog.getOpenFileName(self, self.tr('Select dict...'), '', 'TXT Files (*.txt)') if addDictPath != "": addDictPath = str(addDictPath.toUtf8()) addDictPath = addDictPath.decode('utf-8') shutil.copy(os.path.abspath(addDictPath), "dicts") QtGui.QMessageBox.information(self, self.tr("ADDED"), addDictPath + self.tr("\nHas been added to \'dicts\' directory!")) def editDict(self): filePath = self.preferences.value("dict") filePath = filePath.toString() filePath = str(filePath.toUtf8()) filePath = filePath.decode('utf-8') f = open(filePath, 'r') data = f.read() f.close() data = QtCore.QString.fromUtf8(data) self.editorForm = EditorForm() self.editorForm.plainTextEdit.setPlainText(data) self.editorForm.filePathLabel.setText(filePath) self.editorForm.show() def removeDict(self): filePath = self.preferences.value("dict") filePath = filePath.toString() reply = QtGui.QMessageBox.question(self, self.tr("DELETION"), self.tr("Really delete?\n") + filePath, QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: filePath = str(filePath.toUtf8()) filePath = filePath.decode('utf-8') os.remove(os.path.abspath(filePath)) QtGui.QMessageBox.information(self, self.tr("DELETED"), filePath + self.tr("\nHas been deleted!")) def initTimer(self): self.timer = QtCore.QTimer() self.timer.start(self.delay) self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.timerUpdate) def timerUpdate(self): dictSize = len(self.myDict) #random.shuffle(self.myList) randNumber = random.randrange(1, dictSize) randLine = self.myDict[randNumber] #self.debug("%d %s" % (randnumber, randline.rstrip())) if (len(randLine) < 3): head, body, extra = randLine[0], randLine[1], '' else: head, body, extra = randLine[0], randLine[1], randLine[2] self.debug("[%d/%d] %s ― %s ― %s" % (randNumber, dictSize, head, body, extra)) head = QtCore.QString.fromUtf8(head) body = body + "\n" + extra body = body.rstrip() #extra = QtCore.QString.fromUtf8(extra) body = QtCore.QString.fromUtf8(body) if self.notifyd == True: #head = str(head) #body = str(body) head = unicode(head) body = unicode(body) body = "<b><i>" + body + "</i></b>" iconPath = os.path.join(os.getcwd(), "icon.png") # unicoded icon path iconPath = iconPath.decode('utf-8') self.showNotifyd(head, body, iconPath, self.timeout) elif self.notifyd == False: self.sysTray.showMessage(head, body, self.noicon, self.timeout) else: QtGui.QMessageBox.information(self, self.tr("ERROR"), self.tr("Unexpected error occurred!")) self.debug("Unexpected error occurred!") def showNotifyd(self, head, body, icon, timeout): #msg = pynotify.Notification(head, body, icon) #msg.set_timeout(timeout) #msg.show() ncmd = "notify-send" subprocess.call([ncmd, "-t", str(timeout), "-i", icon, head, body]) def startClicked(self): #self.hide() filePath = self.preferences.value("dict").toString() self.timeout = self.preferences.value("timeout").toInt()[0]*1000 self.delay = self.preferences.value("delay").toInt()[0]*1000 if self.preferences.value("notifyd").toString() == "true": self.notifyd = True #global pynotify #import pynotify #pynotify.init("init") else: self.notifyd = False self.icon = QtGui.QSystemTrayIcon.Information self.noicon = QtGui.QSystemTrayIcon.NoIcon self.myDict = {} self.myIndex = 0 filePath = str(filePath.toUtf8()) filePath = filePath.decode('utf-8') with open(filePath, 'rb') as f: reader = csv.reader(f, delimiter=':', quoting=csv.QUOTE_NONE) for line in reader: self.myIndex += 1 self.myDict[self.myIndex] = line f.close() #random.shuffle(self.myList) self.initTimer() self.sysTray.showMessage("qWordNotify", self.tr("Timer started!"), self.icon, 1000) self.debug("Timer started!") def stopClicked(self): self.timer.stop() self.sysTray.showMessage("qWordNotify", self.tr("Timer stopped!"), self.icon, 1000) self.debug("Timer stopped!") def optionsClicked(self): self.prefDialog = PreferencesDialog() self.prefDialog.setModal(True) self.prefDialog.show() def about(self): QtGui.QMessageBox.information(self, self.tr("About qWordNotify"), "<b>qWordNotify 0.1</b><br>(c) 2014 Anonymous") def aboutQt(self): QtGui.QApplication.aboutQt() def closeEvent(self,event): reply=QtGui.QMessageBox.question(self, self.tr("QUITTING"), self.tr("Are you sure to quit?"), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) if reply==QtGui.QMessageBox.Yes: self.preferences.sync() event.accept() else: event.ignore() def quit(self): QtGui.qApp.quit() def debug(self, msg): print "DEBUG:", msg def tr(self, text): return QtCore.QCoreApplication.translate("WordNotify_Window", text)
def on_preferences_clicked(self, widget): dialog = PreferencesDialog() dialog.dialog.set_transient_for(widget.get_toplevel()) dialog.run() dialog.destroy()
def __init__(self): self.pdialog = PreferencesDialog() self.pdialog.signals.settingsChanged.connect(self.initializeApi) self.signals = self.Signals() self.initializeApi()
class CloudHandle(object): fileList = [] def __init__(self): self.pdialog = PreferencesDialog() self.pdialog.signals.settingsChanged.connect(self.initializeApi) self.signals = self.Signals() self.initializeApi() def initializeApi(self): self.connected = False try: username = self.pdialog.settings['username'] password = self.pdialog.settings['password'] if username == '' or password == '': raise ValueError('Empty password or username') self.api = CloudApi(username, password) self.getFileList() except (KeyError, ValueError): self.pdialog.show() print "Error reading settings" def getFileList(self): self.api.getFileList(self.pdialog.settings['list_size'], self.gotFileList) def gotFileList(self, l): self.connected = True self.fileList = l self.signals.gotFileList.emit(l) def addItem(self, url): url = str(url) if urlparse.urlparse(url).scheme == "file": self.api.uploadFile(url, self.itemAdded) else: self.api.bookmark(url, self.itemAdded) self.signals.uploadStarted.emit() def itemAdded(self, item): self.fileList.insert(0, item) self.fileList.pop() self.signals.gotFileList.emit(self.fileList) if self.pdialog.settings['auto_clipboard']: self.signals.loadClipboard.emit(item['url']) if self.pdialog.settings['notifications']: if item['item_type'] == 'bookmark': self.notify('Bookmarked - ' + item['name'], item['url']) else: self.notify('File Uploaded - ' + item['name'], item['url']) self.signals.uploadFinished.emit() def deleteItem(self, url): url = str(url) self.api.delete(url, self.deleted) def deleted(self, x): self.getFileList() if self.pdialog.settings['notifications']: self.notify("Deleted - " + x['name'], 'This item was removed from your CloudApp') def showPreferences(self): self.pdialog.show() def notify(self, title, text, icon=None): try: import pynotify if pynotify.init("Cloud App"): n = pynotify.Notification(title, text) n.set_timeout(5) n.show() else: print "there was a problem initializing the pynotify module" except: print "you don't seem to have pynotify installed" class Signals(QObject): gotFileList = pyqtSignal(list) loadClipboard = pyqtSignal(str) uploadStarted = pyqtSignal() uploadFinished = pyqtSignal()
class JackMixer(SerializedObject): # scales suitable as meter scales meter_scales = [ scale.K20(), scale.K14(), scale.IEC268(), scale.Linear70dB(), scale.IEC268Minimalistic() ] # scales suitable as volume slider scales slider_scales = [scale.Linear30dB(), scale.Linear70dB()] # name of settings file that is currently open current_filename = None _init_solo_channels = None def __init__(self, client_name='jack_mixer'): self.visible = False self.nsm_client = None if os.environ.get('NSM_URL'): self.nsm_client = NSMClient( prettyName="jack_mixer", saveCallback=self.nsm_save_cb, openOrNewCallback=self.nsm_open_cb, supportsSaveStatus=False, hideGUICallback=self.nsm_hide_cb, showGUICallback=self.nsm_show_cb, exitProgramCallback=self.nsm_exit_cb, loggingLevel="error", ) self.nsm_client.announceGuiVisibility(self.visible) else: self.visible = True self.create_mixer(client_name, with_nsm=False) def create_mixer(self, client_name, with_nsm=True): self.mixer = jack_mixer_c.Mixer(client_name) if not self.mixer: raise RuntimeError("Failed to create Mixer instance.") self.create_ui(with_nsm) self.window.set_title(client_name) self.monitor_channel = self.mixer.add_output_channel( "Monitor", True, True) self.save = False GLib.timeout_add(33, self.read_meters) GLib.timeout_add(50, self.midi_events_check) if with_nsm: GLib.timeout_add(200, self.nsm_react) def new_menu_item(self, title, callback=None, accel=None, enabled=True): menuitem = Gtk.MenuItem.new_with_mnemonic(title) menuitem.set_sensitive(enabled) if callback: menuitem.connect("activate", callback) if accel: key, mod = Gtk.accelerator_parse(accel) menuitem.add_accelerator("activate", self.menu_accelgroup, key, mod, Gtk.AccelFlags.VISIBLE) return menuitem def create_ui(self, with_nsm): self.channels = [] self.output_channels = [] self.window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL) self.window.set_icon_name('jack_mixer') self.gui_factory = gui.Factory(self.window, self.meter_scales, self.slider_scales) self.gui_factory.connect('midi-behavior-mode-changed', self.on_midi_behavior_mode_changed) self.gui_factory.emit_midi_behavior_mode() self.vbox_top = Gtk.VBox() self.window.add(self.vbox_top) self.menu_accelgroup = Gtk.AccelGroup() self.window.add_accel_group(self.menu_accelgroup) self.menubar = Gtk.MenuBar() self.vbox_top.pack_start(self.menubar, False, True, 0) mixer_menu_item = Gtk.MenuItem.new_with_mnemonic("_Mixer") self.menubar.append(mixer_menu_item) edit_menu_item = Gtk.MenuItem.new_with_mnemonic('_Edit') self.menubar.append(edit_menu_item) help_menu_item = Gtk.MenuItem.new_with_mnemonic('_Help') self.menubar.append(help_menu_item) self.width = 420 self.height = 420 self.paned_position = 210 self.window.set_default_size(self.width, self.height) self.mixer_menu = Gtk.Menu() mixer_menu_item.set_submenu(self.mixer_menu) self.mixer_menu.append( self.new_menu_item('New _Input Channel', self.on_add_input_channel, "<Control>N")) self.mixer_menu.append( self.new_menu_item('New Output _Channel', self.on_add_output_channel, "<Shift><Control>N")) self.mixer_menu.append(Gtk.SeparatorMenuItem()) if not with_nsm: self.mixer_menu.append( self.new_menu_item('_Open...', self.on_open_cb, "<Control>O")) self.mixer_menu.append( self.new_menu_item('_Save', self.on_save_cb, "<Control>S")) if not with_nsm: self.mixer_menu.append( self.new_menu_item('Save _As...', self.on_save_as_cb, "<Shift><Control>S")) self.mixer_menu.append(Gtk.SeparatorMenuItem()) if with_nsm: self.mixer_menu.append( self.new_menu_item('_Hide', self.nsm_hide_cb, "<Control>W")) else: self.mixer_menu.append( self.new_menu_item('_Quit', self.on_quit_cb, "<Control>Q")) edit_menu = Gtk.Menu() edit_menu_item.set_submenu(edit_menu) self.channel_edit_input_menu_item = self.new_menu_item( '_Edit Input Channel', enabled=False) edit_menu.append(self.channel_edit_input_menu_item) self.channel_edit_input_menu = Gtk.Menu() self.channel_edit_input_menu_item.set_submenu( self.channel_edit_input_menu) self.channel_edit_output_menu_item = self.new_menu_item( 'E_dit Output Channel', enabled=False) edit_menu.append(self.channel_edit_output_menu_item) self.channel_edit_output_menu = Gtk.Menu() self.channel_edit_output_menu_item.set_submenu( self.channel_edit_output_menu) self.channel_remove_input_menu_item = self.new_menu_item( '_Remove Input Channel', enabled=False) edit_menu.append(self.channel_remove_input_menu_item) self.channel_remove_input_menu = Gtk.Menu() self.channel_remove_input_menu_item.set_submenu( self.channel_remove_input_menu) self.channel_remove_output_menu_item = self.new_menu_item( 'Re_move Output Channel', enabled=False) edit_menu.append(self.channel_remove_output_menu_item) self.channel_remove_output_menu = Gtk.Menu() self.channel_remove_output_menu_item.set_submenu( self.channel_remove_output_menu) edit_menu.append(Gtk.SeparatorMenuItem()) edit_menu.append( self.new_menu_item('Shrink Input Channels', self.on_narrow_input_channels_cb, "<Control>minus")) edit_menu.append( self.new_menu_item('Expand Input Channels', self.on_widen_input_channels_cb, "<Control>plus")) edit_menu.append(Gtk.SeparatorMenuItem()) edit_menu.append( self.new_menu_item('_Clear', self.on_channels_clear, "<Control>X")) edit_menu.append(Gtk.SeparatorMenuItem()) edit_menu.append( self.new_menu_item('_Preferences', self.on_preferences_cb, "<Control>P")) help_menu = Gtk.Menu() help_menu_item.set_submenu(help_menu) help_menu.append(self.new_menu_item('_About', self.on_about, "F1")) self.hbox_top = Gtk.HBox() self.vbox_top.pack_start(self.hbox_top, True, True, 0) self.scrolled_window = Gtk.ScrolledWindow() self.scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.hbox_inputs = Gtk.Box() self.hbox_inputs.set_spacing(0) self.hbox_inputs.set_border_width(0) self.hbox_top.set_spacing(0) self.hbox_top.set_border_width(0) self.scrolled_window.add(self.hbox_inputs) self.hbox_outputs = Gtk.Box() self.hbox_outputs.set_spacing(0) self.hbox_outputs.set_border_width(0) self.scrolled_output = Gtk.ScrolledWindow() self.scrolled_output.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.scrolled_output.add(self.hbox_outputs) self.paned = Gtk.HPaned() self.paned.set_wide_handle(True) self.hbox_top.pack_start(self.paned, True, True, 0) self.paned.pack1(self.scrolled_window, True, False) self.paned.pack2(self.scrolled_output, True, False) self.window.connect("destroy", Gtk.main_quit) self.window.connect('delete-event', self.on_delete_event) def nsm_react(self): self.nsm_client.reactToMessage() return True def nsm_hide_cb(self, *args): self.window.hide() self.visible = False self.nsm_client.announceGuiVisibility(False) def nsm_show_cb(self): width, height = self.window.get_size() self.window.show_all() self.paned.set_position(self.paned_position / self.width * width) self.visible = True self.nsm_client.announceGuiVisibility(True) def nsm_open_cb(self, path, session_name, client_name): self.create_mixer(client_name, with_nsm=True) self.current_filename = path + '.xml' if os.path.isfile(self.current_filename): f = open(self.current_filename, 'r') self.load_from_xml(f, from_nsm=True) f.close() else: f = open(self.current_filename, 'w') f.close() def nsm_save_cb(self, path, session_name, client_name): self.current_filename = path + '.xml' f = open(self.current_filename, 'w') self.save_to_xml(f) f.close() def nsm_exit_cb(self, path, session_name, client_name): Gtk.main_quit() def on_midi_behavior_mode_changed(self, gui_factory, value): self.mixer.midi_behavior_mode = value def on_delete_event(self, widget, event): if self.nsm_client: self.nsm_hide_cb() return True return self.on_quit_cb() def sighandler(self, signum, frame): log.debug("Signal %d received.", signum) if signum == signal.SIGUSR1: self.save = True elif signum == signal.SIGTERM: self.on_quit_cb() elif signum == signal.SIGINT: self.on_quit_cb() else: log.warning("Unknown signal %d received.", signum) def cleanup(self): log.debug("Cleaning jack_mixer.") if not self.mixer: return for channel in self.channels: channel.unrealize() self.mixer.destroy() def on_open_cb(self, *args): dlg = Gtk.FileChooserDialog(title='Open', parent=self.window, action=Gtk.FileChooserAction.OPEN) dlg.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK) dlg.set_default_response(Gtk.ResponseType.OK) if dlg.run() == Gtk.ResponseType.OK: filename = dlg.get_filename() try: f = open(filename, 'r') self.load_from_xml(f) except Exception as e: error_dialog(self.window, "Failed loading settings (%s)", e) else: self.current_filename = filename finally: f.close() dlg.destroy() def on_save_cb(self, *args): if not self.current_filename: return self.on_save_as_cb() f = open(self.current_filename, 'w') self.save_to_xml(f) f.close() def on_save_as_cb(self, *args): dlg = Gtk.FileChooserDialog(title='Save', parent=self.window, action=Gtk.FileChooserAction.SAVE) dlg.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.OK) dlg.set_default_response(Gtk.ResponseType.OK) if dlg.run() == Gtk.ResponseType.OK: self.current_filename = dlg.get_filename() self.on_save_cb() dlg.destroy() def on_quit_cb(self, *args): if not self.nsm_client and self.gui_factory.get_confirm_quit(): dlg = Gtk.MessageDialog(parent=self.window, message_type=Gtk.MessageType.QUESTION, buttons=Gtk.ButtonsType.NONE) dlg.set_markup("<b>Quit application?</b>") dlg.format_secondary_markup( "All jack_mixer ports will be closed and connections lost," "\nstopping all sound going through jack_mixer.\n\n" "Are you sure?") dlg.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_QUIT, Gtk.ResponseType.OK) response = dlg.run() dlg.destroy() if response != Gtk.ResponseType.OK: return True Gtk.main_quit() def on_narrow_input_channels_cb(self, widget): for channel in self.channels: channel.narrow() def on_widen_input_channels_cb(self, widget): for channel in self.channels: channel.widen() preferences_dialog = None def on_preferences_cb(self, widget): if not self.preferences_dialog: self.preferences_dialog = PreferencesDialog(self) self.preferences_dialog.show() self.preferences_dialog.present() def on_add_channel(self, inout="input", default_name="Input"): dialog = getattr(self, '_add_{}_dialog'.format(inout), None) values = getattr(self, '_add_{}_values'.format(inout), {}) if dialog == None: cls = NewInputChannelDialog if inout == 'input' else NewOutputChannelDialog dialog = cls(app=self) setattr(self, '_add_{}_dialog'.format(inout), dialog) names = { ch.channel_name for ch in ( self.channels if inout == 'input' else self.output_channels) } values.setdefault('name', default_name) while True: if values['name'] in names: values['name'] = add_number_suffix(values['name']) else: break dialog.fill_ui(**values) dialog.set_transient_for(self.window) dialog.show() ret = dialog.run() dialog.hide() if ret == Gtk.ResponseType.OK: result = dialog.get_result() setattr(self, '_add_{}_values'.format(inout), result) method = getattr( self, 'add_channel' if inout == 'input' else 'add_output_channel') channel = method(**result) if self.visible or self.nsm_client == None: self.window.show_all() def on_add_input_channel(self, widget): return self.on_add_channel("input", "Input") def on_add_output_channel(self, widget): return self.on_add_channel("output", "Output") def on_edit_input_channel(self, widget, channel): log.debug('Editing input channel "%s".', channel.channel_name) channel.on_channel_properties() def remove_channel_edit_input_menuitem_by_label(self, widget, label): if (widget.get_label() == label): self.channel_edit_input_menu.remove(widget) def on_remove_input_channel(self, widget, channel): log.debug('Removing input channel "%s".', channel.channel_name) self.channel_remove_input_menu.remove(widget) self.channel_edit_input_menu.foreach( self.remove_channel_edit_input_menuitem_by_label, channel.channel_name) if self.monitored_channel is channel: channel.monitor_button.set_active(False) for i in range(len(self.channels)): if self.channels[i] is channel: channel.unrealize() del self.channels[i] self.hbox_inputs.remove(channel.get_parent()) break if not self.channels: self.channel_edit_input_menu_item.set_sensitive(False) self.channel_remove_input_menu_item.set_sensitive(False) def on_edit_output_channel(self, widget, channel): log.debug('Editing output channel "%s".', channel.channel_name) channel.on_channel_properties() def remove_channel_edit_output_menuitem_by_label(self, widget, label): if (widget.get_label() == label): self.channel_edit_output_menu.remove(widget) def on_remove_output_channel(self, widget, channel): log.debug('Removing output channel "%s".', channel.channel_name) self.channel_remove_output_menu.remove(widget) self.channel_edit_output_menu.foreach( self.remove_channel_edit_output_menuitem_by_label, channel.channel_name) if self.monitored_channel is channel: channel.monitor_button.set_active(False) for i in range(len(self.channels)): if self.output_channels[i] is channel: channel.unrealize() del self.output_channels[i] self.hbox_outputs.remove(channel.get_parent()) break if not self.output_channels: self.channel_edit_output_menu_item.set_sensitive(False) self.channel_remove_output_menu_item.set_sensitive(False) def rename_channels(self, container, parameters): if (container.get_label() == parameters['oldname']): container.set_label(parameters['newname']) def on_channel_rename(self, oldname, newname): rename_parameters = {'oldname': oldname, 'newname': newname} self.channel_edit_input_menu.foreach(self.rename_channels, rename_parameters) self.channel_edit_output_menu.foreach(self.rename_channels, rename_parameters) self.channel_remove_input_menu.foreach(self.rename_channels, rename_parameters) self.channel_remove_output_menu.foreach(self.rename_channels, rename_parameters) log.debug('Renaming channel from "%s" to "%s".', oldname, newname) def on_channels_clear(self, widget): dlg = Gtk.MessageDialog( parent=self.window, modal=True, message_type=Gtk.MessageType.WARNING, text="Are you sure you want to clear all channels?", buttons=Gtk.ButtonsType.OK_CANCEL) if not widget or dlg.run() == Gtk.ResponseType.OK: for channel in self.output_channels: channel.unrealize() self.hbox_outputs.remove(channel.get_parent()) for channel in self.channels: channel.unrealize() self.hbox_inputs.remove(channel.get_parent()) self.channels = [] self.output_channels = [] self.channel_edit_input_menu = Gtk.Menu() self.channel_edit_input_menu_item.set_submenu( self.channel_edit_input_menu) self.channel_edit_input_menu_item.set_sensitive(False) self.channel_remove_input_menu = Gtk.Menu() self.channel_remove_input_menu_item.set_submenu( self.channel_remove_input_menu) self.channel_remove_input_menu_item.set_sensitive(False) self.channel_edit_output_menu = Gtk.Menu() self.channel_edit_output_menu_item.set_submenu( self.channel_edit_output_menu) self.channel_edit_output_menu_item.set_sensitive(False) self.channel_remove_output_menu = Gtk.Menu() self.channel_remove_output_menu_item.set_submenu( self.channel_remove_output_menu) self.channel_remove_output_menu_item.set_sensitive(False) dlg.destroy() def add_channel(self, name, stereo, volume_cc, balance_cc, mute_cc, solo_cc, value): try: channel = InputChannel(self, name, stereo, value) self.add_channel_precreated(channel) except Exception: error_dialog(self.window, "Channel creation failed.") return if volume_cc != -1: channel.channel.volume_midi_cc = volume_cc else: channel.channel.autoset_volume_midi_cc() if balance_cc != -1: channel.channel.balance_midi_cc = balance_cc else: channel.channel.autoset_balance_midi_cc() if mute_cc != -1: channel.channel.mute_midi_cc = mute_cc else: channel.channel.autoset_mute_midi_cc() if solo_cc != -1: channel.channel.solo_midi_cc = solo_cc else: channel.channel.autoset_solo_midi_cc() return channel def add_channel_precreated(self, channel): frame = Gtk.Frame() frame.add(channel) self.hbox_inputs.pack_start(frame, False, True, 0) channel.realize() channel_edit_menu_item = Gtk.MenuItem(label=channel.channel_name) self.channel_edit_input_menu.append(channel_edit_menu_item) channel_edit_menu_item.connect("activate", self.on_edit_input_channel, channel) self.channel_edit_input_menu_item.set_sensitive(True) channel_remove_menu_item = Gtk.MenuItem(label=channel.channel_name) self.channel_remove_input_menu.append(channel_remove_menu_item) channel_remove_menu_item.connect("activate", self.on_remove_input_channel, channel) self.channel_remove_input_menu_item.set_sensitive(True) self.channels.append(channel) for outputchannel in self.output_channels: channel.add_control_group(outputchannel) # create post fader output channel matching the input channel channel.post_fader_output_channel = self.mixer.add_output_channel( channel.channel.name + ' Out', channel.channel.is_stereo, True) channel.post_fader_output_channel.volume = 0 channel.post_fader_output_channel.set_solo(channel.channel, True) channel.connect('input-channel-order-changed', self.on_input_channel_order_changed) def on_input_channel_order_changed(self, widget, source_name, dest_name): self.channels.clear() channel_box = self.hbox_inputs frames = channel_box.get_children() for f in frames: c = f.get_child() if source_name == c._channel_name: source_frame = f break for f in frames: c = f.get_child() if (dest_name == c._channel_name): pos = frames.index(f) channel_box.reorder_child(source_frame, pos) break for frame in self.hbox_inputs.get_children(): c = frame.get_child() self.channels.append(c) def read_meters(self): for channel in self.channels: channel.read_meter() for channel in self.output_channels: channel.read_meter() return True def midi_events_check(self): for channel in self.channels + self.output_channels: channel.midi_events_check() return True def add_output_channel(self, name, stereo, volume_cc, balance_cc, mute_cc, display_solo_buttons, color, value): try: channel = OutputChannel(self, name, stereo, value) channel.display_solo_buttons = display_solo_buttons channel.color = color self.add_output_channel_precreated(channel) except Exception: error_dialog(self.window, "Channel creation failed") return if volume_cc != -1: channel.channel.volume_midi_cc = volume_cc else: channel.channel.autoset_volume_midi_cc() if balance_cc != -1: channel.channel.balance_midi_cc = balance_cc else: channel.channel.autoset_balance_midi_cc() if mute_cc != -1: channel.channel.mute_midi_cc = mute_cc else: channel.channel.autoset_mute_midi_cc() return channel def add_output_channel_precreated(self, channel): frame = Gtk.Frame() frame.add(channel) self.hbox_outputs.pack_end(frame, False, True, 0) self.hbox_outputs.reorder_child(frame, 0) channel.realize() channel_edit_menu_item = Gtk.MenuItem(label=channel.channel_name) self.channel_edit_output_menu.append(channel_edit_menu_item) channel_edit_menu_item.connect("activate", self.on_edit_output_channel, channel) self.channel_edit_output_menu_item.set_sensitive(True) channel_remove_menu_item = Gtk.MenuItem(label=channel.channel_name) self.channel_remove_output_menu.append(channel_remove_menu_item) channel_remove_menu_item.connect("activate", self.on_remove_output_channel, channel) self.channel_remove_output_menu_item.set_sensitive(True) self.output_channels.append(channel) channel.connect('output-channel-order-changed', self.on_output_channel_order_changed) def on_output_channel_order_changed(self, widget, source_name, dest_name): self.output_channels.clear() channel_box = self.hbox_outputs frames = channel_box.get_children() for f in frames: c = f.get_child() if source_name == c._channel_name: source_frame = f break for f in frames: c = f.get_child() if (dest_name == c._channel_name): pos = len(frames) - 1 - frames.index(f) channel_box.reorder_child(source_frame, pos) break for frame in self.hbox_outputs.get_children(): c = frame.get_child() self.output_channels.append(c) _monitored_channel = None def get_monitored_channel(self): return self._monitored_channel def set_monitored_channel(self, channel): if self._monitored_channel: if channel.channel.name == self._monitored_channel.channel.name: return self._monitored_channel = channel if type(channel) is InputChannel: # reset all solo/mute settings for in_channel in self.channels: self.monitor_channel.set_solo(in_channel.channel, False) self.monitor_channel.set_muted(in_channel.channel, False) self.monitor_channel.set_solo(channel.channel, True) self.monitor_channel.prefader = True else: self.monitor_channel.prefader = False self.update_monitor(channel) monitored_channel = property(get_monitored_channel, set_monitored_channel) def update_monitor(self, channel): if self._monitored_channel is not channel: return self.monitor_channel.volume = channel.channel.volume self.monitor_channel.balance = channel.channel.balance if type(self.monitored_channel) is OutputChannel: # sync solo/muted channels for input_channel in self.channels: self.monitor_channel.set_solo( input_channel.channel, channel.channel.is_solo(input_channel.channel)) self.monitor_channel.set_muted( input_channel.channel, channel.channel.is_muted(input_channel.channel)) def get_input_channel_by_name(self, name): for input_channel in self.channels: if input_channel.channel.name == name: return input_channel return None def on_about(self, *args): about = Gtk.AboutDialog() about.set_name('jack_mixer') about.set_program_name('jack_mixer') about.set_copyright( 'Copyright © 2006-2020\nNedko Arnaudov, Frédéric Péters, Arnout Engelen, Daniel Sheeler' ) about.set_license("""\ jack_mixer 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. jack_mixer 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 jack_mixer; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-130159 USA""") about.set_authors([ 'Nedko Arnaudov <*****@*****.**>', 'Christopher Arndt <*****@*****.**>', 'Arnout Engelen <*****@*****.**>', 'John Hedges <*****@*****.**>', 'Olivier Humbert <*****@*****.**>', 'Sarah Mischke <*****@*****.**>', 'Frédéric Péters <*****@*****.**>', 'Daniel Sheeler <*****@*****.**>', 'Athanasios Silis <*****@*****.**>', ]) about.set_logo_icon_name('jack_mixer') about.set_version(__version__) about.set_website('https://rdio.space/jackmixer/') about.run() about.destroy() def save_to_xml(self, file): log.debug("Saving to XML...") b = XmlSerialization() s = Serializator() s.serialize(self, b) b.save(file) def load_from_xml(self, file, silence_errors=False, from_nsm=False): log.debug("Loading from XML...") self.unserialized_channels = [] b = XmlSerialization() try: b.load(file) except: if silence_errors: return raise self.on_channels_clear(None) s = Serializator() s.unserialize(self, b) for channel in self.unserialized_channels: if isinstance(channel, InputChannel): if self._init_solo_channels and channel.channel_name in self._init_solo_channels: channel.solo = True self.add_channel_precreated(channel) self._init_solo_channels = None for channel in self.unserialized_channels: if isinstance(channel, OutputChannel): self.add_output_channel_precreated(channel) del self.unserialized_channels width, height = self.window.get_size() if self.visible or not from_nsm: self.window.show_all() self.paned.set_position(self.paned_position / self.width * width) self.window.resize(self.width, self.height) def serialize(self, object_backend): width, height = self.window.get_size() object_backend.add_property('geometry', '%sx%s' % (width, height)) pos = self.paned.get_position() object_backend.add_property('paned_position', '%s' % pos) solo_channels = [] for input_channel in self.channels: if input_channel.channel.solo: solo_channels.append(input_channel) if solo_channels: object_backend.add_property( 'solo_channels', '|'.join([x.channel.name for x in solo_channels])) object_backend.add_property('visible', '%s' % str(self.visible)) def unserialize_property(self, name, value): if name == 'geometry': width, height = value.split('x') self.width = int(width) self.height = int(height) return True if name == 'solo_channels': self._init_solo_channels = value.split('|') return True if name == 'visible': self.visible = value == 'True' return True if name == 'paned_position': self.paned_position = int(value) return True return False def unserialize_child(self, name): if name == InputChannel.serialization_name(): channel = InputChannel(self, "", True) self.unserialized_channels.append(channel) return channel if name == OutputChannel.serialization_name(): channel = OutputChannel(self, "", True) self.unserialized_channels.append(channel) return channel if name == gui.Factory.serialization_name(): return self.gui_factory def serialization_get_childs(self): '''Get child objects that required and support serialization''' childs = self.channels[:] + self.output_channels[:] + [ self.gui_factory ] return childs def serialization_name(self): return "jack_mixer" def main(self): if not self.mixer: return if self.visible or self.nsm_client == None: width, height = self.window.get_size() self.window.show_all() if hasattr(self, 'paned_position'): self.paned.set_position(self.paned_position / self.width * width) signal.signal(signal.SIGUSR1, self.sighandler) signal.signal(signal.SIGTERM, self.sighandler) signal.signal(signal.SIGINT, self.sighandler) signal.signal(signal.SIGHUP, signal.SIG_IGN) Gtk.main()
def on_mi_preferences_activate(self, widget): dlg = PreferencesDialog() dlg.run()
def on_preferences(self, event): with PreferencesDialog() as dlg: dlg.ShowModal()
def openPreferences(self): prefDiag = PreferencesDialog(self.settings, self) prefDiag.exec_()
class CloudHandle(object): fileList = [] def __init__(self): self.pdialog = PreferencesDialog() self.pdialog.signals.settingsChanged.connect(self.initializeApi) self.signals = self.Signals() self.updateTimer = QTimer(); QObject.connect(self.updateTimer, SIGNAL("timeout()"), self.getFileList) self.initializeApi() def initializeApi(self): self.updateTimer.stop(); self.connected = False try: username = self.pdialog.settings['username'] password = self.pdialog.settings['password'] if username == '' or password == '': raise ValueError('Empty password or username') self.api = CloudApi(username, password) self.getFileList() self.updateTimer.start(30000); except (KeyError, ValueError): self.pdialog.show() logging.warn("Couldn't reading settings") def getFileList(self): self.api.getFileList(self.pdialog.settings['list_size'], self.gotFileList) def gotFileList(self, l): self.connected = True self.fileList = l self.signals.gotFileList.emit(l) def addItem(self, url): url = str(url) if urllib.parse.urlparse(url).scheme == "file": self.api.uploadFile(url, self.itemAdded) else: self.api.bookmark(url, self.itemAdded) self.signals.uploadStarted.emit() def itemAdded(self, item): self.fileList.insert(0, item) self.fileList.pop() self.signals.gotFileList.emit(self.fileList) if self.pdialog.settings['auto_clipboard']: self.signals.loadClipboard.emit(item['url']) if self.pdialog.settings['notifications']: if item['item_type'] == 'bookmark': self.notify('Bookmarked - '+item['name'], item['url']) else: self.notify('File Uploaded - '+item['name'], item['url']) self.signals.uploadFinished.emit() def deleteItem(self, url): url = str(url) self.api.delete(url, self.deleted) def deleted(self, x): self.getFileList() if self.pdialog.settings['notifications']: self.notify("Deleted - "+x['name'], 'This item was removed from your CloudApp') def showPreferences(self): self.pdialog.show() def notify(self, title, text, icon="dialog-information"): try: from gi.repository import Notify as pynotify if pynotify.init("Cloud App"): n = pynotify.Notification.new(title, text, icon) n.set_timeout(5) n.show() else: logging.error("there was a problem initializing the pynotify module") except: logging.info("you don't seem to have pynotify installed") class Signals(QObject): gotFileList = pyqtSignal(list) loadClipboard = pyqtSignal(str) uploadStarted = pyqtSignal() uploadFinished = pyqtSignal()
def preferences_clicked(self, widget): self.preferences_dialog = PreferencesDialog(self.conf, self.menu) if self.preferences_dialog.exec_() == QtGui.QDialog.Accepted: self.preferences_dialog.save() self.app.emit(QtCore.SIGNAL('reload_project_data'))
class AppMenu: def __init__(self, app, tray, widget, conf, build_icons): self.menu = QtGui.QMenu(widget) tray.setContextMenu(self.menu) self.conf = conf self.app = app self.build_icons = build_icons self.create_default_menu_items() def update(self, projects): projects.sort(lambda x, y: (x.last_build_time - y.last_build_time).days) self.menu.clear() for project in projects: self.create_menu_item( project.name, self.build_icons.for_status(project.get_build_status()), project.url, project.last_build_time, project.server_url) self.create_default_menu_items() def create_default_menu_items(self): self.menu.addSeparator() self.menu.addAction( QtGui.QAction("About", self.menu, triggered=self.about_clicked)) self.menu.addAction( QtGui.QAction("Preferences", self.menu, triggered=self.preferences_clicked)) self.menu.addAction( QtGui.QAction("Exit", self.menu, triggered=self.exit)) def about_clicked(self, widget): QtGui.QMessageBox.about( self.menu, "About BuildNotify %s" % VERSION, "<b>BuildNotify %s</b> has been developed using PyQt4 and serves as a build notification tool for cruise control. In case of any suggestions/bugs," % VERSION + "please visit <a href=\"http://bitbucket.org/Anay/buildnotify\">http://bitbucket.org/Anay/buildnotify</a> and provide your feedback." ) def preferences_clicked(self, widget): self.preferences_dialog = PreferencesDialog(self.conf, self.menu) if self.preferences_dialog.exec_() == QtGui.QDialog.Accepted: self.preferences_dialog.save() self.app.emit(QtCore.SIGNAL('reload_project_data')) def exit(self, widget): sys.exit() def create_menu_item(self, label, icon, url, last_build_time, server_url): menu_item_label = label if self.conf.get_value("lastBuildTimeForProject"): menu_item_label = label + ", " + DistanceOfTime( last_build_time, self.conf.get_project_timezone( url, server_url)).age() + " ago" action = self.menu.addAction(icon, menu_item_label) action.setIconVisibleInMenu(True) receiver = lambda url=url: self.open_url(self, url) QtCore.QObject.connect(action, QtCore.SIGNAL('triggered()'), receiver) def open_url(self, something, url): webbrowser.open(url)
class JackMixer(SerializedObject): # scales suitable as meter scales meter_scales = [ scale.IEC268(), scale.Linear70dB(), scale.IEC268Minimalistic() ] # scales suitable as volume slider scales slider_scales = [scale.Linear30dB(), scale.Linear70dB()] # name of settngs file that is currently open current_filename = None # automatically bridged channels bridged_connection = list() unbridged_connection = list() bridged_channel = list() def __init__(self, name, lash_client): self.mixer = jack_mixer_c.Mixer(name) if not self.mixer: return self.monitor_channel = self.mixer.add_output_channel( "Monitor", True, True) self.save = False if lash_client: # Send our client name to server lash_event = lash.lash_event_new_with_type(lash.LASH_Client_Name) lash.lash_event_set_string(lash_event, name) lash.lash_send_event(lash_client, lash_event) lash.lash_jack_client_name(lash_client, name) self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) if name != self.mixer.client_name(): self.window.set_title(name + " (" + self.mixer.client_name() + ")") else: self.window.set_title(name) self.window.set_icon_name('jack_mixer') self.gui_factory = gui.Factory(self.window, self.meter_scales, self.slider_scales) self.vbox_top = gtk.VBox() self.window.add(self.vbox_top) self.menubar = gtk.MenuBar() self.vbox_top.pack_start(self.menubar, False) mixer_menu_item = gtk.MenuItem("_Mixer") self.menubar.append(mixer_menu_item) edit_menu_item = gtk.MenuItem('_Edit') self.menubar.append(edit_menu_item) help_menu_item = gtk.MenuItem('_Help') self.menubar.append(help_menu_item) self.window.set_default_size(120, 300) mixer_menu = gtk.Menu() mixer_menu_item.set_submenu(mixer_menu) add_input_channel = gtk.ImageMenuItem('New _Input Channel') mixer_menu.append(add_input_channel) add_input_channel.connect("activate", self.on_add_input_channel) add_output_channel = gtk.ImageMenuItem('New _Output Channel') mixer_menu.append(add_output_channel) add_output_channel.connect("activate", self.on_add_output_channel) mixer_menu.append(gtk.SeparatorMenuItem()) bridge_system = gtk.ImageMenuItem('Bridge System Playback') mixer_menu.append(bridge_system) bridge_system.connect("activate", self.on_bridge_system) unbridge_system = gtk.ImageMenuItem('Unbridge System Playback') mixer_menu.append(unbridge_system) unbridge_system.connect("activate", self.on_unbridge_system) mixer_menu.append(gtk.SeparatorMenuItem()) open = gtk.ImageMenuItem(gtk.STOCK_OPEN) mixer_menu.append(open) open.connect('activate', self.on_open_cb) save = gtk.ImageMenuItem(gtk.STOCK_SAVE) mixer_menu.append(save) save.connect('activate', self.on_save_cb) save_as = gtk.ImageMenuItem(gtk.STOCK_SAVE_AS) mixer_menu.append(save_as) save_as.connect('activate', self.on_save_as_cb) mixer_menu.append(gtk.SeparatorMenuItem()) quit = gtk.ImageMenuItem(gtk.STOCK_QUIT) mixer_menu.append(quit) quit.connect('activate', self.on_quit_cb) edit_menu = gtk.Menu() edit_menu_item.set_submenu(edit_menu) self.channel_edit_input_menu_item = gtk.MenuItem('_Edit Input Channel') edit_menu.append(self.channel_edit_input_menu_item) self.channel_edit_input_menu = gtk.Menu() self.channel_edit_input_menu_item.set_submenu( self.channel_edit_input_menu) self.channel_edit_output_menu_item = gtk.MenuItem( 'Edit _Output Channel') edit_menu.append(self.channel_edit_output_menu_item) self.channel_edit_output_menu = gtk.Menu() self.channel_edit_output_menu_item.set_submenu( self.channel_edit_output_menu) self.channel_remove_input_menu_item = gtk.MenuItem( 'Remove _Input Channel') edit_menu.append(self.channel_remove_input_menu_item) self.channel_remove_input_menu = gtk.Menu() self.channel_remove_input_menu_item.set_submenu( self.channel_remove_input_menu) self.channel_remove_output_menu_item = gtk.MenuItem( '_Remove Output Channel') edit_menu.append(self.channel_remove_output_menu_item) self.channel_remove_output_menu = gtk.Menu() self.channel_remove_output_menu_item.set_submenu( self.channel_remove_output_menu) channel_remove_all_menu_item = gtk.ImageMenuItem(gtk.STOCK_CLEAR) edit_menu.append(channel_remove_all_menu_item) channel_remove_all_menu_item.connect("activate", self.on_channels_clear) edit_menu.append(gtk.SeparatorMenuItem()) preferences = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES) preferences.connect('activate', self.on_preferences_cb) edit_menu.append(preferences) help_menu = gtk.Menu() help_menu_item.set_submenu(help_menu) about = gtk.ImageMenuItem(gtk.STOCK_ABOUT) help_menu.append(about) about.connect("activate", self.on_about) self.hbox_top = gtk.HBox() self.vbox_top.pack_start(self.hbox_top, True) self.scrolled_window = gtk.ScrolledWindow() self.hbox_top.pack_start(self.scrolled_window, True) self.hbox_inputs = gtk.HBox() self.hbox_inputs.set_spacing(0) self.hbox_inputs.set_border_width(0) self.hbox_top.set_spacing(0) self.hbox_top.set_border_width(0) self.channels = [] self.output_channels = [] self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.scrolled_window.add_with_viewport(self.hbox_inputs) self.main_mix = MainMixChannel(self) self.hbox_outputs = gtk.HBox() self.hbox_outputs.set_spacing(0) self.hbox_outputs.set_border_width(0) frame = gtk.Frame() frame.add(self.main_mix) self.hbox_outputs.pack_start(frame, False) self.hbox_top.pack_start(self.hbox_outputs, False) self.window.connect("destroy", gtk.main_quit) self.trayicon = TrayIcon(self) self.window.connect('delete-event', self.on_delete_event) gobject.timeout_add(80, self.read_meters) self.lash_client = lash_client gobject.timeout_add(200, self.lash_check_events) gobject.timeout_add(50, self.midi_events_check) def on_delete_event(self, widget, event): if self.gui_factory.get_minimize_to_tray(): self.window.hide() return True else: self.on_quit_cb() return False def sighandler(self, signum, frame): #print "Signal %d received" % signum if signum == signal.SIGUSR1: self.save = True elif signum == signal.SIGTERM: gtk.main_quit() elif signum == signal.SIGINT: gtk.main_quit() else: print "Unknown signal %d received" % signum def cleanup(self): print "Cleaning jack_mixer" if not self.mixer: return for channel in self.channels: channel.unrealize() self.mixer.destroy() def on_open_cb(self, *args): dlg = gtk.FileChooserDialog(title='Open', parent=self.window, action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) dlg.set_default_response(gtk.RESPONSE_OK) if dlg.run() == gtk.RESPONSE_OK: filename = dlg.get_filename() try: f = file(filename, 'r') self.load_from_xml(f) except: err = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Failed loading settings.") err.run() err.destroy() else: self.current_filename = filename finally: f.close() dlg.destroy() def on_save_cb(self, *args): if not self.current_filename: return self.on_save_as_cb() f = file(self.current_filename, 'w') self.save_to_xml(f) f.close() def on_save_as_cb(self, *args): dlg = gtk.FileChooserDialog(title='Save', parent=self.window, action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) dlg.set_default_response(gtk.RESPONSE_OK) if dlg.run() == gtk.RESPONSE_OK: self.current_filename = dlg.get_filename() self.on_save_cb() dlg.destroy() def on_quit_cb(self, *args): self.on_unbridge_system() gtk.main_quit() preferences_dialog = None def on_preferences_cb(self, widget): if not self.preferences_dialog: self.preferences_dialog = PreferencesDialog(self) self.preferences_dialog.show() self.preferences_dialog.present() def on_add_input_channel(self, widget): dialog = NewChannelDialog(app=self) dialog.set_transient_for(self.window) dialog.show() ret = dialog.run() dialog.hide() if ret == gtk.RESPONSE_OK: result = dialog.get_result() channel = self.add_channel(**result) self.window.show_all() def on_add_output_channel(self, widget): dialog = NewOutputChannelDialog(app=self) dialog.set_transient_for(self.window) dialog.show() ret = dialog.run() dialog.hide() if ret == gtk.RESPONSE_OK: result = dialog.get_result() channel = self.add_output_channel(**result) self.window.show_all() @staticmethod def remove_last_digit(mystr): digits = re.findall(r'\d+', mystr) if len(digits) == 0: return mystr lastdigit = digits[len(digits) - 1] return mystr[:-len(str(lastdigit))] def on_bridge_system(self, widget): connections = self.mixer.get_systemport_connections() for i in range(0, len(connections)): actConnection = connections[i] actConnectionNoDigit = self.remove_last_digit(actConnection) # search if channel exists channelExists = False for c in range(len(self.channels)): if self.channels[ c].channel_name == actConnection or self.channels[ c].channel_name == actConnectionNoDigit: channelExists = True break lastChar = actConnection[len(actConnection) - 1] if lastChar == 'R' or lastChar == 'r' or lastChar == 'L' or lastChar == 'l': for c in range(len(self.channels)): if self.channels[c].channel_name == actConnection[:-1]: channelExists = True break # search for other ports => possible stereo sameConnectionCount = 0 for j in range(0, len(connections)): if self.remove_last_digit( connections[j]) == actConnectionNoDigit: sameConnectionCount += 1 stereo = (sameConnectionCount == 2) if stereo: name = actConnectionNoDigit else: name = actConnection # search for 'L' - 'R' paired stereo if actConnection[len(actConnection) - 1] == 'L' or actConnection[len(actConnection) - 1] == 'l': for j in range(0, len(connections)): if connections[ j] == actConnection[:-1] + 'R' or connections[ j] == actConnection[:-1] + 'r': name = actConnection[:-1] stereo = True break else: if actConnection[len(actConnection) - 1] == 'R' or actConnection[ len(actConnection) - 1] == 'r': for j in range(0, len(connections)): if connections[ j] == actConnection[:-1] + 'L' or connections[ j] == actConnection[:-1] + 'l': name = actConnection[:-1] stereo = True break if not channelExists: c = self.add_channel(name, stereo, 0, 0) self.bridged_channel.append(c) # connect and disconnect (bridge) ports if stereo: system_port_connections = self.mixer.get_port_system_connections( actConnection) for k in range(0, len(system_port_connections)): if channelExists: self.mixer.connect_ports( actConnection, self.mixer.client_name() + ':' + name + ' R') self.mixer.connect_ports( self.mixer.client_name() + ':' + name + ' Out R', system_port_connections[k]) self.bridged_connection.append([ actConnection, self.mixer.client_name() + ':' + name + ' R' ]) self.bridged_connection.append([ self.mixer.client_name() + ':' + name + ' Out R', system_port_connections[k] ]) else: self.mixer.connect_ports( actConnection, self.mixer.client_name() + ':' + name + ' L') self.mixer.connect_ports( self.mixer.client_name() + ':' + name + ' Out L', system_port_connections[k]) self.bridged_connection.append([ actConnection, self.mixer.client_name() + ':' + name + ' L' ]) self.bridged_connection.append([ self.mixer.client_name() + ':' + name + ' Out L', system_port_connections[k] ]) self.mixer.disconnect_ports(actConnection, system_port_connections[k]) self.unbridged_connection.append( [actConnection, system_port_connections[k]]) else: # mono self.mixer.connect_ports(actConnection, self.mixer.client_name() + ':' + name) self.bridged_connection.append( [actConnection, self.mixer.client_name() + ':' + name]) system_port_connections = self.mixer.get_port_system_connections( actConnection) for k in range(0, len(system_port_connections)): self.mixer.connect_ports( self.mixer.client_name() + ':' + name + ' Out', system_port_connections[k]) self.bridged_connection.append([ self.mixer.client_name() + ':' + name + ' Out', system_port_connections[k] ]) self.mixer.disconnect_ports(actConnection, system_port_connections[k]) self.bridged_connection.append( [actConnection, system_port_connections[k]]) self.window.show_all() def on_unbridge_system(self, widget=None): print 'Unbridge System Connections' for connection in self.unbridged_connection: self.mixer.connect_ports(connection[0], connection[1]) self.unbridged_connection[:] = [] for connection in self.bridged_connection: self.mixer.disconnect_ports(connection[0], connection[1]) self.bridged_connection[:] = [] if widget != None: # we are closing for channel in self.bridged_channel: self.on_remove_input_channel(widget, channel) self.bridged_channel[:] = [] def on_edit_input_channel(self, widget, channel): print 'Editing channel "%s"' % channel.channel_name channel.on_channel_properties() def remove_channel_edit_input_menuitem_by_label(self, widget, label): if (widget.get_label() == label): self.channel_edit_input_menu.remove(widget) def on_remove_input_channel(self, widget, channel): print 'Removing channel "%s"' % channel.channel_name self.channel_remove_input_menu.remove(widget) self.channel_edit_input_menu.foreach( self.remove_channel_edit_input_menuitem_by_label, channel.channel_name) if self.monitored_channel is channel: channel.monitor_button.set_active(False) for i in range(len(self.channels)): if self.channels[i] is channel: channel.unrealize() del self.channels[i] self.hbox_inputs.remove(channel.parent) break if len(self.channels) == 0: self.channel_remove_input_menu_item.set_sensitive(False) def on_edit_output_channel(self, widget, channel): print 'Editing channel "%s"' % channel.channel_name channel.on_channel_properties() def remove_channel_edit_output_menuitem_by_label(self, widget, label): if (widget.get_label() == label): self.channel_edit_output_menu.remove(widget) def on_remove_output_channel(self, widget, channel): print 'Removing channel "%s"' % channel.channel_name self.channel_remove_output_menu.remove(widget) self.channel_edit_output_menu.foreach( self.remove_channel_edit_output_menuitem_by_label, channel.channel_name) if self.monitored_channel is channel: channel.monitor_button.set_active(False) for i in range(len(self.channels)): if self.output_channels[i] is channel: channel.unrealize() del self.output_channels[i] self.hbox_outputs.remove(channel.parent) break if len(self.output_channels) == 0: self.channel_remove_output_menu_item.set_sensitive(False) def rename_channels(self, container, parameters): if (container.get_label() == parameters['oldname']): container.set_label(parameters['newname']) def on_channel_rename(self, oldname, newname): rename_parameters = {'oldname': oldname, 'newname': newname} self.channel_edit_input_menu.foreach(self.rename_channels, rename_parameters) self.channel_edit_output_menu.foreach(self.rename_channels, rename_parameters) self.channel_remove_input_menu.foreach(self.rename_channels, rename_parameters) self.channel_remove_output_menu.foreach(self.rename_channels, rename_parameters) print "Renaming channel from %s to %s\n" % (oldname, newname) def on_channels_clear(self, widget): for channel in self.output_channels: channel.unrealize() self.hbox_outputs.remove(channel.parent) for channel in self.channels: channel.unrealize() self.hbox_inputs.remove(channel.parent) self.channels = [] self.output_channels = [] self.channel_edit_input_menu = gtk.Menu() self.channel_edit_input_menu_item.set_submenu( self.channel_edit_input_menu) self.channel_edit_input_menu_item.set_sensitive(False) self.channel_remove_input_menu = gtk.Menu() self.channel_remove_input_menu_item.set_submenu( self.channel_remove_input_menu) self.channel_remove_input_menu_item.set_sensitive(False) self.channel_edit_output_menu = gtk.Menu() self.channel_edit_output_menu_item.set_submenu( self.channel_edit_output_menu) self.channel_edit_output_menu_item.set_sensitive(False) self.channel_remove_output_menu = gtk.Menu() self.channel_remove_output_menu_item.set_submenu( self.channel_remove_output_menu) self.channel_remove_output_menu_item.set_sensitive(False) def add_channel(self, name, stereo, volume_cc, balance_cc): try: channel = InputChannel(self, name, stereo) self.add_channel_precreated(channel) except Exception: err = gtk.MessageDialog( self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Channel creation failed") err.run() err.destroy() return if volume_cc: channel.channel.volume_midi_cc = int(volume_cc) if balance_cc: channel.channel.balance_midi_cc = int(balance_cc) if not (volume_cc or balance_cc): channel.channel.autoset_midi_cc() return channel def add_channel_precreated(self, channel): frame = gtk.Frame() frame.add(channel) self.hbox_inputs.pack_start(frame, False) channel.realize() channel_edit_menu_item = gtk.MenuItem(channel.channel_name) self.channel_edit_input_menu.append(channel_edit_menu_item) channel_edit_menu_item.connect("activate", self.on_edit_input_channel, channel) self.channel_edit_input_menu_item.set_sensitive(True) channel_remove_menu_item = gtk.MenuItem(channel.channel_name) self.channel_remove_input_menu.append(channel_remove_menu_item) channel_remove_menu_item.connect("activate", self.on_remove_input_channel, channel) self.channel_remove_input_menu_item.set_sensitive(True) self.channels.append(channel) for outputchannel in self.output_channels: channel.add_control_group(outputchannel) # create post fader output channel matching the input channel channel.post_fader_output_channel = self.mixer.add_output_channel( channel.channel.name + ' Out', channel.channel.is_stereo, True) channel.post_fader_output_channel.volume = 0 channel.post_fader_output_channel.set_solo(channel.channel, True) def read_meters(self): for channel in self.channels: channel.read_meter() self.main_mix.read_meter() for channel in self.output_channels: channel.read_meter() return True def midi_events_check(self): for channel in self.channels + [self.main_mix] + self.output_channels: channel.midi_events_check() return True def add_output_channel(self, name, stereo, volume_cc, balance_cc, display_solo_buttons): try: channel = OutputChannel(self, name, stereo) channel.display_solo_buttons = display_solo_buttons self.add_output_channel_precreated(channel) except Exception: err = gtk.MessageDialog( self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Channel creation failed") err.run() err.destroy() return if volume_cc: channel.channel.volume_midi_cc = int(volume_cc) if balance_cc: channel.channel.balance_midi_cc = int(balance_cc) return channel def add_output_channel_precreated(self, channel): frame = gtk.Frame() frame.add(channel) self.hbox_outputs.pack_start(frame, False) channel.realize() channel_edit_menu_item = gtk.MenuItem(channel.channel_name) self.channel_edit_output_menu.append(channel_edit_menu_item) channel_edit_menu_item.connect("activate", self.on_edit_output_channel, channel) self.channel_edit_output_menu_item.set_sensitive(True) channel_remove_menu_item = gtk.MenuItem(channel.channel_name) self.channel_remove_output_menu.append(channel_remove_menu_item) channel_remove_menu_item.connect("activate", self.on_remove_output_channel, channel) self.channel_remove_output_menu_item.set_sensitive(True) self.output_channels.append(channel) _monitored_channel = None def get_monitored_channel(self): return self._monitored_channel def set_monitored_channel(self, channel): if self._monitored_channel: if channel.channel.name == self._monitored_channel.channel.name: return self._monitored_channel = channel if type(channel) is InputChannel: # reset all solo/mute settings for in_channel in self.channels: self.monitor_channel.set_solo(in_channel.channel, False) self.monitor_channel.set_muted(in_channel.channel, False) self.monitor_channel.set_solo(channel.channel, True) self.monitor_channel.prefader = True else: self.monitor_channel.prefader = False self.update_monitor(channel) monitored_channel = property(get_monitored_channel, set_monitored_channel) def update_monitor(self, channel): if self.monitored_channel is not channel: return self.monitor_channel.volume = channel.channel.volume self.monitor_channel.balance = channel.channel.balance if type(self.monitored_channel) is OutputChannel: # sync solo/muted channels for input_channel in self.channels: self.monitor_channel.set_solo( input_channel.channel, channel.channel.is_solo(input_channel.channel)) self.monitor_channel.set_muted( input_channel.channel, channel.channel.is_muted(input_channel.channel)) elif type(self.monitored_channel) is MainMixChannel: # sync solo/muted channels for input_channel in self.channels: self.monitor_channel.set_solo(input_channel.channel, input_channel.channel.solo) self.monitor_channel.set_muted(input_channel.channel, input_channel.channel.mute) def get_input_channel_by_name(self, name): for input_channel in self.channels: if input_channel.channel.name == name: return input_channel return None def on_about(self, *args): about = gtk.AboutDialog() about.set_name('jack_mixer') about.set_copyright( 'Copyright © 2006-2010\nNedko Arnaudov, Frederic Peters, Arnout Engelen' ) about.set_license('''\ jack_mixer 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. jack_mixer 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 jack_mixer; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-130159 USA''') about.set_authors([ 'Nedko Arnaudov <*****@*****.**>', 'Frederic Peters <*****@*****.**>' ]) about.set_logo_icon_name('jack_mixer') about.set_website('http://home.gna.org/jackmixer/') about.run() about.destroy() def lash_check_events(self): if self.save: self.save = False if self.current_filename: print "saving on SIGUSR1 request" self.on_save_cb() print "save done" else: print "not saving because filename is not known" return True if not self.lash_client: return True while lash.lash_get_pending_event_count(self.lash_client): event = lash.lash_get_event(self.lash_client) #print repr(event) event_type = lash.lash_event_get_type(event) if event_type == lash.LASH_Quit: print "jack_mixer: LASH ordered quit." gtk.main_quit() return False elif event_type == lash.LASH_Save_File: directory = lash.lash_event_get_string(event) print "jack_mixer: LASH ordered to save data in directory %s" % directory filename = directory + os.sep + "jack_mixer.xml" f = file(filename, "w") self.save_to_xml(f) f.close() lash.lash_send_event(self.lash_client, event) # we crash with double free elif event_type == lash.LASH_Restore_File: directory = lash.lash_event_get_string(event) print "jack_mixer: LASH ordered to restore data from directory %s" % directory filename = directory + os.sep + "jack_mixer.xml" f = file(filename, "r") self.load_from_xml(f, silence_errors=True) f.close() lash.lash_send_event(self.lash_client, event) else: print "jack_mixer: Got unhandled LASH event, type " + str( event_type) return True #lash.lash_event_destroy(event) return True def save_to_xml(self, file): #print "Saving to XML..." b = XmlSerialization() s = Serializator() s.serialize(self, b) b.save(file) def load_from_xml(self, file, silence_errors=False): #print "Loading from XML..." self.on_channels_clear(None) self.unserialized_channels = [] b = XmlSerialization() try: b.load(file) except: if silence_errors: return raise s = Serializator() s.unserialize(self, b) for channel in self.unserialized_channels: if isinstance(channel, InputChannel): self.add_channel_precreated(channel) for channel in self.unserialized_channels: if isinstance(channel, OutputChannel): self.add_output_channel_precreated(channel) del self.unserialized_channels self.window.show_all() def serialize(self, object_backend): object_backend.add_property( 'geometry', '%sx%s' % (self.window.allocation.width, self.window.allocation.height)) def unserialize_property(self, name, value): if name == 'geometry': width, height = value.split('x') self.window.resize(int(width), int(height)) return True def unserialize_child(self, name): if name == MainMixChannel.serialization_name(): return self.main_mix if name == InputChannel.serialization_name(): channel = InputChannel(self, "", True) self.unserialized_channels.append(channel) return channel if name == OutputChannel.serialization_name(): channel = OutputChannel(self, "", True) self.unserialized_channels.append(channel) return channel def serialization_get_childs(self): '''Get child objects tha required and support serialization''' childs = self.channels[:] + self.output_channels[:] childs.append(self.main_mix) return childs def serialization_name(self): return "jack_mixer" def main(self): self.main_mix.realize() self.main_mix.set_monitored() if not self.mixer: return self.window.show_all() signal.signal(signal.SIGUSR1, self.sighandler) signal.signal(signal.SIGTERM, self.sighandler) signal.signal(signal.SIGINT, self.sighandler) signal.signal(signal.SIGHUP, signal.SIG_IGN) gtk.main()
def optionsClicked(self): self.prefDialog = PreferencesDialog() self.prefDialog.setModal(True) self.prefDialog.show()
def on_preferences_cb(self, widget): if not self.preferences_dialog: self.preferences_dialog = PreferencesDialog(self) self.preferences_dialog.show() self.preferences_dialog.present()
class CloudHandle(object): fileList = [] def __init__(self): self.pdialog = PreferencesDialog() self.pdialog.signals.settingsChanged.connect(self.initializeApi) self.signals = self.Signals() self.initializeApi() def initializeApi(self): self.connected = False try: username = self.pdialog.settings["username"] password = self.pdialog.settings["password"] if username == "" or password == "": raise ValueError("Empty password or username") self.api = CloudApi(username, password) self.getFileList() except (KeyError, ValueError): self.pdialog.show() print "Error reading settings" def getFileList(self): self.api.getFileList(self.pdialog.settings["list_size"], self.gotFileList) def gotFileList(self, l): self.connected = True self.fileList = l self.signals.gotFileList.emit(l) def addItem(self, url): url = str(url) if urlparse.urlparse(url).scheme == "file": self.api.uploadFile(url, self.itemAdded) else: self.api.bookmark(url, self.itemAdded) self.signals.uploadStarted.emit() def itemAdded(self, item): self.fileList.insert(0, item) self.fileList.pop() self.signals.gotFileList.emit(self.fileList) if self.pdialog.settings["auto_clipboard"]: self.signals.loadClipboard.emit(item["url"]) if self.pdialog.settings["notifications"]: if item["item_type"] == "bookmark": self.notify("Bookmarked - " + item["name"], item["url"]) else: self.notify("File Uploaded - " + item["name"], item["url"]) self.signals.uploadFinished.emit() def deleteItem(self, url): url = str(url) self.api.delete(url, self.deleted) def deleted(self, x): self.getFileList() if self.pdialog.settings["notifications"]: self.notify("Deleted - " + x["name"], "This item was removed from your CloudApp") def showPreferences(self): self.pdialog.show() def notify(self, title, text, icon=None): try: import pynotify if pynotify.init("Cloud App"): n = pynotify.Notification(title, text) n.set_timeout(5) n.show() else: print "there was a problem initializing the pynotify module" except: print "you don't seem to have pynotify installed" class Signals(QObject): gotFileList = pyqtSignal(list) loadClipboard = pyqtSignal(str) uploadStarted = pyqtSignal() uploadFinished = pyqtSignal()
def preferences(self): dialog = PreferencesDialog(self, self.lang.languages, self.lang.get_current_language_index()) if dialog.exec_(): self.lang.select(dialog.get_language())
def preferrences_action_triggered(self): preferences_dialog = PreferencesDialog( settings=self.settings.value('Preferences')) signal = preferences_dialog.apply_signal signal.connect(self.apply_preferences) preferences_dialog.exec_()
class JackMixer(SerializedObject): # scales suitable as meter scales meter_scales = [ scale.IEC268(), scale.Linear70dB(), scale.IEC268Minimalistic() ] # scales suitable as volume slider scales slider_scales = [scale.Linear30dB(), scale.Linear70dB()] # name of settngs file that is currently open current_filename = None _init_solo_channels = None def __init__(self, name, lash_client): self.mixer = jack_mixer_c.Mixer(name) if not self.mixer: return self.monitor_channel = self.mixer.add_output_channel( "Monitor", True, True) self.save = False if lash_client: # Send our client name to server lash_event = lash.lash_event_new_with_type(lash.LASH_Client_Name) lash.lash_event_set_string(lash_event, name) lash.lash_send_event(lash_client, lash_event) lash.lash_jack_client_name(lash_client, name) self.window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL) if name != self.mixer.client_name(): self.window.set_title(name + " (" + self.mixer.client_name() + ")") else: self.window.set_title(name) self.window.set_icon_name('jack_mixer') self.gui_factory = gui.Factory(self.window, self.meter_scales, self.slider_scales) self.vbox_top = Gtk.VBox() self.window.add(self.vbox_top) self.menubar = Gtk.MenuBar() self.vbox_top.pack_start(self.menubar, False, True, 0) mixer_menu_item = Gtk.MenuItem.new_with_mnemonic("_Mixer") self.menubar.append(mixer_menu_item) edit_menu_item = Gtk.MenuItem.new_with_mnemonic('_Edit') self.menubar.append(edit_menu_item) help_menu_item = Gtk.MenuItem.new_with_mnemonic('_Help') self.menubar.append(help_menu_item) self.window.set_default_size(120, 300) mixer_menu = Gtk.Menu() mixer_menu_item.set_submenu(mixer_menu) add_input_channel = Gtk.MenuItem.new_with_mnemonic( 'New _Input Channel') mixer_menu.append(add_input_channel) add_input_channel.connect("activate", self.on_add_input_channel) add_output_channel = Gtk.MenuItem.new_with_mnemonic( 'New _Output Channel') mixer_menu.append(add_output_channel) add_output_channel.connect("activate", self.on_add_output_channel) mixer_menu.append(Gtk.SeparatorMenuItem()) open = Gtk.MenuItem.new_with_mnemonic('_Open') mixer_menu.append(open) open.connect('activate', self.on_open_cb) save = Gtk.MenuItem.new_with_mnemonic('_Save') mixer_menu.append(save) save.connect('activate', self.on_save_cb) save_as = Gtk.MenuItem.new_with_mnemonic('Save_As') mixer_menu.append(save_as) save_as.connect('activate', self.on_save_as_cb) mixer_menu.append(Gtk.SeparatorMenuItem()) quit = Gtk.MenuItem.new_with_mnemonic('_Quit') mixer_menu.append(quit) quit.connect('activate', self.on_quit_cb) edit_menu = Gtk.Menu() edit_menu_item.set_submenu(edit_menu) self.channel_edit_input_menu_item = Gtk.MenuItem.new_with_mnemonic( '_Edit Input Channel') edit_menu.append(self.channel_edit_input_menu_item) self.channel_edit_input_menu = Gtk.Menu() self.channel_edit_input_menu_item.set_submenu( self.channel_edit_input_menu) self.channel_edit_output_menu_item = Gtk.MenuItem.new_with_mnemonic( 'Edit _Output Channel') edit_menu.append(self.channel_edit_output_menu_item) self.channel_edit_output_menu = Gtk.Menu() self.channel_edit_output_menu_item.set_submenu( self.channel_edit_output_menu) self.channel_remove_input_menu_item = Gtk.MenuItem.new_with_mnemonic( 'Remove _Input Channel') edit_menu.append(self.channel_remove_input_menu_item) self.channel_remove_input_menu = Gtk.Menu() self.channel_remove_input_menu_item.set_submenu( self.channel_remove_input_menu) self.channel_remove_output_menu_item = Gtk.MenuItem.new_with_mnemonic( '_Remove Output Channel') edit_menu.append(self.channel_remove_output_menu_item) self.channel_remove_output_menu = Gtk.Menu() self.channel_remove_output_menu_item.set_submenu( self.channel_remove_output_menu) channel_remove_all_menu_item = Gtk.MenuItem.new_with_mnemonic('Clear') edit_menu.append(channel_remove_all_menu_item) channel_remove_all_menu_item.connect("activate", self.on_channels_clear) edit_menu.append(Gtk.SeparatorMenuItem()) preferences = Gtk.MenuItem.new_with_mnemonic('_Preferences') preferences.connect('activate', self.on_preferences_cb) edit_menu.append(preferences) help_menu = Gtk.Menu() help_menu_item.set_submenu(help_menu) about = Gtk.MenuItem.new_with_mnemonic('_About') help_menu.append(about) about.connect("activate", self.on_about) self.hbox_top = Gtk.HBox() self.vbox_top.pack_start(self.hbox_top, True, True, 0) self.scrolled_window = Gtk.ScrolledWindow() self.hbox_top.pack_start(self.scrolled_window, True, True, 0) self.hbox_inputs = Gtk.HBox() self.hbox_inputs.set_spacing(0) self.hbox_inputs.set_border_width(0) self.hbox_top.set_spacing(0) self.hbox_top.set_border_width(0) self.channels = [] self.output_channels = [] self.scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.scrolled_window.add(self.hbox_inputs) self.hbox_outputs = Gtk.HBox() self.hbox_outputs.set_spacing(0) self.hbox_outputs.set_border_width(0) frame = Gtk.Frame() self.hbox_outputs.pack_start(frame, False, True, 0) self.hbox_top.pack_start(self.hbox_outputs, False, True, 0) self.window.connect("destroy", Gtk.main_quit) self.window.connect('delete-event', self.on_delete_event) GLib.timeout_add(80, self.read_meters) self.lash_client = lash_client GLib.timeout_add(200, self.lash_check_events) GLib.timeout_add(50, self.midi_events_check) def on_delete_event(self, widget, event): return False def sighandler(self, signum, frame): #print "Signal %d received" % signum if signum == signal.SIGUSR1: self.save = True elif signum == signal.SIGTERM: Gtk.main_quit() elif signum == signal.SIGINT: Gtk.main_quit() else: print("Unknown signal %d received" % signum) def cleanup(self): print("Cleaning jack_mixer") if not self.mixer: return for channel in self.channels: channel.unrealize() self.mixer.destroy() def on_open_cb(self, *args): dlg = Gtk.FileChooserDialog( title='Open', parent=self.window, action=Gtk.FileChooserAction.OPEN, buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) dlg.set_default_response(Gtk.ResponseType.OK) if dlg.run() == Gtk.ResponseType.OK: filename = dlg.get_filename() try: f = file(filename, 'r') self.load_from_xml(f) except: err = Gtk.MessageDialog(self.window, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, "Failed loading settings.") err.run() err.destroy() else: self.current_filename = filename finally: f.close() dlg.destroy() def on_save_cb(self, *args): if not self.current_filename: return self.on_save_as_cb() f = file(self.current_filename, 'w') self.save_to_xml(f) f.close() def on_save_as_cb(self, *args): dlg = Gtk.FileChooserDialog( title='Save', parent=self.window, action=Gtk.FileChooserAction.SAVE, buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.OK)) dlg.set_default_response(Gtk.ResponseType.OK) if dlg.run() == Gtk.ResponseType.OK: self.current_filename = dlg.get_filename() self.on_save_cb() dlg.destroy() def on_quit_cb(self, *args): Gtk.main_quit() preferences_dialog = None def on_preferences_cb(self, widget): if not self.preferences_dialog: self.preferences_dialog = PreferencesDialog(self) self.preferences_dialog.show() self.preferences_dialog.present() def on_add_input_channel(self, widget): dialog = NewChannelDialog(app=self) dialog.set_transient_for(self.window) dialog.show() ret = dialog.run() dialog.hide() if ret == Gtk.ResponseType.OK: result = dialog.get_result() channel = self.add_channel(**result) self.window.show_all() def on_add_output_channel(self, widget): dialog = NewOutputChannelDialog(app=self) dialog.set_transient_for(self.window) dialog.show() ret = dialog.run() dialog.hide() if ret == Gtk.ResponseType.OK: result = dialog.get_result() channel = self.add_output_channel(**result) self.window.show_all() def on_edit_input_channel(self, widget, channel): print('Editing channel "%s"' % channel.channel_name) channel.on_channel_properties() def remove_channel_edit_input_menuitem_by_label(self, widget, label): if (widget.get_label() == label): self.channel_edit_input_menu.remove(widget) def on_remove_input_channel(self, widget, channel): print('Removing channel "%s"' % channel.channel_name) self.channel_remove_input_menu.remove(widget) self.channel_edit_input_menu.foreach( self.remove_channel_edit_input_menuitem_by_label, channel.channel_name) if self.monitored_channel is channel: channel.monitor_button.set_active(False) for i in range(len(self.channels)): if self.channels[i] is channel: channel.unrealize() del self.channels[i] self.hbox_inputs.remove(channel.get_parent()) break if len(self.channels) == 0: self.channel_remove_input_menu_item.set_sensitive(False) def on_edit_output_channel(self, widget, channel): print('Editing channel "%s"' % channel.channel_name) channel.on_channel_properties() def remove_channel_edit_output_menuitem_by_label(self, widget, label): if (widget.get_label() == label): self.channel_edit_output_menu.remove(widget) def on_remove_output_channel(self, widget, channel): print('Removing channel "%s"' % channel.channel_name) self.channel_remove_output_menu.remove(widget) self.channel_edit_output_menu.foreach( self.remove_channel_edit_output_menuitem_by_label, channel.channel_name) if self.monitored_channel is channel: channel.monitor_button.set_active(False) for i in range(len(self.channels)): if self.output_channels[i] is channel: channel.unrealize() del self.output_channels[i] self.hbox_outputs.remove(channel.get_parent()) break if len(self.output_channels) == 0: self.channel_remove_output_menu_item.set_sensitive(False) def rename_channels(self, container, parameters): if (container.get_label() == parameters['oldname']): container.set_label(parameters['newname']) def on_channel_rename(self, oldname, newname): rename_parameters = {'oldname': oldname, 'newname': newname} self.channel_edit_input_menu.foreach(self.rename_channels, rename_parameters) self.channel_edit_output_menu.foreach(self.rename_channels, rename_parameters) self.channel_remove_input_menu.foreach(self.rename_channels, rename_parameters) self.channel_remove_output_menu.foreach(self.rename_channels, rename_parameters) print("Renaming channel from %s to %s\n" % (oldname, newname)) def on_channels_clear(self, widget): for channel in self.output_channels: channel.unrealize() self.hbox_outputs.remove(channel.get_parent()) for channel in self.channels: channel.unrealize() self.hbox_inputs.remove(channel.get_parent()) self.channels = [] self.output_channels = [] self.channel_edit_input_menu = Gtk.Menu() self.channel_edit_input_menu_item.set_submenu( self.channel_edit_input_menu) self.channel_edit_input_menu_item.set_sensitive(False) self.channel_remove_input_menu = Gtk.Menu() self.channel_remove_input_menu_item.set_submenu( self.channel_remove_input_menu) self.channel_remove_input_menu_item.set_sensitive(False) self.channel_edit_output_menu = Gtk.Menu() self.channel_edit_output_menu_item.set_submenu( self.channel_edit_output_menu) self.channel_edit_output_menu_item.set_sensitive(False) self.channel_remove_output_menu = Gtk.Menu() self.channel_remove_output_menu_item.set_submenu( self.channel_remove_output_menu) self.channel_remove_output_menu_item.set_sensitive(False) def add_channel(self, name, stereo, volume_cc, balance_cc, mute_cc, solo_cc): try: channel = InputChannel(self, name, stereo) self.add_channel_precreated(channel) except Exception: e = sys.exc_info()[0] err = Gtk.MessageDialog( self.window, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, "Channel creation failed") err.run() err.destroy() return if volume_cc != '-1': channel.channel.volume_midi_cc = int(volume_cc) if balance_cc != '-1': channel.channel.balance_midi_cc = int(balance_cc) if mute_cc != '-1': channel.channel.mute_midi_cc = int(mute_cc) if solo_cc != '-1': channel.channel.solo_midi_cc = int(solo_cc) if (volume_cc == '-1' and balance_cc == '-1' and mute_cc == '-1' and solo_cc == '-1'): channel.channel.autoset_midi_cc() return channel def add_channel_precreated(self, channel): frame = Gtk.Frame() frame.add(channel) self.hbox_inputs.pack_start(frame, False, True, 0) channel.realize() channel_edit_menu_item = Gtk.MenuItem(label=channel.channel_name) self.channel_edit_input_menu.append(channel_edit_menu_item) channel_edit_menu_item.connect("activate", self.on_edit_input_channel, channel) self.channel_edit_input_menu_item.set_sensitive(True) channel_remove_menu_item = Gtk.MenuItem(label=channel.channel_name) self.channel_remove_input_menu.append(channel_remove_menu_item) channel_remove_menu_item.connect("activate", self.on_remove_input_channel, channel) self.channel_remove_input_menu_item.set_sensitive(True) self.channels.append(channel) for outputchannel in self.output_channels: channel.add_control_group(outputchannel) # create post fader output channel matching the input channel channel.post_fader_output_channel = self.mixer.add_output_channel( channel.channel.name + ' Out', channel.channel.is_stereo, True) channel.post_fader_output_channel.volume = 0 channel.post_fader_output_channel.set_solo(channel.channel, True) def read_meters(self): for channel in self.channels: channel.read_meter() for channel in self.output_channels: channel.read_meter() return True def midi_events_check(self): for channel in self.channels + self.output_channels: channel.midi_events_check() return True def add_output_channel(self, name, stereo, volume_cc, balance_cc, mute_cc, display_solo_buttons): try: channel = OutputChannel(self, name, stereo) channel.display_solo_buttons = display_solo_buttons self.add_output_channel_precreated(channel) except Exception: err = Gtk.MessageDialog( self.window, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, "Channel creation failed") err.run() err.destroy() return if volume_cc != '-1': channel.channel.volume_midi_cc = int(volume_cc) if balance_cc != '-1': channel.channel.balance_midi_cc = int(balance_cc) if mute_cc != '-1': channel.channel.mute_midi_cc = int(mute_cc) return channel def add_output_channel_precreated(self, channel): frame = Gtk.Frame() frame.add(channel) self.hbox_outputs.pack_start(frame, False, True, 0) channel.realize() channel_edit_menu_item = Gtk.MenuItem(label=channel.channel_name) self.channel_edit_output_menu.append(channel_edit_menu_item) channel_edit_menu_item.connect("activate", self.on_edit_output_channel, channel) self.channel_edit_output_menu_item.set_sensitive(True) channel_remove_menu_item = Gtk.MenuItem(label=channel.channel_name) self.channel_remove_output_menu.append(channel_remove_menu_item) channel_remove_menu_item.connect("activate", self.on_remove_output_channel, channel) self.channel_remove_output_menu_item.set_sensitive(True) self.output_channels.append(channel) _monitored_channel = None def get_monitored_channel(self): return self._monitored_channel def set_monitored_channel(self, channel): if self._monitored_channel: if channel.channel.name == self._monitored_channel.channel.name: return self._monitored_channel = channel if type(channel) is InputChannel: # reset all solo/mute settings for in_channel in self.channels: self.monitor_channel.set_solo(in_channel.channel, False) self.monitor_channel.set_muted(in_channel.channel, False) self.monitor_channel.set_solo(channel.channel, True) self.monitor_channel.prefader = True else: self.monitor_channel.prefader = False self.update_monitor(channel) monitored_channel = property(get_monitored_channel, set_monitored_channel) def update_monitor(self, channel): if self.monitored_channel is not channel: return self.monitor_channel.volume = channel.channel.volume self.monitor_channel.balance = channel.channel.balance self.monitor_channel.out_mute = channel.channel.out_mute if type(self.monitored_channel) is OutputChannel: # sync solo/muted channels for input_channel in self.channels: self.monitor_channel.set_solo( input_channel.channel, channel.channel.is_solo(input_channel.channel)) self.monitor_channel.set_muted( input_channel.channel, channel.channel.is_muted(input_channel.channel)) def get_input_channel_by_name(self, name): for input_channel in self.channels: if input_channel.channel.name == name: return input_channel return None def on_about(self, *args): about = Gtk.AboutDialog() about.set_name('jack_mixer') about.set_copyright( 'Copyright © 2006-2020\nNedko Arnaudov, Frederic Peters, Arnout Engelen, Daniel Sheeler' ) about.set_license('''\ jack_mixer 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. jack_mixer 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 jack_mixer; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-130159 USA''') about.set_authors([ 'Nedko Arnaudov <*****@*****.**>', 'Frederic Peters <*****@*****.**>', 'Daniel Sheeler <*****@*****.**>' ]) about.set_logo_icon_name('jack_mixer') about.set_website('https://rdio.space/jackmixer/') about.run() about.destroy() def lash_check_events(self): if self.save: self.save = False if self.current_filename: print("saving on SIGUSR1 request") self.on_save_cb() print("save done") else: print("not saving because filename is not known") return True if not self.lash_client: return True while lash.lash_get_pending_event_count(self.lash_client): event = lash.lash_get_event(self.lash_client) #print repr(event) event_type = lash.lash_event_get_type(event) if event_type == lash.LASH_Quit: print("jack_mixer: LASH ordered quit.") Gtk.main_quit() return False elif event_type == lash.LASH_Save_File: directory = lash.lash_event_get_string(event) print("jack_mixer: LASH ordered to save data in directory %s" % directory) filename = directory + os.sep + "jack_mixer.xml" f = file(filename, "w") self.save_to_xml(f) f.close() lash.lash_send_event(self.lash_client, event) # we crash with double free elif event_type == lash.LASH_Restore_File: directory = lash.lash_event_get_string(event) print( "jack_mixer: LASH ordered to restore data from directory %s" % directory) filename = directory + os.sep + "jack_mixer.xml" f = file(filename, "r") self.load_from_xml(f, silence_errors=True) f.close() lash.lash_send_event(self.lash_client, event) else: print("jack_mixer: Got unhandled LASH event, type " + str(event_type)) return True #lash.lash_event_destroy(event) return True def save_to_xml(self, file): #print "Saving to XML..." b = XmlSerialization() s = Serializator() s.serialize(self, b) b.save(file) def load_from_xml(self, file, silence_errors=False): #print "Loading from XML..." self.on_channels_clear(None) self.unserialized_channels = [] b = XmlSerialization() try: b.load(file) except: if silence_errors: return raise s = Serializator() s.unserialize(self, b) for channel in self.unserialized_channels: if isinstance(channel, InputChannel): if self._init_solo_channels and channel.channel_name in self._init_solo_channels: channel.solo = True self.add_channel_precreated(channel) self._init_solo_channels = None for channel in self.unserialized_channels: if isinstance(channel, OutputChannel): self.add_output_channel_precreated(channel) del self.unserialized_channels self.window.show_all() def serialize(self, object_backend): width, height = self.window.get_size() object_backend.add_property('geometry', '%sx%s' % (width, height)) solo_channels = [] for input_channel in self.channels: if input_channel.channel.solo: solo_channels.append(input_channel) if solo_channels: object_backend.add_property( 'solo_channels', '|'.join([x.channel.name for x in solo_channels])) def unserialize_property(self, name, value): if name == 'geometry': width, height = value.split('x') self.window.resize(int(width), int(height)) return True if name == 'solo_channels': self._init_solo_channels = value.split('|') return True def unserialize_child(self, name): if name == InputChannel.serialization_name(): channel = InputChannel(self, "", True) self.unserialized_channels.append(channel) return channel if name == OutputChannel.serialization_name(): channel = OutputChannel(self, "", True) self.unserialized_channels.append(channel) return channel def serialization_get_childs(self): '''Get child objects tha required and support serialization''' childs = self.channels[:] + self.output_channels[:] return childs def serialization_name(self): return "jack_mixer" def main(self): if not self.mixer: return self.window.show_all() signal.signal(signal.SIGUSR1, self.sighandler) signal.signal(signal.SIGTERM, self.sighandler) signal.signal(signal.SIGINT, self.sighandler) signal.signal(signal.SIGHUP, signal.SIG_IGN) Gtk.main()
def open_preferences_dialog(self): """Open a dialog with preferences.""" self.preferences_dialog = PreferencesDialog(self.config)