def onDND(self, list, context, x, y, dragData, dndId, time): """ External Drag'n'Drop """ import urllib if dragData.data == '': context.finish(False, False, time) return # A list of filenames, without 'file://' at the beginning if dndId == consts.DND_DAP_URI: tracks = media.getTracks([urllib.url2pathname(uri) for uri in dragData.data.split()]) # A list of filenames starting with 'file://' elif dndId == consts.DND_URI: tracks = media.getTracks([urllib.url2pathname(uri)[7:] for uri in dragData.data.split()]) # A list of tracks elif dndId == consts.DND_DAP_TRACKS: tracks = [media.track.unserialize(serialTrack) for serialTrack in dragData.data.split('\n')] dropInfo = list.get_dest_row_at_pos(x, y) # Insert the tracks, but beware of the AFTER/BEFORE mechanism used by GTK if dropInfo is None: self.insert(tracks, False) elif dropInfo[1] == gtk.TREE_VIEW_DROP_AFTER: self.insert(tracks, False, dropInfo[0][0] + 1) else: self.insert(tracks, False, dropInfo[0][0]) context.finish(True, False, time)
def onDND(self, list, context, x, y, dragData, dndId, time): """ External Drag'n'Drop """ import urllib if dragData.data == '': context.finish(False, False, time) return # A list of filenames, without 'file://' at the beginning if dndId == consts.DND_POGO_URI: tracks = media.getTracks([urllib.url2pathname(uri) for uri in dragData.data.split()]) # A list of filenames starting with 'file://' elif dndId == consts.DND_URI: tracks = media.getTracks([urllib.url2pathname(uri)[7:] for uri in dragData.data.split()]) else: assert False # dropInfo is tuple (path, drop_pos) dropInfo = list.get_dest_row_at_pos(x, y) # Insert the tracks, but beware of the AFTER/BEFORE mechanism used by GTK if dropInfo is None: self.insert(tracks, playNow=False, highlight=True) else: path, drop_mode = dropInfo iter = self.tree.store.get_iter(path) self.insert(tracks, iter, drop_mode, playNow=False, highlight=True) # We want to allow dropping tracks only when we are sure that no dir is # selected. This is needed for dnd from nautilus. self.tree.dir_selected = True context.finish(True, False, time)
def play(self, replace, path=None): """ Replace/extend the tracklist If 'path' is None, use the current selection """ if path is None: tracks = media.getTracks([row[ROW_FULLPATH] for row in self.tree.getSelectedRows()], self.addByFilename, not self.showHiddenFiles) else: tracks = media.getTracks([self.tree.getRow(path)[ROW_FULLPATH]], self.addByFilename, not self.showHiddenFiles) if replace: modules.postMsg(consts.MSG_CMD_TRACKLIST_SET, {'tracks': tracks, 'playNow': True}) else: modules.postMsg(consts.MSG_CMD_TRACKLIST_ADD, {'tracks': tracks, 'playNow': False})
def sendMsg(self, msg, params): """ Send the given message and its parameters to the core """ if msg in (consts.MSG_CMD_TOGGLE_PAUSE, consts.MSG_CMD_NEXT, consts.MSG_CMD_PREVIOUS, consts.MSG_CMD_STOP, consts.MSG_CMD_TRACKLIST_CLR, consts.MSG_CMD_TRACKLIST_SHUFFLE): gobject.idle_add(modules.postMsg, msg) elif msg == consts.MSG_CMD_TRACKLIST_ADD: gobject.idle_add(modules.postMsg, msg, {'tracks': media.getTracks([file for file in params])}) elif msg == consts.MSG_CMD_TRACKLIST_SET: gobject.idle_add(modules.postMsg, msg, {'tracks': media.getTracks([file for file in params]), 'playNow': True}) elif msg == consts.MSG_CMD_SET_VOLUME: gobject.idle_add(modules.postMsg, msg, {'value': float(params[0]) / 100.0}) else: return False return True
def onDragDataGet(self, tree, context, selection, info, time): """ Provide information about the data being dragged """ allTracks = media.getTracks( [row[ROW_FULLPATH] for row in self.tree.getSelectedRows()], self.addByFilename, not self.showHiddenFiles) selection.set(consts.DND_TARGETS[consts.DND_DAP_TRACKS][0], 8, '\n'.join([track.serialize() for track in allTracks]))
def SetTracks(self, uris, playNow): """ Replace the tracklist by the given URIs """ # uris is a DBus array we want a Python list # We add the empty string to convert the uris from DBus.String to unicode paths = [uri + '' for uri in uris] gobject.idle_add(modules.postMsg, consts.MSG_CMD_TRACKLIST_SET, {'tracks': media.getTracks(paths), 'playNow': playNow})
def AddTracks(self, uris, playNow): """ Appends multiple URIs to the tracklist """ # uris is a DBus array we want a Python list # We add the empty string to convert the uris from DBus.String to unicode paths = [uri + '' for uri in uris] gobject.idle_add(modules.postMsg, consts.MSG_CMD_TRACKLIST_ADD, {'tracks': media.getTracks(paths), 'playNow': playNow})
def onDND(self, list, context, x, y, dragData, dndId, time): """ External Drag'n'Drop """ import urllib.request uris = dragData.get_uris() if not uris: context.finish(False, False, time) return def get_path(uri): if uri.startswith('file://'): uri = uri[len('file://'):] return urllib.request.url2pathname(uri) paths = [get_path(uri) for uri in uris] tracks = media.getTracks(paths) dropInfo = list.get_dest_row_at_pos(x, y) # Insert the tracks, but beware of the AFTER/BEFORE mechanism used by GTK if dropInfo is None: self.insert(tracks, playNow=False, highlight=True) else: path, drop_mode = dropInfo iter = self.tree.store.get_iter(path) self.insert(tracks, iter, drop_mode, playNow=False, highlight=True) # We want to allow dropping tracks only when we are sure that no dir is # selected. This is needed for dnd from nautilus. self.tree.dir_selected = True context.finish(True, False, time)
def SetTracks(self, uris, playNow): """ Replace the tracklist by the given URIs """ gobject.idle_add( modules.postMsg, consts.MSG_CMD_TRACKLIST_SET, {"tracks": media.getTracks([file for file in uris]), "playNow": playNow}, )
def AddTracks(self, uris, playNow): """ Appends multiple URIs to the tracklist """ gobject.idle_add( modules.postMsg, consts.MSG_CMD_TRACKLIST_ADD, {"tracks": media.getTracks([file for file in uris]), "playNow": playNow}, )
def onAppStarted(self): """ This is the real initialization function, called when the module has been loaded """ wTree = tools.prefs.getWidgetsTree() self.playtime = 0 self.bufferedTrack = None # Retrieve widgets self.window = wTree.get_object('win-main') columns = (('', [(gtk.CellRendererPixbuf(), gtk.gdk.Pixbuf), (gtk.CellRendererText(), TYPE_STRING)], True), (None, [(None, TYPE_PYOBJECT)], False), ) self.tree = TrackTreeView(columns, use_markup=True) self.tree.enableDNDReordering() self.tree.setDNDSources([DND_INTERNAL_TARGET]) wTree.get_object('scrolled-tracklist').add(self.tree) # GTK handlers self.tree.connect('exttreeview-button-pressed', self.onMouseButton) self.tree.connect('tracktreeview-dnd', self.onDND) self.tree.connect('key-press-event', self.onKeyboard) self.tree.get_model().connect('row-deleted', self.onRowDeleted) (options, args) = prefs.getCmdLine() self.savedPlaylist = os.path.join(consts.dirCfg, 'saved-playlist') self.paused = False # Populate the playlist with the saved playlist dump = None if os.path.exists(self.savedPlaylist): try: dump = pickleLoad(self.savedPlaylist) except: msg = '[%s] Unable to restore playlist from %s\n\n%s' log.logger.error(msg % (MOD_INFO[modules.MODINFO_NAME], self.savedPlaylist, traceback.format_exc())) if dump: self.restoreTreeDump(dump) log.logger.info('[%s] Restored playlist' % MOD_INFO[modules.MODINFO_NAME]) self.tree.collapse_all() self.select_last_played_track() self.onListModified() commands, args = tools.separate_commands_and_tracks(args) # Add commandline tracks to the playlist if args: log.logger.info('[%s] Filling playlist with files given on command line' % MOD_INFO[modules.MODINFO_NAME]) tracks = media.getTracks([os.path.abspath(arg) for arg in args]) playNow = not 'stop' in commands and not 'pause' in commands modules.postMsg(consts.MSG_CMD_TRACKLIST_ADD, {'tracks': tracks, 'playNow': playNow}) elif 'play' in commands: modules.postMsg(consts.MSG_CMD_TOGGLE_PAUSE) # Automatically save the content at regular intervals gobject.timeout_add_seconds(SAVE_INTERVAL, self.save_track_tree)
def SetTracks(self, uris, playNow): """ Replace the tracklist by the given URIs """ # uris is a DBus array we want a Python list # We add the empty string to convert the uris from DBus.String to unicode paths = [uri + '' for uri in uris] GObject.idle_add(modules.postMsg, consts.MSG_CMD_TRACKLIST_SET, { 'tracks': media.getTracks(paths), 'playNow': playNow })
def AddTracks(self, uris, playNow): """ Appends multiple URIs to the tracklist """ # uris is a DBus array we want a Python list # We add the empty string to convert the uris from DBus.String to unicode paths = [uri + '' for uri in uris] GObject.idle_add(modules.postMsg, consts.MSG_CMD_TRACKLIST_ADD, { 'tracks': media.getTracks(paths), 'playNow': playNow })
def onDND(self, list, context, x, y, dragData, dndId, time): """ External Drag'n'Drop """ if dragData.data == '': context.finish(False, False, time) return dropInfo = list.get_dest_row_at_pos(x, y) # A list of filenames, without 'file://' at the beginning if dndId == consts.DND_DAP_URI: tracks = media.getTracks([urllib.url2pathname(uri) for uri in dragData.data.split()]) # A list of filenames starting with 'file://' elif dndId == consts.DND_URI: tracks = media.getTracks([urllib.url2pathname(uri)[7:] for uri in dragData.data.split()]) # A list of tracks elif dndId == consts.DND_DAP_TRACKS: tracks = [media.track.unserialize(serialTrack) for serialTrack in dragData.data.split('\n')] if dropInfo is None: self.insert(tracks) else: self.insert(tracks, dropInfo[0][0]) context.finish(True, False, time)
def onAppStarted(self): """ Try to fill the playlist by using the files given on the command line or by restoring the last playlist """ (options, args) = prefs.getCmdLine() self.savedPlaylist = os.path.join(consts.dirCfg, 'saved-playlist.txt') if len(args) != 0: log.logger.info('[%s] Filling playlist with files given on command line' % MOD_NAME) modules.postMsg(consts.MSG_CMD_TRACKLIST_SET, {'tracks': media.getTracks(args), 'playNow': True}) else: try: tracks = [media.track.unserialize(serialTrack) for serialTrack in tools.pickleLoad(self.savedPlaylist)] modules.postMsg(consts.MSG_CMD_TRACKLIST_SET, {'tracks': tracks, 'playNow': False}) log.logger.info('[%s] Restored playlist' % MOD_NAME) except: log.logger.error('[%s] Unable to restore playlist from %s\n\n%s' % (MOD_NAME, self.savedPlaylist, traceback.format_exc()))
def play(self, replace, path=None): """ Replace/extend the tracklist If 'path' is None, use the current selection """ if path is None: tracks = media.getTracks( [row[ROW_FULLPATH] for row in self.tree.getSelectedRows()], self.addByFilename, not self.showHiddenFiles) else: tracks = media.getTracks([self.tree.getRow(path)[ROW_FULLPATH]], self.addByFilename, not self.showHiddenFiles) if replace: modules.postMsg(consts.MSG_CMD_TRACKLIST_SET, { 'tracks': tracks, 'playNow': True }) else: modules.postMsg(consts.MSG_CMD_TRACKLIST_ADD, { 'tracks': tracks, 'playNow': False })
if pos_ok: # Everything ok, enable dnd self.enable_model_drag_dest(self.dndTargets, gtk.gdk.ACTION_DEFAULT) else: # do not let the user drop anything here self.enable_model_drag_dest([('invalid-position', 0, -1)], gtk.gdk.ACTION_DEFAULT) if __name__ == '__main__': from gobject import TYPE_INT, TYPE_PYOBJECT from tools import icons from media import getTracks tracks = getTracks(['/home/jendrik/Musik/Clearlake - Amber']) columns = (('', [(gtk.CellRendererPixbuf(), gtk.gdk.Pixbuf), (gtk.CellRendererText(), TYPE_STRING)], True), (None, [(None, TYPE_INT)], False), (None, [(None, TYPE_STRING)], False), (None, [(None, TYPE_PYOBJECT)], False), ) tree = TrackTreeView(columns, True) track = None a = tree.appendRow((icons.nullMenuIcon(), 'a', 1, 'something', track), None) b = tree.appendRow((icons.nullMenuIcon(), 'b', 1, 'something', track), a)
else: action = Gdk.DragAction.COPY Gdk.drag_status(context, action, time) # Return whether the cursor position is in a drop zone. return pos_ok if __name__ == '__main__': from gi.repository import GdkPixbuf from gi.repository import GObject from tools import icons from media import getTracks tracks = getTracks(['/home/jendrik/Musik/Clearlake - Amber']) columns = ( ('', [(Gtk.CellRendererPixbuf(), GdkPixbuf.Pixbuf), (Gtk.CellRendererText(), GObject.TYPE_STRING)], True), (None, [(None, GObject.TYPE_INT)], False), (None, [(None, GObject.TYPE_STRING)], False), (None, [(None, GObject.TYPE_PYOBJECT)], False), ) tree = TrackTreeView(columns, True) track = None a = tree.appendRow((icons.nullMenuIcon(), 'a', 1, 'something', track), None)
def onLoadTracks(self, paths): modules.postMsg(consts.MSG_CMD_TRACKLIST_ADD, { 'tracks': media.getTracks(paths), 'playNow': True })
def onDragDataGet(self, tree, context, selection, info, time): """ Provide information about the data being dragged """ allTracks = media.getTracks([row[ROW_FULLPATH] for row in self.tree.getSelectedRows()], self.addByFilename, not self.showHiddenFiles) selection.set(consts.DND_TARGETS[consts.DND_DAP_TRACKS][0], 8, '\n'.join([track.serialize() for track in allTracks]))
def onAppStarted(self): """ This is the real initialization function, called when the module has been loaded """ wTree = tools.prefs.getWidgetsTree() self.playtime = 0 self.bufferedTrack = None # Retrieve widgets self.window = wTree.get_object('win-main') columns = (('', [(Gtk.CellRendererPixbuf(), GdkPixbuf.Pixbuf), (Gtk.CellRendererText(), GObject.TYPE_STRING)], True), (None, [(None, GObject.TYPE_PYOBJECT)], False), ) self.tree = TrackTreeView(columns, use_markup=True) self.tree.enableDNDReordering() target = Gtk.TargetEntry.new(*DND_INTERNAL_TARGET) targets = Gtk.TargetList.new([target]) self.tree.setDNDSources(targets) wTree.get_object('scrolled-tracklist').add(self.tree) # GTK handlers self.tree.connect('exttreeview-button-pressed', self.onMouseButton) self.tree.connect('tracktreeview-dnd', self.onDND) self.tree.connect('key-press-event', self.onKeyboard) self.tree.get_model().connect('row-deleted', self.onRowDeleted) (options, args) = prefs.getCmdLine() self.savedPlaylist = os.path.join(consts.dirCfg, 'saved-playlist') self.paused = False # Populate the playlist with the saved playlist dump = None if os.path.exists(self.savedPlaylist): try: dump = pickleLoad(self.savedPlaylist) except (EOFError, IOError): msg = '[%s] Unable to restore playlist from %s\n\n%s' log.logger.error(msg % (MOD_INFO[modules.MODINFO_NAME], self.savedPlaylist, traceback.format_exc())) if dump: self.restoreTreeDump(dump) log.logger.info('[%s] Restored playlist' % MOD_INFO[modules.MODINFO_NAME]) self.tree.collapse_all() self.select_last_played_track() self.onListModified() commands, args = tools.separate_commands_and_tracks(args) # Add commandline tracks to the playlist if args: log.logger.info('[%s] Filling playlist with files given on command line' % MOD_INFO[modules.MODINFO_NAME]) tracks = media.getTracks([os.path.abspath(arg) for arg in args]) playNow = not 'stop' in commands and not 'pause' in commands modules.postMsg(consts.MSG_CMD_TRACKLIST_ADD, {'tracks': tracks, 'playNow': playNow}) elif 'play' in commands: modules.postMsg(consts.MSG_CMD_TOGGLE_PAUSE) # Automatically save the content at regular intervals GObject.timeout_add_seconds(SAVE_INTERVAL, self.save_track_tree)
def onLoadTracks(self, paths): modules.postMsg(consts.MSG_CMD_TRACKLIST_ADD, {"tracks": media.getTracks(paths), "playNow": True})