def test_get_set_columns(self): self.failIf(config.get("settings", "headers", None)) self.failIf(config.get("settings", "columns", None)) columns = ["first", "won't", "two words", "4"] set_columns(columns) self.failUnlessEqual(columns, get_columns()) columns += ["~~another~one"] set_columns(columns) self.failUnlessEqual(columns, get_columns()) self.failIf(config.get("settings", "headers", None))
def __apply(self, button, buttons, tiv, aip, fip, aio): new_headers = set() # Get the checked headers for key, name in self.PREDEFINED_TAGS: if buttons[key].get_active(): new_headers.add(key) # And the customs new_headers.update(set(self.other_cols)) on_to_off = dict((on, off) for (w, off, on) in self._toggle_data) result = [] cur_cols = get_columns() for h in cur_cols: if h in new_headers: result.append(h) else: try: alternative = on_to_off[h] if alternative in new_headers: result.append(alternative) except KeyError: pass # Add new ones on the end result.extend(new_headers - set(result)) # After this, do the substitutions for (check, off, on) in self._toggle_data: if check.get_active(): try: result[result.index(off)] = on except ValueError: pass SongList.set_all_column_headers(result)
def test_get_columns_migrated(self): self.failIf(config.get("settings", "headers", None)) columns = "~album,~#replaygain_track_gain,foobar" config.set("settings", "columns", columns) self.failUnlessEqual(get_columns(), ["~album", "~#replaygain_track_gain", "foobar"]) self.failIf(config.get("settings", "headers", None))
def __apply(self, button, buttons, tiv, aip, fip, aio): new_headers = set() # Get the checked headers for key, name in self.PREDEFINED_TAGS: if buttons[key].get_active(): new_headers.add(key) # And the customs new_headers.update(set(self.other_cols)) on_to_off = dict((on, off) for (w, off, on) in self._toggle_data) result = [] cur_cols = get_columns() for h in cur_cols: if h in new_headers: result.append(h) else: try: alternative = on_to_off[h] if alternative in new_headers: result.append(alternative) except KeyError: pass # Add new ones on the end result.extend(new_headers - set(result)) # After this, do the substitutions for (check, off, on) in self._toggle_data: if check.get_active(): try: result[result.index(off)] = on except ValueError: pass SongList.set_all_column_headers(result)
def test_get_columns_migrated(self): self.failIf(config.get("settings", "headers", None)) columns = "~album,~#replaygain_track_gain,foobar" config.set("settings", "columns", columns) self.failUnlessEqual(get_columns(), ["~album", "~#replaygain_track_gain", "foobar"]) self.failIf(config.get("settings", "headers", None))
def test_get_columns_migrates(self): self.failIf(config.get("settings", "headers", None)) self.failIf(config.get("settings", "columns", None)) headers = "~album ~#replaygain_track_gain foobar" config.set("settings", "headers", headers) columns = get_columns() self.failUnlessEqual(columns, ["~album", "~#replaygain_track_gain", "foobar"]) self.failIf(config.get("settings", "headers", None))
def __cols_changed(self, songlist): headers = [col.header_name for col in songlist.get_columns()] try: headers.remove('~current') except ValueError: pass if len(headers) == len(get_columns()): # Not an addition or removal (handled separately) set_columns(headers) SongList.headers = headers
def __cols_changed(self, songlist): headers = [col.header_name for col in songlist.get_columns()] try: headers.remove('~current') except ValueError: pass if len(headers) == len(get_columns()): # Not an addition or removal (handled separately) set_columns(headers) SongList.headers = headers
def to_html(songs): cols = get_columns() cols_s = "" for col in cols: cols_s += '<th>%s</th>' % tag(col) songs_s = "" for song in songs: s = '<tr>' for col in cols: col = {"~#rating": "~rating", "~#length": "~length"}.get(col, col) s += '\n<td>%s</td>' % (escape(str(song.comma(col))) or ' ') s += '</tr>' songs_s += s return HTML % {'headers': cols_s, 'songs': songs_s}
def to_html(songs): cols = get_columns() cols_s = "" for col in cols: cols_s += '<th>%s</th>' % tag(col) songs_s = "" for song in songs: s = '<tr>' for col in cols: col = {"~#rating": "~rating", "~#length": "~length"}.get( col, col) s += '\n<td>%s</td>' % ( escape(text_type(song.comma(col))) or ' ') s += '</tr>' songs_s += s return HTML % {'headers': cols_s, 'songs': songs_s}
def __get_current_columns(self, buttons): """Given the current column list and the widgets states compute a new column list. """ new_headers = set() # Get the checked headers for key, name in self.PREDEFINED_TAGS: if buttons[key].get_active(): new_headers.add(key) # And the customs new_headers.update(set(self.other_cols)) on_to_off = dict((on, off) for (w, off, on) in self._toggle_data) result = [] cur_cols = get_columns() for h in cur_cols: if h in new_headers: result.append(h) else: try: alternative = on_to_off[h] if alternative in new_headers: result.append(alternative) except KeyError: pass # Add new ones on the end result.extend(new_headers - set(result)) # After this, do the substitutions for (check, off, on) in self._toggle_data: if check.get_active(): try: result[result.index(off)] = on except ValueError: pass return result
def __get_current_columns(self, buttons): """Given the current column list and the widgets states compute a new column list. """ new_headers = set() # Get the checked headers for key, name in self.PREDEFINED_TAGS: if buttons[key].get_active(): new_headers.add(key) # And the customs new_headers.update(set(self.other_cols)) on_to_off = dict((on, off) for (w, off, on) in self._toggle_data) result = [] cur_cols = get_columns() for h in cur_cols: if h in new_headers: result.append(h) else: try: alternative = on_to_off[h] if alternative in new_headers: result.append(alternative) except KeyError: pass # Add new ones on the end result.extend(new_headers - set(result)) # After this, do the substitutions for (check, off, on) in self._toggle_data: if check.get_active(): try: result[result.index(off)] = on except ValueError: pass return result
def __init__(self): super(PreferencesWindow.SongList, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Song List") # Behaviour vbox = Gtk.VBox(spacing=6) c = CCB(_("_Jump to playing song automatically"), 'settings', 'jump', populate=True, tooltip=_("When the playing song changes, " "scroll to it in the song list")) vbox.pack_start(c, False, True, 0) frame = qltk.Frame(_("Behavior"), child=vbox) self.pack_start(frame, False, True, 0) # Columns vbox = Gtk.VBox(spacing=12) buttons = {} table = Gtk.Table.new(3, 3, True) cols = get_columns() for i, (k, t) in enumerate(self.PREDEFINED_TAGS): x, y = i % 3, i / 3 buttons[k] = Gtk.CheckButton(label=t, use_underline=True) if k in cols: buttons[k].set_active(True) cols.remove(k) table.attach(buttons[k], x, x + 1, y, y + 1) vbox.pack_start(table, False, True, 0) if "~current" in cols: cols.remove("~current") self.other_cols = cols # Other columns hbox = Gtk.HBox(spacing=6) l = Gtk.Label(label=_("_Others:"), use_underline=True) hbox.pack_start(l, False, True, 0) self.others = others = UndoEntry() others.set_sensitive(False) # Stock edit doesn't have ellipsis chars. edit_button = Gtk.Button( label=_(u"_Edit…"), use_underline=True) edit_button.connect("clicked", self.__config_cols) edit_button.set_tooltip_text(_("Add or remove additional column " "headers")) l.set_mnemonic_widget(edit_button) l.set_use_underline(True) hbox.pack_start(others, True, True, 0) hbox.pack_start(edit_button, False, True, 0) vbox.pack_start(hbox, False, True, 0) frame = qltk.Frame(_("Visible Columns"), child=vbox) self.pack_start(frame, False, True, 0) # Column preferences tiv = Gtk.CheckButton(label=_("Title includes _version"), use_underline=True) aio = Gtk.CheckButton(label=_("Artist includes all _people"), use_underline=True) aip = Gtk.CheckButton(label=_("Album includes _disc subtitle"), use_underline=True) fip = Gtk.CheckButton(label=_("Filename includes _folder"), use_underline=True) self._toggle_data = [ (tiv, "title", "~title~version"), (aip, "album", "~album~discsubtitle"), (fip, "~basename", "~filename"), (aio, "artist", "~people") ] # Turn on the toggles if the toggled version is detected in config for (check, off, on) in self._toggle_data: if on in cols: buttons[off].set_active(True) check.set_active(True) cols.remove(on) # Update text once to exclude ticked columns, munged or not others.set_text(", ".join(cols)) t = Gtk.Table.new(2, 2, True) t.attach(tiv, 0, 1, 0, 1) t.attach(aip, 0, 1, 1, 2) t.attach(aio, 1, 2, 0, 1) t.attach(fip, 1, 2, 1, 2) frame = qltk.Frame(_("Column Preferences"), child=t) self.pack_start(frame, False, True, 0) # Apply button vbox = Gtk.VBox(spacing=12) apply = Gtk.Button(stock=Gtk.STOCK_APPLY) apply.set_tooltip_text(_("Apply current configuration to song " "list, adding new columns to the end")) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(apply, True, True, 0) vbox.pack_start(b, True, True, 0) self.pack_start(vbox, True, True, 0) apply.connect('clicked', self.__apply, buttons, tiv, aip, fip, aio) # Apply on destroy, else config gets mangled self.connect('destroy', self.__apply, buttons, tiv, aip, fip, aio) for child in self.get_children(): child.show_all()
def __init__(self): super(PreferencesWindow.SongList, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Song List") # Behaviour vbox = Gtk.VBox(spacing=6) c = CCB(_("_Jump to playing song automatically"), 'settings', 'jump', populate=True, tooltip=_("When the playing song changes, " "scroll to it in the song list")) vbox.pack_start(c, False, True, 0) frame = qltk.Frame(_("Behavior"), child=vbox) self.pack_start(frame, False, True, 0) # Columns vbox = Gtk.VBox(spacing=12) buttons = {} table = Gtk.Table.new(3, 3, True) cols = get_columns() for i, (k, t) in enumerate(self.PREDEFINED_TAGS): x, y = i % 3, i / 3 buttons[k] = Gtk.CheckButton(label=t, use_underline=True) if k in cols: buttons[k].set_active(True) cols.remove(k) table.attach(buttons[k], x, x + 1, y, y + 1) vbox.pack_start(table, False, True, 0) if "~current" in cols: cols.remove("~current") self.other_cols = cols # Other columns hbox = Gtk.HBox(spacing=6) l = Gtk.Label(label=_("_Others:"), use_underline=True) hbox.pack_start(l, False, True, 0) self.others = others = UndoEntry() others.set_sensitive(False) # Stock edit doesn't have ellipsis chars. edit_button = Gtk.Button(label=_("_Edit..."), use_underline=True) edit_button.connect("clicked", self.__config_cols) edit_button.set_tooltip_text(_("Add or remove additional column " "headers")) l.set_mnemonic_widget(edit_button) l.set_use_underline(True) hbox.pack_start(others, True, True, 0) hbox.pack_start(edit_button, False, True, 0) vbox.pack_start(hbox, False, True, 0) frame = qltk.Frame(_("Visible Columns"), child=vbox) self.pack_start(frame, False, True, 0) # Column preferences tiv = Gtk.CheckButton(label=_("Title includes _version"), use_underline=True) aio = Gtk.CheckButton(label=_("Artist includes all _people"), use_underline=True) aip = Gtk.CheckButton(label=_("Album includes _disc subtitle"), use_underline=True) fip = Gtk.CheckButton(label=_("Filename includes _folder"), use_underline=True) self._toggle_data = [ (tiv, "title", "~title~version"), (aip, "album", "~album~discsubtitle"), (fip, "~basename", "~filename"), (aio, "artist", "~people") ] # Turn on the toggles if the toggled version is detected in config for (check, off, on) in self._toggle_data: if on in cols: buttons[off].set_active(True) check.set_active(True) cols.remove(on) # Update text once to exclude ticked columns, munged or not others.set_text(", ".join(cols)) t = Gtk.Table.new(2, 2, True) t.attach(tiv, 0, 1, 0, 1) t.attach(aip, 0, 1, 1, 2) t.attach(aio, 1, 2, 0, 1) t.attach(fip, 1, 2, 1, 2) frame = qltk.Frame(_("Column Preferences"), child=t) self.pack_start(frame, False, True, 0) # Apply button vbox = Gtk.VBox(spacing=12) apply = Gtk.Button(stock=Gtk.STOCK_APPLY) apply.set_tooltip_text(_("Apply current configuration to song " "list, adding new columns to the end")) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(apply, True, True, 0) vbox.pack_start(b, True, True, 0) self.pack_start(vbox, True, True, 0) apply.connect('clicked', self.__apply, buttons, tiv, aip, fip, aio) # Apply on destroy, else config gets mangled self.connect('destroy', self.__apply, buttons, tiv, aip, fip, aio) for child in self.get_children(): child.show_all()
def main(): try: # we want basic commands not to import gtk (doubles process time) assert "gi.repository.Gtk" not in sys.modules sys.modules["gi.repository.Gtk"] = None startup_actions, cmds_todo = process_arguments() finally: sys.modules.pop("gi.repository.Gtk", None) import traceback import quodlibet from quodlibet import app from quodlibet.qltk import add_signal_watch, icons add_signal_watch(app.quit) import quodlibet.player import quodlibet.library from quodlibet import config from quodlibet import browsers from quodlibet import const from quodlibet import util from quodlibet.util.string import decode config.init(const.CONFIG) app.name = "Quod Libet" app.id = "quodlibet" quodlibet.init(icon=icons.QUODLIBET, name=app.name, proc_title=app.id) print_d("Initializing main library (%s)" % (quodlibet.util.path.unexpand(const.LIBRARY))) library = quodlibet.library.init(const.LIBRARY) app.library = library # this assumes that nullbe will always succeed from quodlibet.player import PlayerError wanted_backend = os.environ.get("QUODLIBET_BACKEND", config.get("player", "backend")) backend_traceback = None for backend in [wanted_backend, "nullbe"]: try: player = quodlibet.player.init_player(backend, app.librarian) except PlayerError: backend_traceback = decode(traceback.format_exc()) else: break app.player = player os.environ["PULSE_PROP_media.role"] = "music" os.environ["PULSE_PROP_application.icon_name"] = "quodlibet" browsers.init() from quodlibet.qltk.songlist import SongList, get_columns from quodlibet.util.collection import Album try: cover_size = config.getint("browsers", "cover_size") except config.Error: pass else: if cover_size > 0: Album.COVER_SIZE = cover_size headers = get_columns() SongList.set_all_column_headers(headers) for opt in config.options("header_maps"): val = config.get("header_maps", opt) util.tags.add(opt, val) in_all = ("~filename ~uri ~#lastplayed ~#rating ~#playcount ~#skipcount " "~#added ~#bitrate ~current ~#laststarted ~basename " "~dirname").split() for Kind in browsers.browsers: if Kind.headers is not None: Kind.headers.extend(in_all) Kind.init(library) pm = quodlibet.init_plugins("no-plugins" in startup_actions) if hasattr(player, "init_plugins"): player.init_plugins() from quodlibet.qltk import unity unity.init("quodlibet.desktop", player) from quodlibet.qltk.songsmenu import SongsMenu SongsMenu.init_plugins() from quodlibet.util.cover import CoverManager app.cover_manager = CoverManager() app.cover_manager.init_plugins() from quodlibet.plugins.playlist import PLAYLIST_HANDLER PLAYLIST_HANDLER.init_plugins() from gi.repository import GLib def exec_commands(*args): for cmd in cmds_todo: try: resp = cmd_registry.run(app, *cmd) except CommandError: pass else: if resp is not None: print_(resp, end="") from quodlibet.qltk.quodlibetwindow import QuodLibetWindow # Call exec_commands after the window is restored, but make sure # it's after the mainloop has started so everything is set up. app.window = window = QuodLibetWindow( library, player, restore_cb=lambda: GLib.idle_add(exec_commands, priority=GLib.PRIORITY_HIGH)) from quodlibet.qltk.debugwindow import MinExceptionDialog from quodlibet.qltk.window import on_first_map if backend_traceback is not None: def show_backend_error(window): d = MinExceptionDialog( window, _("Audio Backend Failed to Load"), _("Loading the audio backend '%(name)s' failed. " "Audio playback will be disabled.") % {"name": wanted_backend}, backend_traceback) d.run() # so we show the main window first on_first_map(app.window, show_backend_error, app.window) from quodlibet.plugins.events import EventPluginHandler pm.register_handler(EventPluginHandler(library.librarian, player)) from quodlibet.mmkeys import MMKeysHandler from quodlibet.remote import Remote, RemoteError from quodlibet.commands import registry as cmd_registry, CommandError from quodlibet.qltk.tracker import SongTracker, FSInterface try: from quodlibet.qltk.dbus_ import DBusHandler except ImportError: DBusHandler = lambda player, library: None mmkeys_handler = MMKeysHandler(app.name, window, player) if "QUODLIBET_NO_MMKEYS" not in os.environ: mmkeys_handler.start() fsiface = FSInterface(player) remote = Remote(app, cmd_registry) try: remote.start() except RemoteError: exit_(1, True) DBusHandler(player, library) tracker = SongTracker(library.librarian, player, window.playlist) from quodlibet.qltk import session session.init("quodlibet") quodlibet.enable_periodic_save(save_library=True) if "start-playing" in startup_actions: player.paused = False # restore browser windows from quodlibet.qltk.browser import LibraryBrowser GLib.idle_add(LibraryBrowser.restore, library, player, priority=GLib.PRIORITY_HIGH) def before_quit(): print_d("Saving active browser state") try: app.browser.save() except NotImplementedError: pass print_d("Shutting down player device %r." % player.version_info) player.destroy() quodlibet.main(window, before_quit=before_quit) quodlibet.finish_first_session(app.id) mmkeys_handler.quit() remote.stop() fsiface.destroy() tracker.destroy() quodlibet.library.save() config.save(const.CONFIG) print_d("Finished shutdown.")
def __init__(self): def create_behaviour_frame(): vbox = Gtk.VBox(spacing=6) c = CCB(_("_Jump to playing song automatically"), 'settings', 'jump', populate=True, tooltip=_("When the playing song changes, " "scroll to it in the song list")) vbox.pack_start(c, False, True, 0) return qltk.Frame(_("Behavior"), child=vbox) def create_visible_columns_frame(): buttons = {} vbox = Gtk.VBox(spacing=12) table = Gtk.Table.new(3, 3, True) for i, (k, t) in enumerate(self.PREDEFINED_TAGS): x, y = i % 3, i / 3 buttons[k] = Gtk.CheckButton(label=t, use_underline=True) table.attach(buttons[k], x, x + 1, y, y + 1) vbox.pack_start(table, False, True, 0) # Other columns hbox = Gtk.HBox(spacing=6) l = Gtk.Label(label=_("_Others:"), use_underline=True) hbox.pack_start(l, False, True, 0) self.others = others = UndoEntry() others.set_sensitive(False) # Stock edit doesn't have ellipsis chars. edit_button = Gtk.Button( label=_(u"_Edit…"), use_underline=True) edit_button.connect("clicked", self.__config_cols, buttons) edit_button.set_tooltip_text( _("Add or remove additional column " "headers")) l.set_mnemonic_widget(edit_button) l.set_use_underline(True) hbox.pack_start(others, True, True, 0) vbox.pack_start(hbox, False, True, 0) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(edit_button, True, True, 0) vbox.pack_start(b, True, True, 0) return qltk.Frame(_("Visible Columns"), child=vbox), buttons def create_columns_prefs_frame(): tiv = Gtk.CheckButton(label=_("Title includes _version"), use_underline=True) aio = Gtk.CheckButton(label=_("Artist includes all _people"), use_underline=True) aip = Gtk.CheckButton(label=_("Album includes _disc subtitle"), use_underline=True) fip = Gtk.CheckButton(label=_("Filename includes _folder"), use_underline=True) self._toggle_data = [ (tiv, "title", "~title~version"), (aip, "album", "~album~discsubtitle"), (fip, "~basename", "~filename"), (aio, "artist", "~people") ] t = Gtk.Table.new(2, 2, True) t.attach(tiv, 0, 1, 0, 1) t.attach(aip, 0, 1, 1, 2) t.attach(aio, 1, 2, 0, 1) t.attach(fip, 1, 2, 1, 2) return qltk.Frame(_("Column Preferences"), child=t) def create_apply_button(): vbox = Gtk.VBox(spacing=12) apply = Button(_("_Apply")) apply.set_tooltip_text( _("Apply current configuration to song list, " "adding new columns to the end")) apply.connect('clicked', self.__apply, buttons) # Apply on destroy, else config gets mangled self.connect('destroy', self.__apply, buttons) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(apply, True, True, 0) vbox.pack_start(b, True, True, 0) return vbox super(PreferencesWindow.SongList, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Song List") self.pack_start(create_behaviour_frame(), False, True, 0) columns_frame, buttons = create_visible_columns_frame() self.pack_start(columns_frame, False, True, 0) self.pack_start(create_columns_prefs_frame(), False, True, 0) self.pack_start(create_apply_button(), True, True, 0) self.__update(buttons, self._toggle_data, get_columns()) for child in self.get_children(): child.show_all()
def main(argv): import quodlibet quodlibet.init_cli() try: # we want basic commands not to import gtk (doubles process time) assert "gi.repository.Gtk" not in sys.modules sys.modules["gi.repository.Gtk"] = None startup_actions, cmds_todo = process_arguments(argv) finally: sys.modules.pop("gi.repository.Gtk", None) quodlibet.init() from quodlibet import app from quodlibet.qltk import add_signal_watch, Icons add_signal_watch(app.quit) import quodlibet.player import quodlibet.library from quodlibet import config from quodlibet import browsers from quodlibet import util from quodlibet.util.string import decode app.name = "Quod Libet" app.id = "quodlibet" quodlibet.set_application_info(Icons.QUODLIBET, app.id, app.name) config.init(os.path.join(quodlibet.get_user_dir(), "config")) library_path = os.path.join(quodlibet.get_user_dir(), "songs") print_d("Initializing main library (%s)" % ( quodlibet.util.path.unexpand(library_path))) library = quodlibet.library.init(library_path) app.library = library # this assumes that nullbe will always succeed from quodlibet.player import PlayerError wanted_backend = os.environ.get( "QUODLIBET_BACKEND", config.get("player", "backend")) backend_traceback = None for backend in [wanted_backend, "nullbe"]: try: player = quodlibet.player.init_player(backend, app.librarian) except PlayerError: backend_traceback = decode(traceback.format_exc()) else: break app.player = player os.environ["PULSE_PROP_media.role"] = "music" os.environ["PULSE_PROP_application.icon_name"] = "quodlibet" browsers.init() from quodlibet.qltk.songlist import SongList, get_columns from quodlibet.util.collection import Album try: cover_size = config.getint("browsers", "cover_size") except config.Error: pass else: if cover_size > 0: Album.COVER_SIZE = cover_size headers = get_columns() SongList.set_all_column_headers(headers) for opt in config.options("header_maps"): val = config.get("header_maps", opt) util.tags.add(opt, val) in_all = ("~filename ~uri ~#lastplayed ~#rating ~#playcount ~#skipcount " "~#added ~#bitrate ~current ~#laststarted ~basename " "~dirname").split() for Kind in browsers.browsers: if Kind.headers is not None: Kind.headers.extend(in_all) Kind.init(library) pm = quodlibet.init_plugins("no-plugins" in startup_actions) if hasattr(player, "init_plugins"): player.init_plugins() from quodlibet.qltk import unity unity.init("quodlibet.desktop", player) from quodlibet.qltk.songsmenu import SongsMenu SongsMenu.init_plugins() from quodlibet.util.cover import CoverManager app.cover_manager = CoverManager() app.cover_manager.init_plugins() from quodlibet.plugins.playlist import PLAYLIST_HANDLER PLAYLIST_HANDLER.init_plugins() from gi.repository import GLib def exec_commands(*args): for cmd in cmds_todo: try: resp = cmd_registry.run(app, *cmd) except CommandError: pass else: if resp is not None: print_(resp, end="") from quodlibet.qltk.quodlibetwindow import QuodLibetWindow, PlayerOptions # Call exec_commands after the window is restored, but make sure # it's after the mainloop has started so everything is set up. app.window = window = QuodLibetWindow( library, player, restore_cb=lambda: GLib.idle_add(exec_commands, priority=GLib.PRIORITY_HIGH)) app.player_options = PlayerOptions(window) from quodlibet.qltk.debugwindow import MinExceptionDialog from quodlibet.qltk.window import on_first_map if backend_traceback is not None: def show_backend_error(window): d = MinExceptionDialog(window, _("Audio Backend Failed to Load"), _("Loading the audio backend '%(name)s' failed. " "Audio playback will be disabled.") % {"name": wanted_backend}, backend_traceback) d.run() # so we show the main window first on_first_map(app.window, show_backend_error, app.window) from quodlibet.plugins.events import EventPluginHandler pm.register_handler(EventPluginHandler(library.librarian, player)) from quodlibet.mmkeys import MMKeysHandler from quodlibet.remote import Remote, RemoteError from quodlibet.commands import registry as cmd_registry, CommandError from quodlibet.qltk.tracker import SongTracker, FSInterface try: from quodlibet.qltk.dbus_ import DBusHandler except ImportError: DBusHandler = lambda player, library: None mmkeys_handler = MMKeysHandler(app.name, window, player) if "QUODLIBET_NO_MMKEYS" not in os.environ: mmkeys_handler.start() current_path = os.path.join(quodlibet.get_user_dir(), "current") fsiface = FSInterface(current_path, player) remote = Remote(app, cmd_registry) try: remote.start() except RemoteError: exit_(1, True) DBusHandler(player, library) tracker = SongTracker(library.librarian, player, window.playlist) from quodlibet.qltk import session session.init("quodlibet") quodlibet.enable_periodic_save(save_library=True) if "start-playing" in startup_actions: player.paused = False # restore browser windows from quodlibet.qltk.browser import LibraryBrowser GLib.idle_add(LibraryBrowser.restore, library, player, priority=GLib.PRIORITY_HIGH) def before_quit(): print_d("Saving active browser state") try: app.browser.save() except NotImplementedError: pass print_d("Shutting down player device %r." % player.version_info) player.destroy() quodlibet.main(window, before_quit=before_quit) app.player_options.destroy() quodlibet.finish_first_session(app.id) mmkeys_handler.quit() remote.stop() fsiface.destroy() tracker.destroy() quodlibet.library.save() config.save() print_d("Finished shutdown.")
def main(argv=None): if argv is None: argv = sys_argv import quodlibet config_file = os.path.join(quodlibet.get_user_dir(), "config") quodlibet.init_cli(config_file=config_file) try: # we want basic commands not to import gtk (doubles process time) assert "gi.repository.Gtk" not in sys.modules sys.modules["gi.repository.Gtk"] = None startup_actions, cmds_todo = process_arguments(argv) finally: sys.modules.pop("gi.repository.Gtk", None) quodlibet.init() from quodlibet import app from quodlibet.qltk import add_signal_watch, Icons add_signal_watch(app.quit) import quodlibet.player import quodlibet.library from quodlibet import config from quodlibet import browsers from quodlibet import util app.name = "Quod Libet" app.id = "quodlibet" quodlibet.set_application_info(Icons.QUODLIBET, app.id, app.name) library_path = os.path.join(quodlibet.get_user_dir(), "songs") print_d("Initializing main library (%s)" % ( quodlibet.util.path.unexpand(library_path))) library = quodlibet.library.init(library_path) app.library = library # this assumes that nullbe will always succeed from quodlibet.player import PlayerError wanted_backend = environ.get( "QUODLIBET_BACKEND", config.get("player", "backend")) try: player = quodlibet.player.init_player(wanted_backend, app.librarian) except PlayerError: print_exc() player = quodlibet.player.init_player("nullbe", app.librarian) app.player = player environ["PULSE_PROP_media.role"] = "music" environ["PULSE_PROP_application.icon_name"] = "quodlibet" browsers.init() from quodlibet.qltk.songlist import SongList, get_columns headers = get_columns() SongList.set_all_column_headers(headers) for opt in config.options("header_maps"): val = config.get("header_maps", opt) util.tags.add(opt, val) in_all = ("~filename ~uri ~#lastplayed ~#rating ~#playcount ~#skipcount " "~#added ~#bitrate ~current ~#laststarted ~basename " "~dirname").split() for Kind in browsers.browsers: if Kind.headers is not None: Kind.headers.extend(in_all) Kind.init(library) pm = quodlibet.init_plugins("no-plugins" in startup_actions) if hasattr(player, "init_plugins"): player.init_plugins() from quodlibet.qltk import unity unity.init("quodlibet.desktop", player) from quodlibet.qltk.songsmenu import SongsMenu SongsMenu.init_plugins() from quodlibet.util.cover import CoverManager app.cover_manager = CoverManager() app.cover_manager.init_plugins() from quodlibet.plugins.playlist import PLAYLIST_HANDLER PLAYLIST_HANDLER.init_plugins() from quodlibet.plugins.query import QUERY_HANDLER QUERY_HANDLER.init_plugins() from gi.repository import GLib def exec_commands(*args): for cmd in cmds_todo: try: resp = cmd_registry.run(app, *cmd) except CommandError: pass else: if resp is not None: print_(resp, end="", flush=True) from quodlibet.qltk.quodlibetwindow import QuodLibetWindow, PlayerOptions # Call exec_commands after the window is restored, but make sure # it's after the mainloop has started so everything is set up. app.window = window = QuodLibetWindow( library, player, restore_cb=lambda: GLib.idle_add(exec_commands, priority=GLib.PRIORITY_HIGH)) app.player_options = PlayerOptions(window) from quodlibet.qltk.window import Window from quodlibet.plugins.events import EventPluginHandler from quodlibet.plugins.gui import UserInterfacePluginHandler pm.register_handler(EventPluginHandler(library.librarian, player, app.window.songlist)) pm.register_handler(UserInterfacePluginHandler()) from quodlibet.mmkeys import MMKeysHandler from quodlibet.remote import Remote, RemoteError from quodlibet.commands import registry as cmd_registry, CommandError from quodlibet.qltk.tracker import SongTracker, FSInterface try: from quodlibet.qltk.dbus_ import DBusHandler except ImportError: DBusHandler = lambda player, library: None mmkeys_handler = MMKeysHandler(app) mmkeys_handler.start() current_path = os.path.join(quodlibet.get_user_dir(), "current") fsiface = FSInterface(current_path, player) remote = Remote(app, cmd_registry) try: remote.start() except RemoteError: exit_(1, True) DBusHandler(player, library) tracker = SongTracker(library.librarian, player, window.playlist) from quodlibet.qltk import session session.init("quodlibet") quodlibet.enable_periodic_save(save_library=True) if "start-playing" in startup_actions: player.paused = False if "start-hidden" in startup_actions: Window.prevent_inital_show(True) # restore browser windows from quodlibet.qltk.browser import LibraryBrowser GLib.idle_add(LibraryBrowser.restore, library, player, priority=GLib.PRIORITY_HIGH) def before_quit(): print_d("Saving active browser state") try: app.browser.save() except NotImplementedError: pass print_d("Shutting down player device %r." % player.version_info) player.destroy() quodlibet.run(window, before_quit=before_quit) app.player_options.destroy() quodlibet.finish_first_session(app.id) mmkeys_handler.quit() remote.stop() fsiface.destroy() tracker.destroy() quodlibet.library.save() config.save() print_d("Finished shutdown.")
def __init__(self): def create_behaviour_frame(): vbox = Gtk.VBox(spacing=6) c = CCB(_("_Jump to playing song automatically"), 'settings', 'jump', populate=True, tooltip=_("When the playing song changes, " "scroll to it in the song list")) vbox.pack_start(c, False, True, 0) return qltk.Frame(_("Behavior"), child=vbox) def create_visible_columns_frame(): buttons = {} vbox = Gtk.VBox(spacing=12) table = Gtk.Table.new(3, 3, True) for i, (k, t) in enumerate(self.PREDEFINED_TAGS): x, y = i % 3, i / 3 buttons[k] = Gtk.CheckButton(label=t, use_underline=True) table.attach(buttons[k], x, x + 1, y, y + 1) vbox.pack_start(table, False, True, 0) # Other columns hbox = Gtk.HBox(spacing=6) l = Gtk.Label(label=_("_Others:"), use_underline=True) hbox.pack_start(l, False, True, 0) self.others = others = UndoEntry() others.set_sensitive(False) # Stock edit doesn't have ellipsis chars. edit_button = Gtk.Button( label=_(u"_Edit…"), use_underline=True) edit_button.connect("clicked", self.__config_cols, buttons) edit_button.set_tooltip_text( _("Add or remove additional column " "headers")) l.set_mnemonic_widget(edit_button) l.set_use_underline(True) hbox.pack_start(others, True, True, 0) vbox.pack_start(hbox, False, True, 0) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(edit_button, True, True, 0) vbox.pack_start(b, True, True, 0) return qltk.Frame(_("Visible Columns"), child=vbox), buttons def create_columns_prefs_frame(): tiv = Gtk.CheckButton(label=_("Title includes _version"), use_underline=True) aio = Gtk.CheckButton(label=_("Artist includes all _people"), use_underline=True) aip = Gtk.CheckButton(label=_("Album includes _disc subtitle"), use_underline=True) fip = Gtk.CheckButton(label=_("Filename includes _folder"), use_underline=True) self._toggle_data = [ (tiv, "title", "~title~version"), (aip, "album", "~album~discsubtitle"), (fip, "~basename", "~filename"), (aio, "artist", "~people") ] t = Gtk.Table.new(2, 2, True) t.attach(tiv, 0, 1, 0, 1) t.attach(aip, 0, 1, 1, 2) t.attach(aio, 1, 2, 0, 1) t.attach(fip, 1, 2, 1, 2) return qltk.Frame(_("Column Preferences"), child=t) def create_apply_button(): vbox = Gtk.VBox(spacing=12) apply = Button(_("_Apply")) apply.set_tooltip_text( _("Apply current configuration to song list, " "adding new columns to the end")) apply.connect('clicked', self.__apply, buttons) # Apply on destroy, else config gets mangled self.connect('destroy', self.__apply, buttons) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(apply, True, True, 0) vbox.pack_start(b, True, True, 0) return vbox super().__init__(spacing=12) self.set_border_width(12) self.title = _("Song List") self.pack_start(create_behaviour_frame(), False, True, 0) columns_frame, buttons = create_visible_columns_frame() self.pack_start(columns_frame, False, True, 0) self.pack_start(create_columns_prefs_frame(), False, True, 0) self.pack_start(create_apply_button(), True, True, 0) self.__update(buttons, self._toggle_data, get_columns()) for child in self.get_children(): child.show_all()
def main(): try: # we want basic commands not to import gtk (doubles process time) assert "gi.repository.Gtk" not in sys.modules sys.modules["gi.repository.Gtk"] = None startup_actions = process_arguments() # this will exit if it succeeds control('focus', ignore_error=True) finally: sys.modules.pop("gi.repository.Gtk", None) import quodlibet from quodlibet import app from quodlibet.qltk import add_signal_watch, icons add_signal_watch(app.quit) import quodlibet.player import quodlibet.library from quodlibet import config from quodlibet import browsers from quodlibet import const from quodlibet import util config.init(const.CONFIG) app.name = "Quod Libet" app.id = "quodlibet" quodlibet.init(icon=icons.QUODLIBET, name=app.name, proc_title=app.id) print_d("Initializing main library (%s)" % ( quodlibet.util.path.unexpand(const.LIBRARY))) library = quodlibet.library.init(const.LIBRARY) app.library = library from quodlibet.player import PlayerError # this assumes that nullbe will always succeed for backend in [config.get("player", "backend"), "nullbe"]: try: player = quodlibet.init_backend(backend, app.librarian) except PlayerError as error: print_e("%s. %s" % (error.short_desc, error.long_desc)) else: break app.player = player os.environ["PULSE_PROP_media.role"] = "music" os.environ["PULSE_PROP_application.icon_name"] = "quodlibet" browsers.init() from quodlibet.qltk.songlist import SongList, get_columns from quodlibet.util.collection import Album try: cover_size = config.getint("browsers", "cover_size") except config.Error: pass else: if cover_size > 0: Album.COVER_SIZE = cover_size headers = get_columns() SongList.set_all_column_headers(headers) for opt in config.options("header_maps"): val = config.get("header_maps", opt) util.tags.add(opt, val) in_all = ("~filename ~uri ~#lastplayed ~#rating ~#playcount ~#skipcount " "~#added ~#bitrate ~current ~#laststarted ~basename " "~dirname").split() for Kind in browsers.browsers: if Kind.headers is not None: Kind.headers.extend(in_all) Kind.init(library) pm = quodlibet.init_plugins("no-plugins" in startup_actions) if hasattr(player, "init_plugins"): player.init_plugins() from quodlibet.qltk import unity unity.init("quodlibet.desktop", player) from quodlibet.qltk.songsmenu import SongsMenu SongsMenu.init_plugins() from quodlibet.util.cover import CoverManager app.cover_manager = CoverManager() app.cover_manager.init_plugins() from quodlibet.plugins.playlist import PLAYLIST_HANDLER PLAYLIST_HANDLER.init_plugins() from quodlibet.qltk.quodlibetwindow import QuodLibetWindow app.window = window = QuodLibetWindow(library, player) from quodlibet.plugins.events import EventPluginHandler pm.register_handler(EventPluginHandler(library.librarian, player)) from quodlibet.mmkeys import MMKeysHandler from quodlibet.remote import Remote from quodlibet.commands import registry as cmd_registry from quodlibet.qltk.tracker import SongTracker, FSInterface try: from quodlibet.qltk.dbus_ import DBusHandler except ImportError: DBusHandler = lambda player, library: None mmkeys_handler = MMKeysHandler(app.name, window, player) if "QUODLIBET_NO_MMKEYS" not in os.environ: mmkeys_handler.start() fsiface = FSInterface(player) remote = Remote(app, cmd_registry) remote.start() DBusHandler(player, library) tracker = SongTracker(library.librarian, player, window.playlist) from quodlibet.qltk import session session.init("quodlibet") quodlibet.enable_periodic_save(save_library=True) if "start-playing" in startup_actions: player.paused = False # restore browser windows from quodlibet.qltk.browser import LibraryBrowser from gi.repository import GLib GLib.idle_add(LibraryBrowser.restore, library, player, priority=GLib.PRIORITY_HIGH) def before_quit(): print_d("Saving active browser state") try: app.browser.save() except NotImplementedError: pass quodlibet.main(window, before_quit=before_quit) quodlibet.finish_first_session(app.id) mmkeys_handler.quit() remote.stop() fsiface.destroy() print_d("Shutting down player device %r." % player.version_info) player.destroy() tracker.destroy() quodlibet.library.save(force=True) config.save(const.CONFIG) print_d("Finished shutdown.")
def main(argv=None): if argv is None: argv = sys_argv import quodlibet config_file = os.path.join(quodlibet.get_user_dir(), "config") quodlibet.init_cli(config_file=config_file) try: # we want basic commands not to import gtk (doubles process time) assert "gi.repository.Gtk" not in sys.modules sys.modules["gi.repository.Gtk"] = None startup_actions, cmds_todo = process_arguments(argv) finally: sys.modules.pop("gi.repository.Gtk", None) quodlibet.init() from quodlibet import app from quodlibet.qltk import add_signal_watch, Icons add_signal_watch(app.quit) import quodlibet.player import quodlibet.library from quodlibet import config from quodlibet import browsers from quodlibet import util app.name = "Quod Libet" app.description = _("Music player and music library manager") app.id = "quodlibet" quodlibet.set_application_info(Icons.QUODLIBET, app.id, app.name) library_path = os.path.join(quodlibet.get_user_dir(), "songs") print_d("Initializing main library (%s)" % ( quodlibet.util.path.unexpand(library_path))) library = quodlibet.library.init(library_path) app.library = library # this assumes that nullbe will always succeed from quodlibet.player import PlayerError wanted_backend = environ.get( "QUODLIBET_BACKEND", config.get("player", "backend")) try: player = quodlibet.player.init_player(wanted_backend, app.librarian) except PlayerError: print_exc() player = quodlibet.player.init_player("nullbe", app.librarian) app.player = player environ["PULSE_PROP_media.role"] = "music" environ["PULSE_PROP_application.icon_name"] = "quodlibet" browsers.init() from quodlibet.qltk.songlist import SongList, get_columns headers = get_columns() SongList.set_all_column_headers(headers) for opt in config.options("header_maps"): val = config.get("header_maps", opt) util.tags.add(opt, val) in_all = ("~filename ~uri ~#lastplayed ~#rating ~#playcount ~#skipcount " "~#added ~#bitrate ~current ~#laststarted ~basename " "~dirname").split() for Kind in browsers.browsers: if Kind.headers is not None: Kind.headers.extend(in_all) Kind.init(library) pm = quodlibet.init_plugins("no-plugins" in startup_actions) if hasattr(player, "init_plugins"): player.init_plugins() from quodlibet.qltk import unity unity.init("quodlibet.desktop", player) from quodlibet.qltk.songsmenu import SongsMenu SongsMenu.init_plugins() from quodlibet.util.cover import CoverManager app.cover_manager = CoverManager() app.cover_manager.init_plugins() from quodlibet.plugins.playlist import PLAYLIST_HANDLER PLAYLIST_HANDLER.init_plugins() from quodlibet.plugins.query import QUERY_HANDLER QUERY_HANDLER.init_plugins() from gi.repository import GLib def exec_commands(*args): for cmd in cmds_todo: try: resp = cmd_registry.run(app, *cmd) except CommandError: pass else: if resp is not None: print_(resp, end="", flush=True) from quodlibet.qltk.quodlibetwindow import QuodLibetWindow, PlayerOptions # Call exec_commands after the window is restored, but make sure # it's after the mainloop has started so everything is set up. app.window = window = QuodLibetWindow( library, player, restore_cb=lambda: GLib.idle_add(exec_commands, priority=GLib.PRIORITY_HIGH)) app.player_options = PlayerOptions(window) from quodlibet.qltk.window import Window from quodlibet.plugins.events import EventPluginHandler from quodlibet.plugins.gui import UserInterfacePluginHandler pm.register_handler(EventPluginHandler(library.librarian, player, app.window.songlist)) pm.register_handler(UserInterfacePluginHandler()) from quodlibet.mmkeys import MMKeysHandler from quodlibet.remote import Remote, RemoteError from quodlibet.commands import registry as cmd_registry, CommandError from quodlibet.qltk.tracker import SongTracker, FSInterface try: from quodlibet.qltk.dbus_ import DBusHandler except ImportError: DBusHandler = lambda player, library: None mmkeys_handler = MMKeysHandler(app) mmkeys_handler.start() current_path = os.path.join(quodlibet.get_user_dir(), "current") fsiface = FSInterface(current_path, player) remote = Remote(app, cmd_registry) try: remote.start() except RemoteError: exit_(1, True) DBusHandler(player, library) tracker = SongTracker(library.librarian, player, window.playlist) from quodlibet.qltk import session session.init("quodlibet") quodlibet.enable_periodic_save(save_library=True) if "start-playing" in startup_actions: player.paused = False if "start-hidden" in startup_actions: Window.prevent_inital_show(True) # restore browser windows from quodlibet.qltk.browser import LibraryBrowser GLib.idle_add(LibraryBrowser.restore, library, player, priority=GLib.PRIORITY_HIGH) def before_quit(): print_d("Saving active browser state") try: app.browser.save() except NotImplementedError: pass print_d("Shutting down player device %r." % player.version_info) player.destroy() quodlibet.run(window, before_quit=before_quit) app.player_options.destroy() quodlibet.finish_first_session(app.id) mmkeys_handler.quit() remote.stop() fsiface.destroy() tracker.destroy() quodlibet.library.save() config.save() print_d("Finished shutdown.")