1# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna 2# 2012,2013 Christoph Reiter 3# 2010-2017 Nick Boultbee 4# 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation; either version 2 of the License, or 8# (at your option) any later version. 9 10import sys 11import os 12 13from senf import environ, argv as sys_argv 14 15from quodlibet import _ 16from quodlibet.cli import process_arguments, exit_ 17from quodlibet.util.dprint import print_d, print_, print_exc 18 19 20def main(argv=None): 21 if argv is None: 22 argv = sys_argv 23 24 import quodlibet 25 26 config_file = os.path.join(quodlibet.get_user_dir(), "config") 27 quodlibet.init_cli(config_file=config_file) 28 29 try: 30 # we want basic commands not to import gtk (doubles process time) 31 assert "gi.repository.Gtk" not in sys.modules 32 sys.modules["gi.repository.Gtk"] = None 33 startup_actions, cmds_todo = process_arguments(argv) 34 finally: 35 sys.modules.pop("gi.repository.Gtk", None) 36 37 quodlibet.init() 38 39 from quodlibet import app 40 from quodlibet.qltk import add_signal_watch 41 add_signal_watch(app.quit) 42 43 import quodlibet.player 44 import quodlibet.library 45 from quodlibet import config 46 from quodlibet import browsers 47 from quodlibet import util 48 49 app.name = "Quod Libet" 50 app.description = _("Music player and music library manager") 51 app.id = "io.github.quodlibet.QuodLibet" 52 app.process_name = "quodlibet" 53 quodlibet.set_application_info(app) 54 55 library_path = os.path.join(quodlibet.get_user_dir(), "songs") 56 57 print_d("Initializing main library (%s)" % ( 58 quodlibet.util.path.unexpand(library_path))) 59 60 library = quodlibet.library.init(library_path) 61 app.library = library 62 63 # this assumes that nullbe will always succeed 64 from quodlibet.player import PlayerError 65 wanted_backend = environ.get( 66 "QUODLIBET_BACKEND", config.get("player", "backend")) 67 68 try: 69 player = quodlibet.player.init_player(wanted_backend, app.librarian) 70 except PlayerError: 71 print_exc() 72 player = quodlibet.player.init_player("nullbe", app.librarian) 73 74 app.player = player 75 76 environ["PULSE_PROP_media.role"] = "music" 77 environ["PULSE_PROP_application.icon_name"] = app.icon_name 78 79 browsers.init() 80 81 from quodlibet.qltk.songlist import SongList, get_columns 82 83 headers = get_columns() 84 SongList.set_all_column_headers(headers) 85 86 for opt in config.options("header_maps"): 87 val = config.get("header_maps", opt) 88 util.tags.add(opt, val) 89 90 in_all = ("~filename ~uri ~#lastplayed ~#rating ~#playcount ~#skipcount " 91 "~#added ~#bitrate ~current ~#laststarted ~basename " 92 "~dirname").split() 93 for Kind in browsers.browsers: 94 if Kind.headers is not None: 95 Kind.headers.extend(in_all) 96 Kind.init(library) 97 98 pm = quodlibet.init_plugins("no-plugins" in startup_actions) 99 100 if hasattr(player, "init_plugins"): 101 player.init_plugins() 102 103 from quodlibet.qltk import unity 104 unity.init("io.github.quodlibet.QuodLibet.desktop", player) 105 106 from quodlibet.qltk.songsmenu import SongsMenu 107 SongsMenu.init_plugins() 108 109 from quodlibet.util.cover import CoverManager 110 app.cover_manager = CoverManager() 111 app.cover_manager.init_plugins() 112 113 from quodlibet.plugins.playlist import PLAYLIST_HANDLER 114 PLAYLIST_HANDLER.init_plugins() 115 116 from quodlibet.plugins.query import QUERY_HANDLER 117 QUERY_HANDLER.init_plugins() 118 119 from gi.repository import GLib 120 121 from quodlibet.commands import registry as cmd_registry, CommandError 122 123 def exec_commands(*args): 124 for cmd in cmds_todo: 125 try: 126 resp = cmd_registry.run(app, *cmd) 127 except CommandError: 128 pass 129 else: 130 if resp is not None: 131 print_(resp, end="", flush=True) 132 133 from quodlibet.qltk.quodlibetwindow import QuodLibetWindow, PlayerOptions 134 # Call exec_commands after the window is restored, but make sure 135 # it's after the mainloop has started so everything is set up. 136 137 app.window = window = QuodLibetWindow( 138 library, player, 139 restore_cb=lambda: 140 GLib.idle_add(exec_commands, priority=GLib.PRIORITY_HIGH)) 141 142 app.player_options = PlayerOptions(window) 143 144 from quodlibet.qltk.window import Window 145 146 from quodlibet.plugins.events import EventPluginHandler 147 from quodlibet.plugins.gui import UserInterfacePluginHandler 148 pm.register_handler(EventPluginHandler(library.librarian, player, 149 app.window.songlist)) 150 pm.register_handler(UserInterfacePluginHandler()) 151 152 from quodlibet.mmkeys import MMKeysHandler 153 from quodlibet.remote import Remote, RemoteError 154 from quodlibet.qltk.tracker import SongTracker, FSInterface 155 try: 156 from quodlibet.qltk.dbus_ import DBusHandler 157 except ImportError: 158 DBusHandler = lambda player, library: None 159 160 mmkeys_handler = MMKeysHandler(app) 161 mmkeys_handler.start() 162 163 current_path = os.path.join(quodlibet.get_user_dir(), "current") 164 fsiface = FSInterface(current_path, player) 165 remote = Remote(app, cmd_registry) 166 try: 167 remote.start() 168 except RemoteError: 169 exit_(1, True) 170 171 DBusHandler(player, library) 172 tracker = SongTracker(library.librarian, player, window.playlist) 173 174 from quodlibet import session 175 session_client = session.init(app) 176 177 quodlibet.enable_periodic_save(save_library=True) 178 179 if ("start-playing" in startup_actions or 180 (config.getboolean("player", "restore_playing", False) and 181 config.getboolean("player", "is_playing", False))): 182 player.paused = False 183 184 if "start-hidden" in startup_actions: 185 Window.prevent_inital_show(True) 186 187 # restore browser windows 188 from quodlibet.qltk.browser import LibraryBrowser 189 GLib.idle_add(LibraryBrowser.restore, library, player, 190 priority=GLib.PRIORITY_HIGH) 191 192 def before_quit(): 193 print_d("Saving active browser state") 194 try: 195 app.browser.save() 196 except NotImplementedError: 197 pass 198 199 print_d("Shutting down player device %r." % player.version_info) 200 player.destroy() 201 202 quodlibet.run(window, before_quit=before_quit) 203 204 app.player_options.destroy() 205 quodlibet.finish_first_session("quodlibet") 206 mmkeys_handler.quit() 207 remote.stop() 208 fsiface.destroy() 209 210 tracker.destroy() 211 quodlibet.library.save() 212 213 config.save() 214 215 session_client.close() 216 217 print_d("Finished shutdown.") 218