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 setUp(self): config.init() self.songlist = SongList(SongLibrary()) self.orders_changed = 0 def orders_changed_cb(*args): self.orders_changed += 1 self.songlist.connect("orders-changed", orders_changed_cb)
def setUp(self): self.tempdir = mkdtemp() self.pm = PluginManager(folders=[self.tempdir]) self.lib = SongLibrarian() lib = SongLibrary() lib.librarian = self.lib self.songlist = SongList(library=lib) self.player = player.init_player("nullbe", self.lib) self.handler = EventPluginHandler( librarian=self.lib, player=self.player, songlist=self.songlist) self.pm.register_handler(self.handler) self.pm.rescan() self.assertEquals(self.pm.plugins, [])
def __apply(self, button, buttons, tiv, aip, fip, others): headers = [] for key in ["~#disc", "~#track", "title", "album", "artist", "date", "~basename", "~#rating", "~#length"]: if buttons[key].get_active(): headers.append(key) if tiv.get_active(): try: headers[headers.index("title")] = "~title~version" except ValueError: pass if aip.get_active(): try: headers[headers.index("album")] = "~album~discsubtitle" except ValueError: pass if fip.get_active(): try: headers[headers.index("~basename")] = "~filename" except ValueError: pass headers.extend(others.get_text().split()) if "~current" in headers: headers.remove("~current") headers = [header.lower() for header in headers] SongList.set_all_column_headers(headers)
def setUp(self): config.init() self.lib = SongFileLibrary() self.songlist = SongList(self.lib) assert not self.lib.librarian, "not expecting a librarian - leaky test?" self.orders_changed = 0 self.songs_removed: List[Set] = [] def orders_changed_cb(*args): self.orders_changed += 1 def orders_removed_cb(songlist, removed): self.songs_removed.append(removed) self.__sigs = [ self.songlist.connect("orders-changed", orders_changed_cb), self.songlist.connect("songs-removed", orders_removed_cb) ]
try: ratings = config.getint("settings", "ratings") except (ValueError, TypeError): pass else: util.RATING_PRECISION = 1.0/ratings try: default_rating = config.getfloat("settings", "default_rating") except (ValueError, TypeError): pass else: const.DEFAULT_RATING = default_rating try: symbol = config.get("settings", "rating_symbol").decode("utf-8") except UnicodeDecodeError: pass else: util.RATING_SYMBOL = symbol if config.get("settings", "headers").split() == []: config.set("settings", "headers", "title") headers = config.get("settings", "headers").split() 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) if hasattr(player, "init_plugins"):
def __init__(self, Kind, library, player): super(LibraryBrowser, self).__init__(dialog=False) self._register_instance() self.name = Kind.__name__ self.set_default_size(600, 400) self.enable_window_tracking("browser_" + self.name) self.set_title(Kind.name + " - Quod Libet") self.add(Gtk.VBox()) view = SongList(library, update=True) view.info.connect("changed", self.__set_totals) self.songlist = view sw = ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(view) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.browser = browser = Kind(library) if browser.can_reorder: view.enable_drop() elif browser.dropped: view.enable_drop(False) if browser.accelerators: self.add_accel_group(browser.accelerators) self.__container = browser.pack(sw) self.get_child().pack_start(self.__container, True, True, 0) main = self.get_child() bottom = Gtk.HBox() main.pack_end(bottom, False, True, 0) self._filter_menu = filter_menu = FilterMenu(library, player) filter_menu.set_browser(self.browser) self.add_accel_group(filter_menu.get_accel_group()) bottom.pack_start(filter_menu.get_widget(), False, True, 0) filter_menu.get_widget().show() self.__statusbar = Gtk.Label() self.__statusbar.set_alignment(1.0, 0.5) self.__statusbar.set_padding(6, 3) self.__statusbar.set_ellipsize(Pango.EllipsizeMode.START) bottom.pack_end(self.__statusbar, True, True, 0) self.__statusbar.show() bottom.show() browser.connect('songs-selected', self.__browser_cb) browser.finalize(False) view.connect('popup-menu', self.__menu, library) view.connect('drag-data-received', self.__drag_data_recv) view.connect('row-activated', self.__enqueue, player) if browser.headers is not None: view.connect('columns-changed', self.__cols_changed, browser) self.__cols_changed(view, browser) sw.show_all() for c in self.get_child().get_children(): c.show() self.get_child().show() self.connect("destroy", self._on_destroy)
def __init__(self, Kind, library, player): super(LibraryBrowser, self).__init__(dialog=False) self._register_instance() self.name = Kind.__name__ self.set_default_size(600, 400) self.enable_window_tracking("browser_" + self.name) self.set_title(Kind.name + " - Quod Libet") self.add(Gtk.VBox()) view = SongList(library, update=True) view.info.connect("changed", self.__set_time) self.songlist = view sw = ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(view) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.browser = browser = Kind(library) if browser.can_reorder: view.enable_drop() elif browser.dropped: view.enable_drop(False) if browser.accelerators: self.add_accel_group(browser.accelerators) self.__container = browser.pack(sw) self.get_child().pack_start(self.__container, True, True, 0) main = self.get_child() bottom = Gtk.HBox() main.pack_end(bottom, False, True, 0) self._filter_menu = filter_menu = FilterMenu(library, player) filter_menu.set_browser(self.browser) self.add_accel_group(filter_menu.get_accel_group()) bottom.pack_start(filter_menu.get_widget(), False, True, 0) filter_menu.get_widget().show() self.__statusbar = Gtk.Label() self.__statusbar.set_text(_("No time information")) self.__statusbar.set_alignment(1.0, 0.5) self.__statusbar.set_padding(6, 3) self.__statusbar.set_ellipsize(Pango.EllipsizeMode.START) bottom.pack_end(self.__statusbar, True, True, 0) self.__statusbar.show() bottom.show() browser.connect('songs-selected', self.__browser_cb) browser.finalize(False) view.connect('popup-menu', self.__menu, library) view.connect('drag-data-received', self.__drag_data_recv) view.connect('row-activated', self.__enqueue, player) if browser.headers is not None: view.connect('columns-changed', self.__cols_changed, browser) self.__cols_changed(view, browser) sw.show_all() for c in self.get_child().get_children(): c.show() self.get_child().show() self.connect("destroy", self._on_destroy)
class TEventPlugins(TestCase): def setUp(self): self.tempdir = mkdtemp() self.pm = PluginManager(folders=[self.tempdir]) self.lib = SongLibrarian() lib = SongLibrary() lib.librarian = self.lib self.songlist = SongList(library=lib) self.player = player.init_player("nullbe", self.lib) self.handler = EventPluginHandler(librarian=self.lib, player=self.player, songlist=self.songlist) self.pm.register_handler(self.handler) self.pm.rescan() self.assertEquals(self.pm.plugins, []) def tearDown(self): self.pm.quit() shutil.rmtree(self.tempdir) def create_plugin(self, name='', funcs=None): fd, fn = mkstemp(suffix='.py', text=True, dir=self.tempdir) file = os.fdopen(fd, 'w') file.write("from quodlibet.plugins.events import EventPlugin\n") file.write("log = []\n") file.write("class %s(EventPlugin):\n" % name) indent = ' ' file.write("%spass\n" % indent) if name: file.write("%sPLUGIN_ID = %r\n" % (indent, name)) file.write("%sPLUGIN_NAME = %r\n" % (indent, name)) for f in (funcs or []): file.write("%sdef %s(s, *args): log.append((%r, args))\n" % (indent, f, f)) file.flush() file.close() def _get_calls(self, plugin): mod = sys.modules[plugin.cls.__module__] return mod.log def test_found(self): self.create_plugin(name='Name') self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) def test_player_paused(self): self.create_plugin(name='Name', funcs=["plugin_on_paused"]) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) plugin = self.pm.plugins[0] self.pm.enable(plugin, True) self.player.emit("paused") self.failUnlessEqual([("plugin_on_paused", tuple())], self._get_calls(plugin)) def test_lib_changed(self): self.create_plugin(name='Name', funcs=["plugin_on_changed"]) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) plugin = self.pm.plugins[0] self.pm.enable(plugin, True) self.lib.emit("changed", [None]) self.failUnlessEqual([("plugin_on_changed", ([None], ))], self._get_calls(plugin)) def test_songs_selected(self): self.create_plugin(name='Name', funcs=["plugin_on_songs_selected"]) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) plugin = self.pm.plugins[0] self.pm.enable(plugin, True) self.songlist.emit("selection-changed", self.songlist.get_selection()) self.failUnlessEqual(self._get_calls(plugin), [("plugin_on_songs_selected", ([], ))])
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(): 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.")
class TSongList(TestCase): HEADERS = ["acolumn", "~#lastplayed", "~foo~bar", "~#rating", "~#length", "~dirname", "~#track"] def setUp(self): quodlibet.config.init() self.songlist = SongList(SongLibrary()) def test_set_all_column_headers(self): SongList.set_all_column_headers(self.HEADERS) headers = [col.header_name for col in self.songlist.get_columns()] self.failUnlessEqual(headers, self.HEADERS) def test_set_column_headers(self): self.songlist.set_column_headers(self.HEADERS) headers = [col.header_name for col in self.songlist.get_columns()] self.failUnlessEqual(headers, self.HEADERS) def test_drop(self): self.songlist.enable_drop() self.songlist.disable_drop() def test_sort_by(self): self.songlist.set_column_headers(["one", "two", "three"]) for key, order in [("one", True), ("two", False), ("three", False)]: self.songlist.set_sort_by(None, tag=key, order=order) self.failUnlessEqual(self.songlist.get_sort_by(), (key, order)) self.songlist.set_sort_by(self.songlist.get_columns()[-1], tag="three") self.failUnlessEqual(self.songlist.get_sort_by(), ("three", True)) def tearDown(self): self.songlist.destroy() quodlibet.config.quit()
def setUp(self): quodlibet.config.init() self.songlist = SongList(SongLibrary())
def test_set_all_column_headers(self): SongList.set_all_column_headers(self.HEADERS) headers = [col.header_name for col in self.songlist.get_columns()] self.failUnlessEqual(headers, self.HEADERS)
class TSongList(TestCase): HEADERS = ["acolumn", "~#lastplayed", "~foo~bar", "~#rating", "~#length", "~dirname", "~#track"] def setUp(self): config.init() self.songlist = SongList(SongLibrary()) self.orders_changed = 0 def orders_changed_cb(*args): self.orders_changed += 1 self.songlist.connect("orders-changed", orders_changed_cb) def test_set_all_column_headers(self): SongList.set_all_column_headers(self.HEADERS) headers = [col.header_name for col in self.songlist.get_columns()] self.failUnlessEqual(headers, self.HEADERS) def test_set_column_headers(self): self.songlist.set_column_headers(self.HEADERS) headers = [col.header_name for col in self.songlist.get_columns()] self.failUnlessEqual(headers, self.HEADERS) def test_drop(self): self.songlist.enable_drop() self.songlist.disable_drop() def test_sort_by(self): self.songlist.set_column_headers(["one", "two", "three"]) for key, order in [("one", True), ("two", False), ("three", False)]: self.songlist.set_sort_orders([(key, order)]) self.failUnlessEqual( self.songlist.get_sort_orders(), [(key, order)]) self.songlist.toggle_column_sort(self.songlist.get_columns()[-1]) self.failUnlessEqual( self.songlist.get_sort_orders(), [("three", True)]) def test_sort_orders(self): s = self.songlist s.set_column_headers(["foo", "quux", "bar"]) values = [("foo", True), ("bar", False)] s.set_sort_orders(values) self.assertEqual(s.get_sort_orders(), values) s.toggle_column_sort(s.get_columns()[1], replace=False) self.assertEqual(s.get_sort_orders(), values + [("quux", False)]) s.toggle_column_sort(s.get_columns()[1], replace=True) self.assertEqual(s.get_sort_orders(), [("quux", False)]) def test_toggle_sort(self): s = self.songlist s.set_column_headers(["foo"]) self.assertEqual(self.orders_changed, 1) s.toggle_column_sort(s.get_columns()[0], replace=True) self.assertEqual(self.orders_changed, 2) self.assertEqual(s.get_sort_orders(), [("foo", False)]) s.toggle_column_sort(s.get_columns()[0], replace=True) self.assertEqual(self.orders_changed, 3) self.assertEqual(s.get_sort_orders(), [("foo", True)]) def test_clear_sort(self): s = self.songlist s.set_column_headers(["foo"]) s.toggle_column_sort(s.get_columns()[0], replace=True) self.assertTrue(s.get_sort_orders()) s.clear_sort() self.assertFalse(s.get_sort_orders()) def test_not_sortable(self): s = self.songlist s.sortable = False s.set_column_headers(["foo"]) s.toggle_column_sort(s.get_columns()[0]) self.assertEqual(self.orders_changed, 0) self.assertFalse(s.get_sort_orders()) def test_find_default_sort_column(self): s = self.songlist self.assertTrue(s.find_default_sort_column() is None) s.set_column_headers(["~#track"]) self.assertTrue(s.find_default_sort_column()) def test_inline_search_state(self): self.assertEqual(self.songlist.get_search_column(), 0) self.assertTrue(self.songlist.get_enable_search()) def test_set_songs(self): self.songlist.set_songs([], sorted=True) self.songlist.set_songs([], sorted=False) self.songlist.set_songs([], scroll_select=True) self.songlist.set_songs([], scroll_select=False) self.songlist.set_songs([], scroll=True) self.songlist.set_songs([], scroll=False) def test_set_songs_restore_select(self): song = AudioFile({"~filename": "/dev/null"}) self.songlist.add_songs([song]) sel = self.songlist.get_selection() sel.select_path(Gtk.TreePath.new_first()) self.songlist.set_songs([song], scroll_select=True) self.assertEqual(self.songlist.get_selected_songs(), [song]) song2 = AudioFile({"~filename": "/dev/null"}) self.songlist.set_songs([song2], scroll_select=True) self.assertEqual(self.songlist.get_selected_songs(), []) def test_set_songs_no_restore_select(self): song = AudioFile({"~filename": "/dev/null"}) self.songlist.add_songs([song]) model = self.songlist.get_model() model.go_to(song) self.assertIs(model.current, song) # only restore if there was a selected one self.songlist.set_songs([song], scroll_select=True) self.assertEqual(self.songlist.get_selected_songs(), []) def test_get_selected_songs(self): song = AudioFile({"~filename": "/dev/null"}) self.songlist.add_songs([song]) sel = self.songlist.get_selection() sel.select_path(Gtk.TreePath.new_first()) self.assertEqual(self.songlist.get_selected_songs(), [song]) self.assertEqual(self.songlist.get_first_selected_song(), song) sel.unselect_all() self.assertEqual(self.songlist.get_selected_songs(), []) self.assertIs(self.songlist.get_first_selected_song(), None) def test_add_songs(self): song = AudioFile({"~filename": "/dev/null"}) # unsorted self.songlist.add_songs([song]) self.songlist.add_songs([song]) # sorted self.songlist.set_column_headers(["foo"]) self.songlist.toggle_column_sort(self.songlist.get_columns()[0]) self.songlist.add_songs([]) self.songlist.add_songs([song]) self.songlist.add_songs([song]) self.assertEqual(self.songlist.get_songs(), [song] * 4) def test_header_menu(self): from quodlibet import browsers from quodlibet.library import SongLibrary, SongLibrarian song = AudioFile({"~filename": fsnative(u"/dev/null")}) song.sanitize() self.songlist.set_songs([song]) library = SongLibrary() library.librarian = SongLibrarian() browser = browsers.get("SearchBar")(library) self.songlist.set_column_headers(["foo"]) self.assertFalse(self.songlist.Menu("foo", browser, library)) sel = self.songlist.get_selection() sel.select_all() self.assertTrue(self.songlist.Menu("foo", browser, library)) 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 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 test_header_tag_split(self): self.assertEqual(header_tag_split("foo"), ["foo"]) self.assertEqual(header_tag_split("~foo~bar"), ["foo", "bar"]) self.assertEqual(header_tag_split("<foo>"), ["foo"]) self.assertEqual(header_tag_split("<~foo~bar>"), ["foo", "bar"]) self.assertEqual(header_tag_split("pattern <~foo~bar>"), ["foo", "bar"]) def test_get_sort_tag(self): self.assertEqual(get_sort_tag("~#track"), "") self.assertEqual(get_sort_tag("artist"), "artistsort") self.assertEqual(get_sort_tag("date"), "date") self.assertEqual(get_sort_tag("~artist~date"), "~artistsort~date") self.assertEqual(get_sort_tag("~date~artist"), "~date~artistsort") self.assertEqual(get_sort_tag("composer"), "composersort") def tearDown(self): self.songlist.destroy() config.quit()
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.")
class TSongList(TestCase): HEADERS = [ "acolumn", "~#lastplayed", "~foo~bar", "~#rating", "~#length", "~dirname", "~#track" ] def setUp(self): quodlibet.config.init() self.songlist = SongList(SongLibrary()) def test_set_all_column_headers(self): SongList.set_all_column_headers(self.HEADERS) headers = [col.header_name for col in self.songlist.get_columns()] self.failUnlessEqual(headers, self.HEADERS) def test_set_column_headers(self): self.songlist.set_column_headers(self.HEADERS) headers = [col.header_name for col in self.songlist.get_columns()] self.failUnlessEqual(headers, self.HEADERS) def test_drop(self): self.songlist.enable_drop() self.songlist.disable_drop() def test_sort_by(self): self.songlist.set_column_headers(["one", "two", "three"]) for key, order in [("one", True), ("two", False), ("three", False)]: self.songlist.set_sort_by(None, tag=key, order=order) self.failUnlessEqual(self.songlist.get_sort_by(), (key, order)) self.songlist.set_sort_by(self.songlist.get_columns()[-1], tag="three") self.failUnlessEqual(self.songlist.get_sort_by(), ("three", True)) def test_inline_search_state(self): self.assertEqual(self.songlist.get_search_column(), 0) self.assertTrue(self.songlist.get_enable_search()) def tearDown(self): self.songlist.destroy() quodlibet.config.quit()
class TSongList(TestCase): HEADERS = [ "acolumn", "~#lastplayed", "~foo~bar", "~#rating", "~#length", "~dirname", "~#track" ] def setUp(self): config.init() self.lib = SongFileLibrary() self.songlist = SongList(self.lib) assert not self.lib.librarian, "not expecting a librarian - leaky test?" self.orders_changed = 0 self.songs_removed: List[Set] = [] def orders_changed_cb(*args): self.orders_changed += 1 def orders_removed_cb(songlist, removed): self.songs_removed.append(removed) self.__sigs = [ self.songlist.connect("orders-changed", orders_changed_cb), self.songlist.connect("songs-removed", orders_removed_cb) ] def test_set_all_column_headers(self): SongList.set_all_column_headers(self.HEADERS) headers = [col.header_name for col in self.songlist.get_columns()] self.failUnlessEqual(headers, self.HEADERS) def test_set_column_headers(self): self.songlist.set_column_headers(self.HEADERS) headers = [col.header_name for col in self.songlist.get_columns()] self.failUnlessEqual(headers, self.HEADERS) def test_drop(self): self.songlist.enable_drop() self.songlist.disable_drop() def test_sort_by(self): self.songlist.set_column_headers(["one", "two", "three"]) for key, order in [("one", True), ("two", False), ("three", False)]: self.songlist.set_sort_orders([(key, order)]) self.failUnlessEqual(self.songlist.get_sort_orders(), [(key, order)]) self.songlist.toggle_column_sort(self.songlist.get_columns()[-1]) self.failUnlessEqual(self.songlist.get_sort_orders(), [("three", True)]) def test_sort_orders(self): s = self.songlist s.set_column_headers(["foo", "quux", "bar"]) values = [("foo", True), ("bar", False)] s.set_sort_orders(values) self.assertEqual(s.get_sort_orders(), values) s.toggle_column_sort(s.get_columns()[1], replace=False) self.assertEqual(s.get_sort_orders(), values + [("quux", False)]) s.toggle_column_sort(s.get_columns()[1], replace=True) self.assertEqual(s.get_sort_orders(), [("quux", False)]) def test_toggle_sort(self): s = self.songlist s.set_column_headers(["foo"]) self.assertEqual(self.orders_changed, 1) s.toggle_column_sort(s.get_columns()[0], replace=True) self.assertEqual(self.orders_changed, 2) self.assertEqual(s.get_sort_orders(), [("foo", False)]) s.toggle_column_sort(s.get_columns()[0], replace=True) self.assertEqual(self.orders_changed, 3) self.assertEqual(s.get_sort_orders(), [("foo", True)]) def test_clear_sort(self): s = self.songlist s.set_column_headers(["foo"]) s.toggle_column_sort(s.get_columns()[0], replace=True) self.assertTrue(s.get_sort_orders()) s.clear_sort() self.assertFalse(s.get_sort_orders()) def test_not_sortable(self): s = self.songlist s.sortable = False s.set_column_headers(["foo"]) s.toggle_column_sort(s.get_columns()[0]) self.assertEqual(self.orders_changed, 0) self.assertFalse(s.get_sort_orders()) def test_find_default_sort_column(self): s = self.songlist self.assertTrue(s.find_default_sort_column() is None) s.set_column_headers(["~#track"]) self.assertTrue(s.find_default_sort_column()) def test_inline_search_state(self): self.assertEqual(self.songlist.get_search_column(), 0) self.assertTrue(self.songlist.get_enable_search()) def test_set_songs(self): self.songlist.set_songs([], sorted=True) self.songlist.set_songs([], sorted=False) self.songlist.set_songs([], scroll_select=True) self.songlist.set_songs([], scroll_select=False) self.songlist.set_songs([], scroll=True) self.songlist.set_songs([], scroll=False) def test_set_songs_restore_select(self): song = AudioFile({"~filename": "/dev/null"}) self.songlist.add_songs([song]) sel = self.songlist.get_selection() sel.select_path(Gtk.TreePath.new_first()) self.songlist.set_songs([song], scroll_select=True) self.assertEqual(self.songlist.get_selected_songs(), [song]) song2 = AudioFile({"~filename": "/dev/null"}) self.songlist.set_songs([song2], scroll_select=True) self.assertEqual(self.songlist.get_selected_songs(), []) def test_set_songs_no_restore_select(self): song = AudioFile({"~filename": "/dev/null"}) self.songlist.add_songs([song]) model = self.songlist.get_model() model.go_to(song) self.assertIs(model.current, song) # only restore if there was a selected one self.songlist.set_songs([song], scroll_select=True) self.assertEqual(self.songlist.get_selected_songs(), []) def test_get_selected_songs(self): song = AudioFile({"~filename": "/dev/null"}) self.songlist.add_songs([song]) sel = self.songlist.get_selection() sel.select_path(Gtk.TreePath.new_first()) self.assertEqual(self.songlist.get_selected_songs(), [song]) self.assertEqual(self.songlist.get_first_selected_song(), song) sel.unselect_all() self.assertEqual(self.songlist.get_selected_songs(), []) self.assertIs(self.songlist.get_first_selected_song(), None) def test_add_songs(self): song = AudioFile({"~filename": "/dev/null"}) # unsorted self.songlist.add_songs([song]) self.songlist.add_songs([song]) # sorted self.songlist.set_column_headers(["foo"]) self.songlist.toggle_column_sort(self.songlist.get_columns()[0]) self.songlist.add_songs([]) self.songlist.add_songs([song]) self.songlist.add_songs([song]) self.assertEqual(self.songlist.get_songs(), [song] * 4) def test_remove_songs(self): song = AudioFile({"~filename": "/dev/null"}) song.sanitize() self.lib.add([song]) assert song in self.lib, "Broken library?" self.songlist.add_songs([song]) assert set(self.songlist.get_songs()) == {song} self.lib.remove([song]) assert not list(self.lib), "Didn't get removed" run_gtk_loop() assert self.songs_removed == [{song} ], f"Signal not emitted: {self.__sigs}" def test_header_menu(self): song = AudioFile({"~filename": fsnative(u"/dev/null")}) song.sanitize() self.songlist.set_songs([song]) library = self.lib librarian = SongLibrarian() librarian.register(self.lib, "test") self.lib.librarian = librarian browser = TrackList(library) self.songlist.set_column_headers(["foo"]) self.assertFalse(self.songlist.Menu("foo", browser, library)) sel = self.songlist.get_selection() sel.select_all() self.assertTrue(self.songlist.Menu("foo", browser, library)) librarian.destroy() self.lib.librarian = None 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_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 test_header_tag_split(self): self.assertEqual(header_tag_split("foo"), ["foo"]) self.assertEqual(header_tag_split("~foo~bar"), ["foo", "bar"]) self.assertEqual(header_tag_split("<foo>"), ["foo"]) self.assertEqual(header_tag_split("<~foo~bar>"), ["foo", "bar"]) self.assertEqual(header_tag_split("pattern <~foo~bar>"), ["foo", "bar"]) def test_get_sort_tag(self): self.assertEqual(get_sort_tag("~#track"), "") self.assertEqual(get_sort_tag("artist"), "artistsort") self.assertEqual(get_sort_tag("date"), "date") self.assertEqual(get_sort_tag("~artist~date"), "~artistsort~date") self.assertEqual(get_sort_tag("~date~artist"), "~date~artistsort") self.assertEqual(get_sort_tag("composer"), "composersort") self.assertEqual(get_sort_tag("originalartist"), "originalartistsort") def test_check_sensible_menu_items(self): col = SongListColumn("title") menu = self.songlist._menu(col) submenus = [item.get_submenu() for item in menu.get_children()] names = { item.get_label() for child in submenus if child and not isinstance(child, Gtk.SeparatorMenuItem) for item in child.get_children() } assert {"Title", "Genre", "Comment", "Artist"} < names def tearDown(self): for sig in self.__sigs: self.songlist.disconnect(sig) self.songlist.destroy() self.lib.destroy() config.quit()
class TEventPlugins(TestCase): def setUp(self): self.tempdir = mkdtemp() self.pm = PluginManager(folders=[self.tempdir]) self.lib = SongLibrarian() lib = SongLibrary() lib.librarian = self.lib self.songlist = SongList(library=lib) self.player = player.init_player("nullbe", self.lib) self.handler = EventPluginHandler( librarian=self.lib, player=self.player, songlist=self.songlist) self.pm.register_handler(self.handler) self.pm.rescan() self.assertEquals(self.pm.plugins, []) def tearDown(self): self.pm.quit() shutil.rmtree(self.tempdir) def create_plugin(self, name='', funcs=None): fd, fn = mkstemp(suffix='.py', text=True, dir=self.tempdir) file = os.fdopen(fd, 'w') file.write("from quodlibet.plugins.events import EventPlugin\n") file.write("log = []\n") file.write("class %s(EventPlugin):\n" % name) indent = ' ' file.write("%spass\n" % indent) if name: file.write("%sPLUGIN_ID = %r\n" % (indent, name)) file.write("%sPLUGIN_NAME = %r\n" % (indent, name)) for f in (funcs or []): file.write("%sdef %s(s, *args): log.append((%r, args))\n" % (indent, f, f)) file.flush() file.close() def _get_calls(self, plugin): mod = sys.modules[plugin.cls.__module__] return mod.log def test_found(self): self.create_plugin(name='Name') self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) def test_player_paused(self): self.create_plugin(name='Name', funcs=["plugin_on_paused"]) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) plugin = self.pm.plugins[0] self.pm.enable(plugin, True) self.player.emit("paused") self.failUnlessEqual([("plugin_on_paused", tuple())], self._get_calls(plugin)) def test_lib_changed(self): self.create_plugin(name='Name', funcs=["plugin_on_changed"]) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) plugin = self.pm.plugins[0] self.pm.enable(plugin, True) self.lib.emit("changed", [None]) self.failUnlessEqual([("plugin_on_changed", ([None],))], self._get_calls(plugin)) def test_songs_selected(self): self.create_plugin(name='Name', funcs=["plugin_on_songs_selected"]) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) plugin = self.pm.plugins[0] self.pm.enable(plugin, True) self.songlist.emit("selection-changed", self.songlist.get_selection()) self.failUnlessEqual(self._get_calls(plugin), [("plugin_on_songs_selected", ([], ))])
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, Kind, library): super(LibraryBrowser, self).__init__(dialog=False) self._register_instance() self.name = Kind.__name__ self.set_default_size(600, 400) self.enable_window_tracking("browser_" + self.name) self.set_border_width(6) self.set_title(Kind.name + " - Quod Libet") self.add(Gtk.VBox(spacing=6)) view = SongList(library, update=True) view.info.connect("changed", self.__set_time) self.songlist = view sw = Gtk.ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(view) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.browser = browser = Kind(library, False) if browser.reordered: view.enable_drop() elif browser.dropped: view.enable_drop(False) if browser.accelerators: self.add_accel_group(browser.accelerators) self.__container = browser.pack(sw) self.get_child().pack_start(self.__container, True, True, 0) self.__statusbar = Gtk.Label() self.__statusbar.set_text(_("No time information")) self.__statusbar.set_alignment(1.0, 0.5) self.__statusbar.set_ellipsize(Pango.EllipsizeMode.START) self.get_child().pack_end(self.__statusbar, False, True, 0) browser.connect('songs-selected', self.__browser_cb) browser.finalize(False) view.connect('popup-menu', self.__menu, library) view.connect('drag-data-received', self.__drag_data_recv) view.connect('row-activated', self.__enqueue) if browser.headers is not None: view.connect('columns-changed', self.__cols_changed, browser) self.__cols_changed(view, browser) sw.show_all() for c in self.get_child().get_children(): c.show() self.get_child().show() self.__set_pane_size()
def __apply(self, button, buttons): result = self.__get_current_columns(buttons) SongList.set_all_column_headers(result)
def main(): process_arguments() from quodlibet import const if isrunning() and not const.DEBUG: print_(_("Quod Libet is already running.")) control('focus') import quodlibet quodlibet._init_signal() import quodlibet.player from quodlibet import app from quodlibet import config from quodlibet import browsers from quodlibet import const from quodlibet import util config.init(const.CONFIG) library = quodlibet.init(library=const.LIBRARY, icon="quodlibet", name="Quod Libet", title=const.PROCESS_TITLE_QL) app.library = library from quodlibet.player import PlayerError 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 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 = config.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) 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.manager import cover_plugins cover_plugins.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.qltk import mmkeys_ as mmkeys from quodlibet.qltk.remote import FSInterface, FIFOControl from quodlibet.qltk.tracker import SongTracker try: from quodlibet.qltk.dbus_ import DBusHandler except ImportError: DBusHandler = lambda player, library: None mmkeys.init(window, player) fsiface = FSInterface(player) quodlibet.quit_add(1, fsiface.destroy) fifoctrl = FIFOControl(app) quodlibet.quit_add(1, fifoctrl.destroy) DBusHandler(player, library) SongTracker(library.librarian, player, window.playlist) from quodlibet.qltk import session session.init("quodlibet") quodlibet.enable_periodic_save(save_library=True) if play: player.paused = False # restore browser windows from quodlibet.qltk.browser import LibraryBrowser from gi.repository import GLib GLib.idle_add(LibraryBrowser.restore, library, priority=GLib.PRIORITY_HIGH) quodlibet.main(window) print_d("Shutting down player device %r." % player.version_info) player.destroy() quodlibet.library.save(force=True) config.save(const.CONFIG) print_d("Finished shutdown.")
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 __init__(self, Kind, library): super(LibraryBrowser, self).__init__(dialog=False) self.set_default_size(600, 400) self.enable_window_tracking("browser_" + Kind.__name__) self.set_border_width(6) self.set_title(Kind.name + " - Quod Libet") self.add(gtk.VBox(spacing=6)) view = SongList(library, update=True) self.add_accel_group(view.accelerators) self.songlist = view sw = gtk.ScrolledWindow() sw.set_shadow_type(gtk.SHADOW_IN) sw.add(view) sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) self.browser = browser = Kind(library, False) if browser.reordered: view.enable_drop() elif browser.dropped: view.enable_drop(False) if browser.accelerators: self.add_accel_group(browser.accelerators) self.__container = browser.pack(sw) self.child.pack_start(self.__container) self.__statusbar = gtk.Label() self.__statusbar.set_text(_("No time information")) self.__statusbar.set_alignment(1.0, 0.5) self.__statusbar.set_ellipsize(pango.ELLIPSIZE_START) self.child.pack_end(self.__statusbar, expand=False) browser.connect('songs-selected', self.__browser_cb) browser.finalize(False) view.connect('popup-menu', self.__menu, library) view.connect('drag-data-received', self.__drag_data_recv) view.connect('row-activated', self.__enqueue) view.get_selection().connect('changed', self.__set_time) if browser.headers is not None: view.connect('columns-changed', self.__cols_changed, browser) self.__cols_changed(view, browser) sw.show_all() for c in self.child.get_children(): c.show() self.child.show() self.show() self.__set_pane_size()