def export_current_playlist(self, *e): pl = self.main.get_current_playlist ().playlist name = pl.get_name() + ".m3u" dialog = dialogs.FileOperationDialog(_("Export Current Playlist"), None, gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) extensions = { 'm3u' : _('M3U Playlist'), 'pls' : _('PLS Playlist'), 'asx' : _('ASX Playlist'), 'xspf' : _('XSPF Playlist') } dialog.add_extensions(extensions) dialog.set_current_name (name) result = dialog.run() if result == gtk.RESPONSE_OK: path = unicode(dialog.get_filename(), 'utf-8') try: _xpl.export_playlist(pl, path) except _xpl.InvalidPlaylistTypeException: path = path + ".m3u" try: _xpl.export_playlist(pl, path) except _xpl.InvalidPlaylistTypeException: dialogs.error(None, _('Invalid file extension, file not saved')) dialog.destroy()
def rename_playlist(self, playlist): """ Renames the playlist """ if playlist is None: return # Ask for new name dialog = dialogs.TextEntryDialog( _("Enter the new name you want for your playlist"), _("Rename Playlist"), playlist.name) result = dialog.run() name = dialog.get_value() dialog.destroy() if result != Gtk.ResponseType.OK or name == '': return if name in self.playlist_manager.playlists: # name is already in use dialogs.error( self.parent, _("The " "playlist name you entered is already in use.")) return selection = self.tree.get_selection() (model, iter) = selection.get_selected() model.set_value(iter, 1, name) # Update the manager aswell self.playlist_manager.rename_playlist(playlist, name)
def open_item(self, tree, path, col): """ Called when the user double clicks on a playlist, also called when the user double clicks on a track beneath a playlist. When they active a track it opens the playlist and starts playing that track """ iter = self.model.get_iter(path) item = self.model.get_value(iter, 2) if item is not None: if isinstance(item, (playlist.Playlist, playlist.SmartPlaylist)): # for smart playlists if hasattr(item, 'get_playlist'): try: item = item.get_playlist(self.collection) except Exception as e: logger.exception("Error loading smart playlist") dialogs.error(self.parent, _("Error loading smart playlist: %s") % str(e)) return else: #Get an up to date copy item = self.playlist_manager.get_playlist(item.name) #item.set_is_custom(True) # self.controller.main.add_playlist(item) self.emit('playlist-selected', item) else: self.emit('append-items', [item.track], True)
def on_edited(self, cellrenderer, path, new_text): # Undo newline escaping new_text = new_text.decode('unicode-escape') validate = getattr(self, 'validate', None) if validate: try: new_text = validate(new_text) except ValueError: return # Update the track model = self.get_tree_view().get_model() iter = model.get_iter(path) track = model.get_value(iter, 0) track.set_tag_raw(self.name, new_text) # Invalidate/redraw the value immediately because we know # it's just a single change model.get_value(iter, 1).clear() model.row_changed(path, iter) if not track.write_tags(): dialogs.error( None, "Error writing tags to %s" % GObject.markup_escape_text(track.get_loc_for_io()), )
def _set_bpm(self, result, bpm, track): if result == Gtk.ResponseType.YES: track.set_tags(bpm=bpm) if not track.write_tags(): dialogs.error( None, "Error writing BPM to %s" % GObject.markup_escape_text(track.get_loc_for_io()))
def __init__( self, bookmarks_menu, delete_menu, delete_bookmark_callback, path, time ): """ Creates a bookmark for current track/position if path or time are None. Creates a bookmark for the given track/positon otherwise. """ if not path: # get currently playing track track = player.PLAYER.current if track is None: text = 'Need a playing track to Bookmark.' LOGGER.error(text) dialogs.error(xlgui.main.mainwindow(), text) return time = player.PLAYER.get_time() path = track.get_loc_for_io() self.__path = path self.__time = time self.__title = None self.__cover_pixbuf = None self.item = None self.__fetch_metadata() self.__create_menu_item(bookmarks_menu, delete_menu, delete_bookmark_callback)
def open_item(self, tree, path, col): """ Called when the user double clicks on a playlist, also called when the user double clicks on a track beneath a playlist. When they active a track it opens the playlist and starts playing that track """ iter = self.model.get_iter(path) item = self.model.get_value(iter, 2) if item is not None: if isinstance(item, (xl_playlist.Playlist, xl_playlist.SmartPlaylist)): # for smart playlists if hasattr(item, 'get_playlist'): try: item = item.get_playlist(self.collection) except Exception as e: logger.exception("Error loading smart playlist") dialogs.error( self.parent, _("Error loading smart playlist: %s") % str(e)) return else: # Get an up to date copy item = self.playlist_manager.get_playlist(item.name) # item.set_is_custom(True) # self.controller.main.add_playlist(item) self.emit('playlist-selected', item) else: self.emit('append-items', [item.track], True)
def export_current_playlist(self, *e): pl = self.main.get_current_playlist().playlist name = pl.get_name() + ".m3u" dialog = dialogs.FileOperationDialog( _("Export Current Playlist"), None, gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) extensions = { 'm3u': _('M3U Playlist'), 'pls': _('PLS Playlist'), 'asx': _('ASX Playlist'), 'xspf': _('XSPF Playlist') } dialog.add_extensions(extensions) dialog.set_current_name(name) result = dialog.run() if result == gtk.RESPONSE_OK: path = unicode(dialog.get_filename(), 'utf-8') try: _xpl.export_playlist(pl, path) except _xpl.InvalidPlaylistTypeException: path = path + ".m3u" try: _xpl.export_playlist(pl, path) except _xpl.InvalidPlaylistTypeException: dialogs.error(None, _('Invalid file extension, file not saved')) dialog.destroy()
def __init__(self, bookmarks_menu, delete_menu, delete_bookmark_callback, path, time): """ Creates a bookmark for current track/position if path or time are None. Creates a bookmark for the given track/positon otherwise. """ if not path: # get currently playing track track = player.PLAYER.current if track is None: text = 'Need a playing track to Bookmark.' LOGGER.error(text) dialogs.error(xlgui.main.mainwindow(), text) return time = player.PLAYER.get_time() path = track.get_loc_for_io() self.__path = path self.__time = time self.__title = None self.__cover_pixbuf = None self.item = None self.__fetch_metadata() self.__create_menu_item(bookmarks_menu, delete_menu, delete_bookmark_callback)
def rename_playlist(self, playlist): """ Renames the playlist """ if playlist is None: return # Ask for new name dialog = dialogs.TextEntryDialog( _("Enter the new name you want for your playlist"), _("Rename Playlist"), playlist.name) result = dialog.run() name = dialog.get_value() dialog.destroy() if result != Gtk.ResponseType.OK or name == '': return if name in self.playlist_manager.playlists: # name is already in use dialogs.error(self.parent, _("The " "playlist name you entered is already in use.")) return selection = self.tree.get_selection() (model, iter) = selection.get_selected() model.set_value(iter, 1, name) # Update the manager aswell self.playlist_manager.rename_playlist(playlist, name)
def _save_podcasts(self): try: with open(self.podcast_file, 'w') as fp: for (title, url) in self.podcasts: fp.write('%s\t%s\n' % (url, title)) except (OSError, IOError): dialogs.error(self.parent, _('Could not save podcast file')) return
def _on_complete(bpm, err): if err is not None: dialogs.error(None, err) elif track and bpm: bpm = int(round(float(bpm))) msg = BPMAutodetectResponse(parent_window, bpm, track) result = msg.run() bpm = msg.get_bpm() msg.destroy() self._set_bpm(result, bpm, track)
def _save_podcasts(self): try: h = open(self.podcast_file, "w") except (OSError, IOError): dialogs.error(self.parent, _("Could not save podcast file")) return for (title, url) in self.podcasts: h.write("%s\t%s\n" % (url, title)) h.close()
def _save_podcasts(self): try: h = open(self.podcast_file, 'w') except (OSError, IOError): dialogs.error(self.parent, _('Could not save podcast file')) return for (title, url) in self.podcasts: h.write('%s\t%s\n' % (url, title)) h.close()
def on_playlist_context_select_custom_menu( self, menu, display_name, playlist_view, context, exaile ): '''Called when 'select tracks with similar tags (custom)' is selected''' tracks = context['selected-tracks'] groups = set() for track in tracks: groups |= get_track_groups(track) if len(groups) > 0: create_custom_search_playlist( groups, exaile ) else: dialogs.error( None, _('No categorization tags found in selected tracks'))
def on_playlist_context_select_custom_menu( self, menu, display_name, playlist_view, context, exaile ): '''Called when 'select tracks with similar groups (custom)' is selected''' tracks = context['selected-tracks'] groups = set() for track in tracks: groups |= get_track_groups(track) if len(groups) > 0: create_custom_search_playlist( groups, exaile ) else: dialogs.error( None, _('No categorization tags found in selected tracks'))
def _run_edit_selected_smart_playlist(self, dialog): '''internal helper function''' result = dialog.run() dialog.hide() pl = self.tree.get_selected_page(raw=True) if result == Gtk.ResponseType.ACCEPT: name = dialog.get_name() matchany = dialog.get_match_any() limit = dialog.get_limit() state = dialog.get_state() random = dialog.get_random() if not name: dialogs.error( self.parent, _("You did " "not enter a name for your playlist")) return False if not name == pl.name: try: pl = self.smart_manager.get_playlist(name) dialogs.error( self.parent, _("The " "playlist name you entered is already in use.")) return False except ValueError: pass # playlist didn't exist pl = playlist.SmartPlaylist(name, self.collection) pl.set_or_match(matchany) pl.set_return_limit(limit) pl.set_random_sort(random) for item in state: (field, op) = item[0] value = item[1] pl.add_param(_NMAP[field], _TRANS[op], value) self.smart_manager.remove_playlist(pl.name) self.smart_manager.save_playlist(pl) selection = self.tree.get_selection() (model, iter) = selection.get_selected() model.set_value(iter, 1, name) model.set_value(iter, 2, pl) return True
def set_track_groups(track, groups): ''' Given an array of groups, sets them on a track Returns true if successful, false if there was an error ''' grouping = ' '.join(sorted(['_'.join(group.split()) for group in groups])) track.set_tag_raw(get_tagname(), grouping) if not track.write_tags(): dialogs.error(None, "Error writing tags to %s" % GObject.markup_escape_text(track.get_loc_for_io())) return False return True
def set_track_groups(track, groups): ''' Given an array of groups, sets them on a track Returns true if successful, false if there was an error ''' grouping = ' '.join( sorted( [ '_'.join( group.split() ) for group in groups ] ) ) track.set_tag_raw(get_tagname(), grouping ) if not track.write_tags(): dialogs.error( None, "Error writing tags to %s" % gobject.markup_escape_text(track.get_loc_for_io()) ) return False return True
def set_bpm(self): '''Make sure we don't accidentally set BPM on things''' if self.track and self.bpm: msg = gtk.MessageDialog(self.get_toplevel(), gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Set BPM of %d on %s?') % (int(self.bpm), self.track.get_tag_display('title'))) msg.set_default_response( gtk.RESPONSE_NO ) result = msg.run() msg.destroy() if result == gtk.RESPONSE_YES: self.track.set_tag_raw('bpm', int(self.bpm)) if not self.track.write_tags(): dialogs.error( None, "Error writing BPM to %s" % gobject.markup_escape_text(self.track.get_loc_for_io()) ) self.update_ui()
def _run_edit_selected_smart_playlist(self, dialog): '''internal helper function''' result = dialog.run() dialog.hide() pl = self.tree.get_selected_page(raw=True) if result == Gtk.ResponseType.ACCEPT: name = dialog.get_name() matchany = dialog.get_match_any() limit = dialog.get_limit() state = dialog.get_state() random = dialog.get_random() if not name: dialogs.error(self.parent, _("You did " "not enter a name for your playlist")) return False if not name == pl.name: try: pl = self.smart_manager.get_playlist(name) dialogs.error(self.parent, _("The " "playlist name you entered is already in use.")) return False except ValueError: pass # playlist didn't exist pl = playlist.SmartPlaylist(name, self.collection) pl.set_or_match(matchany) pl.set_return_limit(limit) pl.set_random_sort(random) for item in state: (field, op) = item[0] value = item[1] pl.add_param(_NMAP[field], _TRANS[op], value) self.smart_manager.remove_playlist(pl.name) self.smart_manager.save_playlist(pl) selection = self.tree.get_selection() (model, iter) = selection.get_selected() model.set_value(iter, 1, name) model.set_value(iter, 2, pl) return True
def set_bpm(self, track, bpm, parent_window=None): '''Make sure we don't accidentally set BPM on things''' if track and bpm: bpm = int(bpm) msg = Gtk.MessageDialog(parent_window, Gtk.DialogFlags.MODAL, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, _('Set BPM of %d on %s?') % (bpm, track.get_tag_display('title'))) msg.set_default_response(Gtk.ResponseType.NO) result = msg.run() msg.destroy() if result == Gtk.ResponseType.YES: track.set_tag_raw('bpm', bpm) if not track.write_tags(): dialogs.error(None, "Error writing BPM to %s" % GObject.markup_escape_text(track.get_loc_for_io()))
def toggle_record(self, add_call): current_track = player.PLAYER.current if not current_track: return True if current_track.is_local(): logger.warning('Streamripper can only record streams') return True self.savedir = settings.get_option('plugin/streamripper/save_location', os.getenv('HOME')) options = [] options.append('streamripper') options.append(player.PLAYER._pipe.get_property('uri')) options.append('-D') options.append('%A/%a/%T') if settings.get_option('plugin/streamripper/single_file', False): options.append("-a") options.append("-A") options.append("-r") options.append( settings.get_option('plugin/streamripper/relay_port', '8888')) options.append("-d") options.append(self.savedir) try: self.process = subprocess.Popen(options, 0, None, subprocess.PIPE, subprocess.PIPE, subprocess.PIPE) except OSError: logger.error('There was an error executing streamripper') dialogs.error(self.exaile.gui.main.window, _('Error ' 'executing streamripper')) return True if add_call: event.add_callback(self.quit_application, 'quit_application') event.add_ui_callback(self.start_track, 'playback_track_start', player.PLAYER) event.add_ui_callback(self.stop_playback, 'playback_player_end', player.PLAYER) return False
def _run_add_smart_playlist(self, dialog): '''internal helper function''' result = dialog.run() dialog.hide() if result == gtk.RESPONSE_ACCEPT: name = dialog.get_name() matchany = dialog.get_match_any() limit = dialog.get_limit() state = dialog.get_state() random = dialog.get_random() if not name: dialogs.error(self.parent, _("You did " "not enter a name for your playlist")) return False try: pl = self.smart_manager.get_playlist(name) dialogs.error(self.parent, _("The " "playlist name you entered is already in use.")) return False except ValueError: pass # playlist didn't exist pl = playlist.SmartPlaylist(name, self.collection) pl.set_or_match(matchany) pl.set_return_limit(limit) pl.set_random_sort(random) for item in state: (field, op) = item[0] value = item[1] pl.add_param(_NMAP[field], _TRANS[op], value) self.smart_manager.save_playlist(pl) self.model.append(self.smart, [self.playlist_image, name, pl]) return True
def toggle_record(self, add_call): current_track = player.PLAYER.current if not current_track: return True if current_track.is_local(): logger.warning('Streamripper can only record streams') return True self.savedir = settings.get_option('plugin/streamripper/save_location', os.getenv('HOME')) options = [] options.append('streamripper') options.append(player.PLAYER._pipe.get_property('uri')) options.append('-D') options.append('%A/%a/%T') if settings.get_option('plugin/streamripper/single_file', False): options.append("-a") options.append("-A") options.append("-r") options.append(settings.get_option('plugin/streamripper/relay_port', '8888')) options.append("-d") options.append(self.savedir) try: self.process = subprocess.Popen(options, 0, None, subprocess.PIPE, subprocess.PIPE, subprocess.PIPE) except OSError: logger.error('There was an error executing streamripper') dialogs.error(self.exaile.gui.main.window, _('Error ' 'executing streamripper')) return True if add_call: event.add_callback(self.quit_application, 'quit_application') event.add_ui_callback(self.start_track, 'playback_track_start', player.PLAYER) event.add_ui_callback(self.stop_playback, 'playback_player_end', player.PLAYER) return False
def error(text): logger.error("%s: %s" % ('Bookmarks', text)) dialogs.error(None, exaile.gui.main, text)
def _on_complete(bpm, err): if err is not None: dialogs.error(None, err) else: self.set_bpm(track, bpm, parent_window=parent_window)