class Foo(QtGui.QMainWindow): def __init__(self): super(Foo, self).__init__() self.initUI() def initUI(self): config = Foo.readConfig('options') self.timeOut = -1 self.radio = False self.statusBar().showMessage('Ready') self.createMenu() self.setWindowTitle("Foo.cd") self.player = Player(Foo.readConfig('audio')) self.player.bus.connect('message::eos', self.stop) self.player.bus.connect('message::duration-changed', self.onDurationChanged) self.tree = Tree(self, config['tree_order']) self.tree.addSongs.connect(self.addSongsFromTree) self.tree.customContextMenuRequested.connect(self.tmpTag) if not self.radio: self.table = Table(self, config) self.handlerATF = self.player.playbin.connect( "about-to-finish", self.onAboutToFinish) self.table.runAction.connect(self.tableAction) else: configRadio = Foo.readConfigRadios() self.table = TableRadio(self, configRadio) self.table.runAction.connect(self.tableAction) self.handlerT = self.player.bus.connect('message::tag', self.table.onTag) self.playbackButtons = PlaybackButtons(None) self.playbackButtons.buttonPlay.clicked.connect(self.toggleSong) self.playbackButtons.buttonStop.clicked.connect(self.stop) self.playbackButtons.buttonPrev.clicked.connect(self.previous) self.playbackButtons.buttonNext.clicked.connect(self.next) self.volumeSlider = VolumeSlider(self) self.volumeSlider.sliderMoved.connect(self.player.setVolume) self.scrollSlider = ScrollSlider(self) self.scrollSlider.sliderPressed.connect(self.player.toggle) self.scrollSlider.sliderReleased.connect(self.player.toggle) self.scrollSlider.sliderMoved.connect(self.player.seek) self.pixmap = Image(self, config['cover_names'], config['extensions']) # Album cover connections self.tree.selectionModel().selectionChanged.connect( lambda: self.pixmap.onSelectionChanged(self.tree.getChildren()[0]. get('file', None))) self.table.selectionModel().selectionChanged.connect( lambda: self.pixmap.onSelectionChanged(self.table.getSelection(). get('file', None))) self.searchArea = SearchArea(self) self.searchArea.searchLine.returnPressed.connect(self.startSearch) self.playbackButtons.addWidget(self.volumeSlider) self.playbackButtons.addWidget(self.scrollSlider) splitterLeftRight = QtGui.QSplitter() self.splitterTopBottom = QtGui.QSplitter(Qt.Vertical, self) self.infoFrame = QtGui.QFrame() infoLayout = QtGui.QVBoxLayout() infoLayout.setContentsMargins(0, 0, 0, 0) infoLayout.addLayout(self.playbackButtons) infoLayout.addWidget(self.pixmap) self.infoFrame.setLayout(infoLayout) libLayout = QtGui.QVBoxLayout() libLayout.setContentsMargins(0, 0, 0, 0) libLayout.addWidget(self.tree) libLayout.addLayout(self.searchArea) libFrame = QtGui.QFrame() libFrame.setLayout(libLayout) self.splitterTopBottom.addWidget(self.table) self.splitterTopBottom.addWidget(self.infoFrame) self.splitterTopBottom.setStretchFactor(0, 1) #self.splitterTopBottom.setStretchFactor(1,0) splitterLeftRight.addWidget(libFrame) splitterLeftRight.addWidget(self.splitterTopBottom) splitterLeftRight.setStretchFactor(0, 2) splitterLeftRight.setStretchFactor(1, 3) mainLayout = QtGui.QGridLayout() mainLayout.setContentsMargins(4, 4, 4, 4) mainLayout.addWidget(splitterLeftRight) dummyWidget = QtGui.QWidget() dummyWidget.setLayout(mainLayout) self.setCentralWidget(dummyWidget) self.setTabOrder(self.tree, self.table) dictShortcuts = self.readConfig('shortcuts') modifier = dictShortcuts['modifier'] + '+' self.shortQuit = QtGui.QShortcut( QtGui.QKeySequence(modifier + dictShortcuts['quit']), self, self.close) self.shortStop = QtGui.QShortcut( QtGui.QKeySequence(modifier + dictShortcuts['stop']), self, self.stop) self.shortPlayPause = QtGui.QShortcut( QtGui.QKeySequence(modifier + dictShortcuts['play_pause']), self, self.toggleSong) self.shortSongPrevious = QtGui.QShortcut( QtGui.QKeySequence(modifier + dictShortcuts['previous']), self, self.previous) self.shortSongNext = QtGui.QShortcut( QtGui.QKeySequence(modifier + dictShortcuts['next']), self, self.next) self.shortVolDown = QtGui.QShortcut( QtGui.QKeySequence(modifier + dictShortcuts['volume_down']), self, self.volumeSlider.decr) self.shortVolUp = QtGui.QShortcut( QtGui.QKeySequence(modifier + dictShortcuts['volume_up']), self, self.volumeSlider.incr) self.shortRadioMode = QtGui.QShortcut( QtGui.QKeySequence(modifier + dictShortcuts['radio_mode']), self, self.toggleRadio) self.shortEqualizer = QtGui.QShortcut( QtGui.QKeySequence(modifier + dictShortcuts['equalizer']), self, self.openEqualizer) thread = QtCore.QThread(self) thread.worker = WorkThreadPipe() thread.worker.moveToThread(thread) thread.started.connect(thread.worker.process) thread.worker.hotKey.connect(self.onHotKey) thread.worker.finished.connect(thread.quit) thread.worker.finished.connect(thread.worker.deleteLater) thread.finished.connect(thread.deleteLater) thread.start() self.show() def keyReleaseEvent(self, event): if event.key() == Qt.Key_Alt: self.menuBar().setVisible(not self.menuBar().isVisible()) else: QWidget.keyPressEvent(self, event) # Triggered by player end of stream event # or called by hand to stop the stream def stop(self, bus=None, msg=None): self.player.stop() self.scrollSlider.setValue(0) self.table.displayPlayToStop() self.stopStatusEmission('Ready') def previous(self): if self.table.playingId > 0: self.player.stop() self.table.playingId -= 1 self.player.add(self.table.model().item(self.table.playingId, 0).data()['file']) self.player.play() def next(self): if self.table.model().rowCount() - 1 > self.table.playingId: self.player.stop() self.table.playingId += 1 self.player.add(self.table.model().item(self.table.playingId, 0).data()['file']) self.player.play() def toggleSong(self): state = self.player.playbin.get_state(Gst.State.NULL) if state[1] == Gst.State.PLAYING: self.table.displayPlayToPause() self.player.toggle() status = self.statusBar().currentMessage().replace( 'Playing', 'Paused') self.stopStatusEmission(status) else: self.table.displayPauseToPlay(self.table.playingId) self.player.toggle() #self.onDurationChanged(0,0) status = self.table.getStatus() self.setStatusEmission(status) # Triggered by player when a song starts def onDurationChanged(self, bus, msg): self.table.displayNext() print('Duration changed signal !') filename = self.table.model().item(self.table.playingId, 0).data()['file'][7:] data = wave.getDBData(filename) wave.createImg(data) self.scrollSlider.setStyleSheet("border-image: url(./wave.png)") # Triggered by player at the end of a song def onAboutToFinish(self, bus): if self.table.model().rowCount() - 1 > self.table.playingId: print('About to finish !') self.table.playingId += 1 self.player.add(self.table.model().item(self.table.playingId, 0).data()['file']) def addSongsFromTree(self, list, play): if not self.radio: i = self.table.model().rowCount() for l in list: self.table.addRow(l) self.table.resizeRowsToContents() if play: self.stop() self.player.add(list[0]['file']) self.player.play() self.table.displayStopToPlay(i) status = self.table.getStatus() self.setStatusEmission(status) def setStatusEmission(self, status): if self.timeOut > 0: GObject.source_remove(self.timeOut) self.timeOut = GObject.timeout_add(1000, self.update, status) def stopStatusEmission(self, status): if self.timeOut > 0: GObject.source_remove(self.timeOut) self.timeOut = GObject.timeout_add(0, self.update, status) self.timeOut = -1 def update(self, status): print('.') try: duration_nanosecs = self.player.getDuration() duration = float(duration_nanosecs) / 1000000000 self.scrollSlider.setRange(0, duration) nanosecs = self.player.getPosition() position = float(nanosecs) // 1000000000 self.scrollSlider.setValue(position) m, s = divmod(position, 60) self.statusBar().showMessage( status.replace('%', "%02d:%02d" % (m, s))) except Exception as e: print(e) pass if 'Playing' in status: return True else: return False def tableAction(self, str): if str == 'stop': self.stop() elif str == 'play': if self.table.selectedIndexes(): index = self.table.selectedIndexes()[0] else: index = self.table.model().index( self.table.selectionModel().currentIndex().row(), 0) songURI = index.model().itemFromIndex(index).data()['file'] self.player.stop() self.player.add(songURI) self.player.play() self.table.displayStopToPlay(index.row()) status = self.table.getStatus() self.setStatusEmission(status) @staticmethod def readConfig(section): parser = RawConfigParser() if getattr(sys, 'frozen', False): # frozen parser.read( os.path.dirname(os.path.realpath(sys.executable)) + '/config') else: # unfrozen parser.read( os.path.dirname(os.path.realpath(__file__)) + '/config') return dict(parser.items(section)) #Create menu bar def createMenu(self): self.menuBar() self.menuBar().setVisible(False) actionMenu = self.menuBar().addMenu('&Action') scanMusicFolderAction = QtGui.QAction('Scan Music Folder', self) showShortcutAction = QtGui.QAction('Show Shortcut', self) addFolderToLibraryAction = QtGui.QAction('Add Folder to Library', self) scanWaveformsAction = QtGui.QAction('Scan wave froms', self) #self.toggleRadioAction= QtGui.QAction('Switch to Radio mode',self) if not self.radio: self.toggleRadioAction = QtGui.QAction('Switch to Radio mode', self) else: self.toggleRadioAction = QtGui.QAction('Switch to Library mode', self) scanMusicFolderAction.triggered.connect(self.scanMusicFolder) actionMenu.addAction(scanMusicFolderAction) showShortcutAction.triggered.connect(self.showShortcut) actionMenu.addAction(showShortcutAction) addFolderToLibraryAction.triggered.connect(self.addFolderToLibrary) actionMenu.addAction(addFolderToLibraryAction) scanWaveformsAction.triggered.connect(self.scanWaveforms) actionMenu.addAction(scanWaveformsAction) self.toggleRadioAction.triggered.connect(self.toggleRadio) actionMenu.addAction(self.toggleRadioAction) # Menu Action 1 def scanMusicFolder(self): thread = QtCore.QThread(self) thread.worker = WorkThread( Foo.readConfig('options')['music_folder'], False) thread.worker.moveToThread(thread) thread.started.connect(thread.worker.process) thread.worker.finished.connect(thread.quit) thread.worker.finished.connect(thread.worker.deleteLater) thread.finished.connect(thread.deleteLater) thread.finished.connect(self.tree.initUI) thread.start() # Menu Action 2 def showShortcut(self): dictSC = Foo.readConfig('shortcuts') message = '''<b>''' + dictSC['modifier'] + '''+''' + dictSC[ 'stop'] + '''</b> : Stop<br/>''' + ''' <b>''' + dictSC['modifier'] + '''+''' + dictSC['quit'] + '''</b> : Quit<br/>''' + ''' <b>''' + dictSC['modifier'] + '''+''' + dictSC[ 'play_pause'] + '''</b> : Play/Pause <br/>''' + ''' <b>''' + dictSC['modifier'] + '''+''' + dictSC[ 'previous'] + '''</b> : Previous<br/>''' + ''' <b>''' + dictSC['modifier'] + '''+''' + dictSC['next'] + '''</b> : Next<br/>''' + ''' <b>''' + dictSC['modifier'] + '''+''' + dictSC[ 'volume_down'] + '''</b> : Volume down<br/>''' + ''' <b>''' + dictSC['modifier'] + '''+''' + dictSC[ 'volume_up'] + '''</b> : Volume up<br/>''' + ''' <b>''' + dictSC['modifier'] + '''+''' + dictSC[ 'radio_mode'] + '''</b> : Toggle radio mode<br/>''' + ''' <b>''' + dictSC['modifier'] + '''+''' + dictSC[ 'equalizer'] + '''</b> : Equalizer<br/>''' print(len(self.findChildren(QtCore.QObject))) box = QMessageBox.about(self, 'About Shortcuts', message) print(len(self.findChildren(QtCore.QObject))) print('must delete') # Menu Action3 # Must be subdirectory of music folder otherwise wont be rescanned def addFolderToLibrary(self): dir = QFileDialog.getExistingDirectory( None, "Open Directory", Foo.readConfig('options')['music_folder'], QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) thread = QtCore.QThread(self) thread.worker = WorkThread(dir, True) thread.worker.moveToThread(thread) thread.started.connect(thread.worker.process) thread.worker.finished.connect(thread.quit) thread.worker.finished.connect(thread.worker.deleteLater) thread.finished.connect(thread.deleteLater) thread.finished.connect(self.tree.initUI) thread.start() # Menu action 4 def scanWaveforms(self): from wave import Wave thread = QtCore.QThread(self) thread.worker = Wave(Foo.readConfig('options')['music_folder']) thread.worker.moveToThread(thread) thread.started.connect(thread.worker.processScan) thread.worker.finished.connect(thread.quit) thread.worker.finished.connect(thread.worker.deleteLater) thread.finished.connect(thread.deleteLater) thread.finished.connect(self.tree.initUI) thread.start() # Menu Action5 def toggleRadio(self): self.table.deleteLater() self.table.close() if not self.radio: configRadio = Foo.readConfig('radios') self.table = TableRadio(self.tree, configRadio) self.toggleRadioAction.setText('Switch to Library mode') self.radio = True self.player.playbin.disconnect(self.handlerATF) self.handlerT = self.player.bus.connect('message::tag', self.table.onTag) else: config = Foo.readConfig('options') self.table = Table(self.tree, config) self.toggleRadioAction.setText('Switch to Radio mode') self.radio = False self.handlerATF = self.player.playbin.connect( "about-to-finish", self.onAboutToFinish) self.player.bus.disconnect(self.handlerT) self.splitterTopBottom.addWidget(self.table) # Since the frame is already attached to the splitter, # it only moves it to the new position self.splitterTopBottom.addWidget(self.infoFrame) self.table.runAction.connect(self.tableAction) self.setTabOrder(self.tree, self.table) self.splitterTopBottom.setStretchFactor(0, 10) #self.splitterTopBottom.setStretchFactor(3,1) @QtCore.pyqtSlot() def startSearch(self): input = self.searchArea.searchLine.text() db = thread.load() songList = [] songGenerator = (Song(self.tree.comm, **dict) for dict in db) self.tree.model().removeRows(0, self.tree.model().rowCount()) if self.searchArea.searchExact.isChecked(): songList = [e for e in songGenerator if e.exactMatch(input)] elif self.searchArea.searchPrecise.isChecked(): songList = [e for e in songGenerator if e.preciseMatch(input)] else: songList = [e for e in songGenerator if e.fuzzyMatch(input)] del db[:] songList.sort(key=self.tree.sortFunc) self.tree.populateTree(songList) @QtCore.pyqtSlot(str) def onHotKey(self, key): print('Hotkey was pressed', key) if key == 'quit': self.shortQuit.activated.emit() if key == 'stop': self.shortStop.activated.emit() if key == 'play_pause': self.shortPlayPause.activated.emit() if key == 'volume_up': self.shortVolUp.activated.emit() if key == 'volume_down': self.shortVolDown.activated.emit() if key == 'song_next': self.shortSongNext.activated.emit() if key == 'song_prev': self.shortSongPrev.activated.emit() if key == 'tree_up': if self.radio: self.table.keyPressEvent( QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Up, Qt.KeyboardModifier(), '')) else: self.tree.keyPressEvent( QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Up, Qt.KeyboardModifier(), '')) if key == 'tree_down': if self.radio: self.table.keyPressEvent( QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Down, Qt.KeyboardModifier(), '')) else: self.tree.keyPressEvent( QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Down, Qt.KeyboardModifier(), '')) if key == 'tree_left': if not self.radio: self.tree.keyPressEvent( QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Left, Qt.KeyboardModifier(), '')) if key == 'tree_right': if not self.radio: self.tree.keyPressEvent( QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Right, Qt.KeyboardModifier(), '')) if key == 'tree_validate': if self.radio: self.table.keyPressEvent( QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Return, Qt.KeyboardModifier(), '')) else: self.tree.keyPressEvent( QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Return, Qt.KeyboardModifier(), '')) if key == 'tree_append': if not self.radio: self.tree.keyPressEvent( QtGui.QKeyEvent( QtCore.QEvent.KeyPress, Qt.Key_Return, Qt.KeyboardModifier(QtCore.Qt.ShiftModifier), '')) if key == 'radio_mode': self.shortRadioMode.activated.emit() def tmpTag(self, position): menu = QtGui.QMenu() tagging = QtGui.QAction('Tagging', self) replayGain = QtGui.QAction('ReplayGain', self) tagging.triggered.connect(self.openTagging) replayGain.triggered.connect(self.startReplayGain) menu.addAction(tagging) menu.addAction(replayGain) menu.exec_(self.tree.viewport().mapToGlobal(position)) def startReplayGain(self): children = self.tree.getChildren() self.RG = ReplayGain([x['file'] for x in children]) self.RG.exec_() def openTagging(self): children = self.tree.getChildren() #[7:] to drop the 'file://' appended for gstreamer retag = Retagging([x['file'][7:] for x in children]) res = retag.exec_() if res: self.tree.initUI() print(res) def openEqualizer(self): from configparser import RawConfigParser equa = Equalizer(self, Foo.readConfig('audio')) equa.equalize.connect(self.applyEqua) if equa.exec_(): parser = RawConfigParser() parser.read( os.path.dirname(os.path.realpath(__file__)) + '/config') parser['audio']['settings'] = str(equa.config) with open( os.path.dirname(os.path.realpath(__file__)) + '/config', 'w') as configfile: parser.write(configfile) def applyEqua(self, band, value): print('receiving equa', str(band), value) if str(band) == 'band0' and value == 0: self.player.equalizer.set_property('band0', 0.01) else: self.player.equalizer.set_property(str(band), value)
def _getMrBayesSampleTree(self, sampNum): savedDoFastNextTok = var.nexus_doFastNextTok var.nexus_doFastNextTok = False tLine = self.tLines[sampNum] if self.verbose >= 3: print tLine f = cStringIO.StringIO(tLine) t = Tree() t.parseNexus(f, translationHash=self.translationHash, doModelComments=self.tree.model.nParts) # doModelComments is nParts var.nexus_doFastNextTok = savedDoFastNextTok t.taxNames = self.tree.taxNames for n in t.iterLeavesNoRoot(): n.seqNum = t.taxNames.index(n.name) t.model = copy.deepcopy(self.model) pLine = self.pLines[sampNum] if self.verbose >= 3: print pLine splitPLine = pLine.split() pGenNum = int(splitPLine[0]) splitTName = t.name.split('.') tGenNum = int(splitTName[1]) if tGenNum != pGenNum: raise P4Error( "something wrong. tGenNum=%i, pGenNum=%i" % (tGenNum, pGenNum)) if self.verbose >= 2: print "(zero-based) sample %i is gen %i" % (sampNum, tGenNum) # t.model.dump() splIndx = 3 # but could be Gen LnL LnPr TL ... while splIndx < self.nPrams: pNum = 0 # print "splIndx = %i, pramsHeader = %s" % (splIndx, # self.pramsHeader[splIndx]) if self.pramsHeader[splIndx].startswith('r(A<->C)'): if self.tree.model.nParts > 1: try: splitPramHeader = self.pramsHeader[ splIndx].split('{')[1][:-1] pNum = int(splitPramHeader) pNum -= 1 except: raise P4Error("could not get the part number") thisSum = 0.0 for i in range(6): theFloat = float(splitPLine[splIndx]) t.model.parts[pNum].rMatrices[0].val[i] = theFloat thisSum += theFloat splIndx += 1 factor = 1.0 / thisSum # must sum to one for i in range(6): t.model.parts[pNum].rMatrices[0].val[i] *= factor elif self.pramsHeader[splIndx].startswith('pi(A)'): if self.tree.model.nParts > 1: try: splitPramHeader = self.pramsHeader[ splIndx].split('{')[1][:-1] pNum = int(splitPramHeader) pNum -= 1 except: raise P4Error("could not get the part number") thisSum = 0.0 for i in range(4): theFloat = float(splitPLine[splIndx]) t.model.parts[pNum].comps[0].val[i] = theFloat thisSum += theFloat splIndx += 1 factor = 1.0 / thisSum # must sum to one for i in range(4): t.model.parts[pNum].comps[0].val[i] *= factor elif self.pramsHeader[splIndx].startswith('alpha'): if self.tree.model.nParts > 1: try: splitPramHeader = self.pramsHeader[ splIndx].split('{')[1][:-1] pNum = int(splitPramHeader) pNum -= 1 except: raise P4Error("could not get the part number") # print "got pNum = %i" % pNum # print "got splitPLine[%i] = %s" % (splIndx, # splitPLine[splIndx]) t.model.parts[pNum].gdasrvs[0].val[ 0] = float(splitPLine[splIndx]) splIndx += 1 elif self.pramsHeader[splIndx].startswith('pinvar'): if self.tree.model.nParts > 1: try: splitPramHeader = self.pramsHeader[ splIndx].split('{')[1][:-1] pNum = int(splitPramHeader) pNum -= 1 except: raise P4Error("could not get the part number") t.model.parts[pNum].pInvar.val = float(splitPLine[splIndx]) splIndx += 1 elif self.pramsHeader[splIndx].startswith('m'): if self.tree.model.nParts > 1: try: splitPramHeader = self.pramsHeader[ splIndx].split('{')[1][:-1] pNum = int(splitPramHeader) pNum -= 1 except: raise P4Error("could not get the part number") t.model.parts[pNum].relRate = float(splitPLine[splIndx]) splIndx += 1 else: print "splIndx=%i. Got unknown pram %s. Fix me!" % (splIndx, self.pramsHeader[splIndx]) splIndx += 1 if splIndx != len(splitPLine): raise P4Error("Something is wrong. After reading, splIndx=%i, but len split pram line=%i" % ( splIndx, len(splitPLine))) return t
class Foo(QtGui.QMainWindow): def __init__(self): super(Foo, self).__init__() self.initUI() def initUI(self): config = Foo.readConfig('options') self.timeOut = -1 self.radio = False self.statusBar().showMessage('Ready') self.createMenu() self.setWindowTitle("Foo.cd") self.player = Player(Foo.readConfig('audio')) self.player.bus.connect('message::eos', self.stop) self.player.bus.connect('message::duration-changed', self.onDurationChanged) self.tree = Tree(self, config['tree_order']) self.tree.addSongs.connect(self.addSongsFromTree) self.tree.customContextMenuRequested.connect(self.tmpTag) if not self.radio: self.table=Table( self, config) self.handlerATF = self.player.playbin.connect("about-to-finish", self.onAboutToFinish) self.table.runAction.connect(self.tableAction) else: configRadio = Foo.readConfigRadios() self.table=TableRadio( self, configRadio) self.table.runAction.connect(self.tableAction) self.handlerT = self.player.bus.connect('message::tag', self.table.onTag) self.playbackButtons = PlaybackButtons(None) self.playbackButtons.buttonPlay.clicked.connect(self.toggleSong) self.playbackButtons.buttonStop.clicked.connect(self.stop) self.playbackButtons.buttonPrev.clicked.connect(self.previous) self.playbackButtons.buttonNext.clicked.connect(self.next) self.volumeSlider = VolumeSlider(self) self.volumeSlider.sliderMoved.connect(self.player.setVolume) self.scrollSlider = ScrollSlider(self) self.scrollSlider.sliderPressed.connect(self.player.toggle) self.scrollSlider.sliderReleased.connect(self.player.toggle) self.scrollSlider.sliderMoved.connect(self.player.seek) self.pixmap = Image(self, config['cover_names'], config['extensions']) # Album cover connections self.tree.selectionModel().selectionChanged.connect(lambda: self.pixmap.onSelectionChanged(self.tree.getChildren()[0].get('file', None))) self.table.selectionModel().selectionChanged.connect(lambda: self.pixmap.onSelectionChanged(self.table.getSelection().get('file', None))) self.searchArea = SearchArea(self) self.searchArea.searchLine.returnPressed.connect(self.startSearch) self.playbackButtons.addWidget(self.volumeSlider) self.playbackButtons.addWidget(self.scrollSlider) splitterLeftRight = QtGui.QSplitter() self.splitterTopBottom = QtGui.QSplitter(Qt.Vertical, self) self.infoFrame = QtGui.QFrame() infoLayout = QtGui.QVBoxLayout() infoLayout.setContentsMargins(0,0,0,0) infoLayout.addLayout(self.playbackButtons) infoLayout.addWidget(self.pixmap) self.infoFrame.setLayout(infoLayout) libLayout = QtGui.QVBoxLayout() libLayout.setContentsMargins(0,0,0,0) libLayout.addWidget(self.tree) libLayout.addLayout(self.searchArea) libFrame = QtGui.QFrame() libFrame.setLayout(libLayout) self.splitterTopBottom.addWidget(self.table) self.splitterTopBottom.addWidget(self.infoFrame) self.splitterTopBottom.setStretchFactor(0,1) #self.splitterTopBottom.setStretchFactor(1,0) splitterLeftRight.addWidget(libFrame) splitterLeftRight.addWidget(self.splitterTopBottom) splitterLeftRight.setStretchFactor(0,2) splitterLeftRight.setStretchFactor(1,3) mainLayout = QtGui.QGridLayout() mainLayout.setContentsMargins(4, 4, 4, 4) mainLayout.addWidget(splitterLeftRight) dummyWidget = QtGui.QWidget() dummyWidget.setLayout(mainLayout) self.setCentralWidget(dummyWidget) self.setTabOrder(self.tree, self.table) dictShortcuts = self.readConfig('shortcuts') modifier = dictShortcuts['modifier']+'+' self.shortQuit = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['quit']), self, self.close) self.shortStop = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['stop']), self, self.stop) self.shortPlayPause = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['play_pause']), self, self.toggleSong) self.shortSongPrevious = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['previous']), self, self.previous) self.shortSongNext = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['next']), self, self.next) self.shortVolDown = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['volume_down']), self, self.volumeSlider.decr) self.shortVolUp = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['volume_up']), self, self.volumeSlider.incr) self.shortRadioMode = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['radio_mode']), self, self.toggleRadio) self.shortEqualizer = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['equalizer']), self, self.openEqualizer) thread = QtCore.QThread(self) thread.worker = WorkThreadPipe() thread.worker.moveToThread(thread); thread.started.connect(thread.worker.process) thread.worker.hotKey.connect(self.onHotKey) thread.worker.finished.connect(thread.quit) thread.worker.finished.connect(thread.worker.deleteLater) thread.finished.connect(thread.deleteLater) thread.start() self.show() def keyReleaseEvent(self, event): if event.key() == Qt.Key_Alt: self.menuBar().setVisible(not self.menuBar().isVisible()) else: QWidget.keyPressEvent(self, event) # Triggered by player end of stream event # or called by hand to stop the stream def stop(self, bus=None, msg=None): self.player.stop() self.scrollSlider.setValue(0) self.table.displayPlayToStop() self.stopStatusEmission('Ready') def previous(self): if self.table.playingId > 0: self.player.stop() self.table.playingId-=1 self.player.add(self.table.model().item(self.table.playingId,0).data()['file']) self.player.play() def next(self): if self.table.model().rowCount()-1 > self.table.playingId: self.player.stop() self.table.playingId+=1 self.player.add(self.table.model().item(self.table.playingId,0).data()['file']) self.player.play() def toggleSong(self): state = self.player.playbin.get_state(Gst.State.NULL) if state[1] == Gst.State.PLAYING: self.table.displayPlayToPause() self.player.toggle() status = self.statusBar().currentMessage().replace('Playing', 'Paused') self.stopStatusEmission(status) else: self.table.displayPauseToPlay(self.table.playingId) self.player.toggle() #self.onDurationChanged(0,0) status = self.table.getStatus() self.setStatusEmission(status) # Triggered by player when a song starts def onDurationChanged(self, bus, msg): self.table.displayNext() print('Duration changed signal !') filename = self.table.model().item(self.table.playingId,0).data()['file'][7:] data = wave.getDBData(filename) wave.createImg(data) self.scrollSlider.setStyleSheet("border-image: url(./wave.png)") # Triggered by player at the end of a song def onAboutToFinish(self, bus): if self.table.model().rowCount()-1 > self.table.playingId: print('About to finish !') self.table.playingId+=1 self.player.add(self.table.model().item(self.table.playingId,0).data()['file']) def addSongsFromTree(self, list, play): if not self.radio: i = self.table.model().rowCount() for l in list: self.table.addRow(l) self.table.resizeRowsToContents() if play: self.stop() self.player.add(list[0]['file']) self.player.play() self.table.displayStopToPlay(i) status = self.table.getStatus() self.setStatusEmission(status) def setStatusEmission(self, status): if self.timeOut > 0: GObject.source_remove(self.timeOut) self.timeOut = GObject.timeout_add(1000, self.update, status) def stopStatusEmission(self, status): if self.timeOut > 0: GObject.source_remove(self.timeOut) self.timeOut = GObject.timeout_add(0, self.update, status) self.timeOut=-1 def update(self, status): print('.') try: duration_nanosecs = self.player.getDuration() duration = float(duration_nanosecs) / 1000000000 self.scrollSlider.setRange(0, duration) nanosecs = self.player.getPosition() position = float(nanosecs) // 1000000000 self.scrollSlider.setValue(position) m, s = divmod(position, 60) self.statusBar().showMessage(status.replace('%',"%02d:%02d" % (m, s))) except Exception as e: print(e) pass if 'Playing' in status: return True else: return False def tableAction(self, str): if str == 'stop': self.stop() elif str == 'play': if self.table.selectedIndexes(): index = self.table.selectedIndexes()[0] else: index= self.table.model().index(self.table.selectionModel().currentIndex().row(),0) songURI = index.model().itemFromIndex(index).data()['file'] self.player.stop() self.player.add(songURI) self.player.play() self.table.displayStopToPlay(index.row()) status = self.table.getStatus() self.setStatusEmission(status) @staticmethod def readConfig(section): parser = RawConfigParser() if getattr(sys, 'frozen', False): # frozen parser.read(os.path.dirname(os.path.realpath(sys.executable))+'/config') else: # unfrozen parser.read(os.path.dirname(os.path.realpath(__file__))+'/config') return dict(parser.items(section)) #Create menu bar def createMenu(self): self.menuBar() self.menuBar().setVisible(False) actionMenu = self.menuBar().addMenu('&Action') scanMusicFolderAction = QtGui.QAction('Scan Music Folder', self) showShortcutAction = QtGui.QAction('Show Shortcut',self) addFolderToLibraryAction = QtGui.QAction('Add Folder to Library',self) scanWaveformsAction = QtGui.QAction('Scan wave froms',self) #self.toggleRadioAction= QtGui.QAction('Switch to Radio mode',self) if not self.radio: self.toggleRadioAction= QtGui.QAction('Switch to Radio mode',self) else: self.toggleRadioAction= QtGui.QAction('Switch to Library mode',self) scanMusicFolderAction.triggered.connect(self.scanMusicFolder) actionMenu.addAction(scanMusicFolderAction) showShortcutAction.triggered.connect(self.showShortcut) actionMenu.addAction(showShortcutAction) addFolderToLibraryAction.triggered.connect(self.addFolderToLibrary) actionMenu.addAction(addFolderToLibraryAction) scanWaveformsAction.triggered.connect(self.scanWaveforms) actionMenu.addAction(scanWaveformsAction) self.toggleRadioAction.triggered.connect(self.toggleRadio) actionMenu.addAction(self.toggleRadioAction) # Menu Action 1 def scanMusicFolder(self): thread = QtCore.QThread(self) thread.worker = WorkThread(Foo.readConfig('options')['music_folder'], False) thread.worker.moveToThread(thread) thread.started.connect(thread.worker.process) thread.worker.finished.connect(thread.quit) thread.worker.finished.connect(thread.worker.deleteLater) thread.finished.connect(thread.deleteLater) thread.finished.connect(self.tree.initUI) thread.start() # Menu Action 2 def showShortcut(self): dictSC = Foo.readConfig('shortcuts') message = '''<b>'''+dictSC['modifier']+'''+'''+dictSC['stop']+'''</b> : Stop<br/>''' + ''' <b>'''+dictSC['modifier']+'''+'''+dictSC['quit']+'''</b> : Quit<br/>''' + ''' <b>'''+dictSC['modifier']+'''+'''+dictSC['play_pause']+'''</b> : Play/Pause <br/>''' + ''' <b>'''+dictSC['modifier']+'''+'''+dictSC['previous']+'''</b> : Previous<br/>''' + ''' <b>'''+dictSC['modifier']+'''+'''+dictSC['next']+'''</b> : Next<br/>''' + ''' <b>'''+dictSC['modifier']+'''+'''+dictSC['volume_down']+'''</b> : Volume down<br/>''' + ''' <b>'''+dictSC['modifier']+'''+'''+dictSC['volume_up']+'''</b> : Volume up<br/>''' + ''' <b>'''+dictSC['modifier']+'''+'''+dictSC['radio_mode']+'''</b> : Toggle radio mode<br/>''' + ''' <b>'''+dictSC['modifier']+'''+'''+dictSC['equalizer']+'''</b> : Equalizer<br/>''' print(len(self.findChildren(QtCore.QObject))) box = QMessageBox.about(self, 'About Shortcuts', message) print(len(self.findChildren(QtCore.QObject))) print('must delete') # Menu Action3 # Must be subdirectory of music folder otherwise wont be rescanned def addFolderToLibrary(self): dir = QFileDialog.getExistingDirectory(None, "Open Directory", Foo.readConfig('options')['music_folder'], QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) thread = QtCore.QThread(self) thread.worker = WorkThread(dir, True) thread.worker.moveToThread(thread) thread.started.connect(thread.worker.process) thread.worker.finished.connect(thread.quit) thread.worker.finished.connect(thread.worker.deleteLater) thread.finished.connect(thread.deleteLater) thread.finished.connect(self.tree.initUI) thread.start() # Menu action 4 def scanWaveforms(self): from wave import Wave thread = QtCore.QThread(self) thread.worker = Wave(Foo.readConfig('options')['music_folder']) thread.worker.moveToThread(thread) thread.started.connect(thread.worker.processScan) thread.worker.finished.connect(thread.quit) thread.worker.finished.connect(thread.worker.deleteLater) thread.finished.connect(thread.deleteLater) thread.finished.connect(self.tree.initUI) thread.start() # Menu Action5 def toggleRadio(self): self.table.deleteLater() self.table.close() if not self.radio: configRadio = Foo.readConfig('radios') self.table=TableRadio(self.tree, configRadio) self.toggleRadioAction.setText('Switch to Library mode') self.radio=True self.player.playbin.disconnect(self.handlerATF) self.handlerT=self.player.bus.connect('message::tag', self.table.onTag) else: config = Foo.readConfig('options') self.table=Table( self.tree, config) self.toggleRadioAction.setText('Switch to Radio mode') self.radio=False self.handlerATF = self.player.playbin.connect("about-to-finish",self.onAboutToFinish) self.player.bus.disconnect(self.handlerT) self.splitterTopBottom.addWidget(self.table) # Since the frame is already attached to the splitter, # it only moves it to the new position self.splitterTopBottom.addWidget(self.infoFrame) self.table.runAction.connect(self.tableAction) self.setTabOrder(self.tree, self.table) self.splitterTopBottom.setStretchFactor(0,10) #self.splitterTopBottom.setStretchFactor(3,1) @QtCore.pyqtSlot() def startSearch(self): input = self.searchArea.searchLine.text() db = thread.load() songList = [] songGenerator = (Song(self.tree.comm, **dict) for dict in db) self.tree.model().removeRows(0, self.tree.model().rowCount()) if self.searchArea.searchExact.isChecked(): songList = [ e for e in songGenerator if e.exactMatch(input) ] elif self.searchArea.searchPrecise.isChecked(): songList = [ e for e in songGenerator if e.preciseMatch(input) ] else: songList = [ e for e in songGenerator if e.fuzzyMatch(input) ] del db[:] songList.sort(key=self.tree.sortFunc) self.tree.populateTree(songList) @QtCore.pyqtSlot(str) def onHotKey(self, key): print('Hotkey was pressed', key) if key == 'quit': self.shortQuit.activated.emit() if key == 'stop': self.shortStop.activated.emit() if key == 'play_pause': self.shortPlayPause.activated.emit() if key == 'volume_up': self.shortVolUp.activated.emit() if key == 'volume_down': self.shortVolDown.activated.emit() if key == 'song_next': self.shortSongNext.activated.emit() if key == 'song_prev': self.shortSongPrev.activated.emit() if key == 'tree_up': if self.radio: self.table.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Up, Qt.KeyboardModifier(), '')) else: self.tree.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Up, Qt.KeyboardModifier(), '')) if key == 'tree_down': if self.radio: self.table.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Down, Qt.KeyboardModifier(), '')) else: self.tree.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Down, Qt.KeyboardModifier(), '')) if key == 'tree_left': if not self.radio: self.tree.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Left, Qt.KeyboardModifier(), '')) if key == 'tree_right': if not self.radio: self.tree.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Right, Qt.KeyboardModifier(), '')) if key == 'tree_validate': if self.radio: self.table.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Return, Qt.KeyboardModifier(), '')) else: self.tree.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Return, Qt.KeyboardModifier(), '')) if key == 'tree_append': if not self.radio: self.tree.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Return, Qt.KeyboardModifier(QtCore.Qt.ShiftModifier), '')) if key == 'radio_mode': self.shortRadioMode.activated.emit() def tmpTag(self, position): menu = QtGui.QMenu() tagging = QtGui.QAction('Tagging',self) replayGain = QtGui.QAction('ReplayGain',self) tagging.triggered.connect(self.openTagging) replayGain.triggered.connect(self.startReplayGain) menu.addAction(tagging) menu.addAction(replayGain) menu.exec_(self.tree.viewport().mapToGlobal(position)) def startReplayGain(self): children = self.tree.getChildren() self.RG = ReplayGain([x['file'] for x in children]) self.RG.exec_() def openTagging(self): children = self.tree.getChildren() #[7:] to drop the 'file://' appended for gstreamer retag = Retagging([x['file'][7:] for x in children]) res = retag.exec_() if res: self.tree.initUI() print(res) def openEqualizer(self): from configparser import RawConfigParser equa = Equalizer(self, Foo.readConfig('audio')) equa.equalize.connect(self.applyEqua) if equa.exec_(): parser = RawConfigParser() parser.read(os.path.dirname(os.path.realpath(__file__))+'/config') parser['audio']['settings']= str(equa.config) with open(os.path.dirname(os.path.realpath(__file__))+'/config', 'w') as configfile: parser.write(configfile) def applyEqua(self,band, value): print('receiving equa', str(band), value) if str(band) == 'band0' and value == 0: self.player.equalizer.set_property('band0', 0.01) else: self.player.equalizer.set_property(str(band), value)
def _getP4SampleTree(self, sampNum): savedDoFastNextTok = var.nexus_doFastNextTok var.nexus_doFastNextTok = False tLine = self.tLines[sampNum] if self.verbose >= 3: print tLine f = cStringIO.StringIO(tLine) t = Tree() t.parseNexus(f, translationHash=self.translationHash, doModelComments=self.tree.model.nParts) var.nexus_doFastNextTok = savedDoFastNextTok t.taxNames = self.tree.taxNames for n in t.iterLeavesNoRoot(): n.seqNum = t.taxNames.index(n.name) t.model = copy.deepcopy(self.model) if self.tree.model.nFreePrams: pLine = self.pLines[sampNum] if self.verbose >= 3: print pLine splitPLine = pLine.split() pGenNum = int(splitPLine[0]) splitTName = t.name.split('_') tGenNum = int(splitTName[1]) if tGenNum != pGenNum: raise P4Error( "something wrong. tGenNum=%i, pGenNum=%i" % (tGenNum, pGenNum)) if self.verbose >= 2: print "(zero-based) sample %i is gen %i" % (sampNum, tGenNum) # t.model.dump() splIndx = 1 for pNum in range(len(self.pramsProfile)): compNum = 0 rMatrixNum = 0 gdasrvNum = 0 for desc in self.pramsProfile[pNum]: if desc[0] == 'relRate': t.model.parts[pNum].relRate = float( splitPLine[splIndx]) splIndx += 1 elif desc[0] == 'comp': vv = [] for i in range(desc[1]): vv.append(float(splitPLine[splIndx])) splIndx += 1 for i in range(desc[1]): if vv[i] < var.PIVEC_MIN: vv[i] = var.PIVEC_MIN * 1.1 thisSum = sum(vv) factor = 1.0 / thisSum # must sum to one for i in range(desc[1]): t.model.parts[pNum].comps[ compNum].val[i] = vv[i] * factor compNum += 1 elif desc[0] == 'rMatrix': vv = [] for i in range(desc[1]): vv.append(float(splitPLine[splIndx])) splIndx += 1 if len(vv) == 1: # its a '2p' model, with a kappa t.model.parts[pNum].rMatrices[ rMatrixNum].val[0] = vv[0] else: # gtr for i in range(desc[1]): if vv[i] < var.RATE_MIN: vv[i] = var.RATE_MIN * 1.1 thisSum = sum(vv) factor = 1.0 / thisSum # must sum to one for i in range(desc[1]): t.model.parts[pNum].rMatrices[ rMatrixNum].val[i] = vv[i] * factor rMatrixNum += 1 elif desc[0] == 'gdasrv': t.model.parts[pNum].gdasrvs[gdasrvNum].val[ 0] = float(splitPLine[splIndx]) splIndx += 1 gdasrvNum += 1 elif desc[0] == 'pInvar': t.model.parts[pNum].pInvar.val = float( splitPLine[splIndx]) splIndx += 1 if splIndx != len(splitPLine): raise P4Error("Something is wrong. After reading, splIndx=%i, but len split pram line=%i" % ( splIndx, len(splitPLine))) return t