def fake_path(path=None, keep_utils=None, all_but=None): if all_but is not None: if isinstance(all_but, (list, set, tuple)): keep_utils = ALL_UTILS - set(all_but) else: keep_utils = ALL_UTILS - {all_but} keep_utils = keep_utils or [] created_utils = set() rm_path = False if keep_utils: if path is None: path = tempfile.mkdtemp(prefix="libblockdev-fake-path", dir="/tmp") rm_path = True for util in keep_utils: util_path = GLib.find_program_in_path(util) if util_path: os.symlink(util_path, os.path.join(path, util)) created_utils.add(util) old_path = os.environ.get("PATH", "") os.environ["PATH"] = path or "" try: yield finally: os.environ["PATH"] = old_path for util in created_utils: os.unlink(os.path.join(path, util)) if rm_path: os.rmdir(path)
def _on_button_press(self, widget, event): """ On button press, set album popularity @param widget as Gtk.EventBox @param event as Gdk.Event """ if Lp().scanner.is_locked(): return user_rating = self.__object.get_rate() != Type.NONE event_star = widget.get_children()[0] if event_star in self._stars: position = self._stars.index(event_star) else: position = -1 pop = position + 1 if pop == 0: if user_rating: self.__object.set_rate(Type.NONE) else: self.__object.set_popularity(0) elif event.button == 1: self.__object.set_rate(pop) else: self.__object.set_popularity(pop) if isinstance(self.__object, Track): Lp().player.emit('rate-changed') # Save to tags if needed if Lp().settings.get_value('save-to-tags') and\ GLib.find_program_in_path("kid3-cli") is not None and\ isinstance(self.__object, Track) and\ not self.__object.is_web: if pop == 0: value = 0 elif pop == 1: value = 1 elif pop == 2: value = 64 elif pop == 3: value = 128 elif pop == 4: value = 196 else: value = 255 path = GLib.filename_from_uri(self.__object.uri)[0] try: bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) proxy = Gio.DBusProxy.new_sync( bus, Gio.DBusProxyFlags.NONE, None, 'org.gnome.Lollypop.Portal', '/org/gnome/LollypopPortal', 'org.gnome.Lollypop.Portal', None) proxy.call_sync('SetPopularity', GLib.Variant( '(is)', (value, path)), Gio.DBusCallFlags.NO_AUTO_START, 500, None) except Exception as e: print("RatingWidget::_on_button_press():", e) return True
def __need_network_search(self): """ Return True if network search needed @return True """ return Lp().settings.get_value('network-search') and\ GLib.find_program_in_path("youtube-dl") is not None
def start_xorg(klass): '''start Xvfb server''' xorg = GLib.find_program_in_path ('Xvfb') display_num = 99 if os.path.isfile('/tmp/.X%d-lock' % display_num): sys.stderr.write('Cannot start X.org, an instance already exists\n') sys.exit(1) # Composite extension won't load unless at least 24bpp is set klass.xorg = subprocess.Popen([xorg, ':%d' % display_num, "-screen", "0", "1280x1024x24", "+extension", "GLX"], stderr=subprocess.PIPE) os.environ['DISPLAY'] = ':%d' % display_num # wait until the server is ready timeout = 50 while timeout > 0: time.sleep(0.1) timeout -= 1 if klass.xorg.poll(): # ended prematurely timeout = -1 break if subprocess.call(['xprop', '-root'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0: break if timeout <= 0: sys.stderr.write('Cannot start Xvfb.\n--------') sys.exit(1)
def __enable_network_search(self): """ True if shoud enable network search @return bool """ return GLib.find_program_in_path("youtube-dl") is not None and\ get_network_available()
def is_installed(package, command='false'): """Check if things are installed already.""" try: cache = apt.Cache() return package in cache and cache[package].is_installed except SystemError: return GLib.find_program_in_path(command) is not None
def validate_exec_line(self, string): try: success, parsed = GLib.shell_parse_argv(string) if GLib.find_program_in_path(parsed[0]) or ((not os.path.isdir(parsed[0])) and os.access(parsed[0], os.X_OK)): return True except: pass return False
def _get_ninja(self): global ninja if not ninja: if GLib.find_program_in_path('ninja-build'): ninja = 'ninja-build' # Fedora... else: ninja = 'ninja' return ninja
def check_logind_gnome_session(self): '''Check that gnome-session is built with logind support''' path = GLib.find_program_in_path ('gnome-session') assert(path) ldd = subprocess.Popen(['ldd', path], stdout=subprocess.PIPE) out = ldd.communicate()[0] if not 'libsystemd-login.so.0' in out: self.fail('gnome-session is not built with logind support')
def exec_line_is_valid(self, exec_text): try: success, parsed = GLib.shell_parse_argv(exec_text) # Make sure program (first part of the command) is in the path command = parsed[0] return (GLib.find_program_in_path(command) is not None) except GLib.GError: return False
def findPackageForProgram(program): path = GLib.find_program_in_path(program); if path is not None: print("Program " + program + " was find in path:" + path) packageName = Installer.findPackageByPath(path); if packageName is not None: print("Program " + program + " was find in package:" + packageName) return packageName return ""
def findPackageForProgram(self, program): path = GLib.find_program_in_path(program); if path is not None: print("Program " + program + " was find in path:" + path) self.installer.register_collection("package") packageName = self.installer.find_package_by_path(path); if packageName is not None: print("Program " + program + " was find in package:" + packageName) return packageName return ""
def check(self): self.start_pulse() success = True for program in self.binfiles: if not GLib.find_program_in_path(program): success = False break GObject.idle_add(self.on_check_complete, success) return False
def do_startup(self): """ Init application """ Gtk.Application.do_startup(self) Notify.init("Lollypop") # Check locale, we want unicode! (code, encoding) = getlocale() if encoding is None or encoding != "UTF-8": builder = Gtk.Builder() builder.add_from_resource('/org/gnome/Lollypop/Unicode.ui') self.window = builder.get_object('unicode') self.window.set_application(self) self.window.show() elif not self.window: self.init() menu = self.__setup_app_menu() # If GNOME/Unity, add appmenu if is_gnome() or is_unity(): self.set_app_menu(menu) self.window = Window() # If not GNOME/Unity add menu to toolbar if not is_gnome() and not is_unity(): self.window.setup_menu(menu) self.window.connect('delete-event', self.__hide_on_delete) self.window.init_list_one() self.window.show() self.player.restore_state() # We add to mainloop as we want to run # after player::restore_state() signals GLib.idle_add(self.window.toolbar.set_mark) # Will not start sooner # Ubuntu > 16.04 if Gtk.get_minor_version() > 18: from lollypop.inhibitor import Inhibitor # Ubuntu <= 16.04, Debian Jessie, ElementaryOS else: from lollypop.inhibitor_legacy import Inhibitor self.inhibitor = Inhibitor() self.charts = None if self.settings.get_value('show-charts'): if GLib.find_program_in_path("youtube-dl") is not None: from lollypop.charts import Charts self.charts = Charts() if get_network_available(): self.charts.update() else: self.settings.set_value('network-search', GLib.Variant('b', False))
def update(self): """ Update database """ if not Gio.NetworkMonitor.get_default().get_network_available(): return # Update adblock_js repo git = GLib.find_program_in_path("git") if git is None: Logger.info(_("For stronger ad blocking, install git command")) else: if GLib.file_test(ADBLOCK_JS, GLib.FileTest.IS_DIR): argv = [git, "-C", ADBLOCK_JS, "pull", "https://gitlab.gnome.org/gnumdk/eolie-adblock.git"] else: argv = [git, "clone", "https://gitlab.gnome.org/gnumdk/eolie-adblock.git", ADBLOCK_JS] (pid, a1, a2, a3) = GLib.spawn_async( argv, flags=GLib.SpawnFlags.STDOUT_TO_DEV_NULL) GLib.spawn_close_pid(pid) # DB version is last successful sync mtime try: version = load(open(EOLIE_DATA_PATH + "/adblock.bin", "rb")) except: version = 0 self.__cancellable.reset() if self.__adblock_mtime - version > self.__UPDATE: # Update host rules uris = list(self.__URIS) locales = GLib.get_language_names() user_locale = locales[0].split("_")[0] try: uris += self.__CSS_URIS +\ [self.__CSS_LOCALIZED_URIS[user_locale]] except: uris += self.__CSS_URIS uri = uris.pop(0) self.__task_helper.load_uri_content(uri, self.__cancellable, self.__on_load_uri_content, uris)
def __init__(self): """ Init Popover """ Gtk.Popover.__init__(self) self.set_position(Gtk.PositionType.BOTTOM) self.connect('map', self.__on_map) self.connect('unmap', self.__on_unmap) self.__timeout = None self.__current_search = '' self.__nsearch = None self.__lsearch = None self.__history = [] builder = Gtk.Builder() builder.add_from_resource('/org/gnome/Lollypop/SearchPopover.ui') self.__new_btn = builder.get_object('new_btn') self.__entry = builder.get_object('entry') self.__view = Gtk.ListBox() self.__view.connect("button-press-event", self.__on_button_press) self.__view.connect("row-activated", self.__on_row_activated) self.__view.set_selection_mode(Gtk.SelectionMode.NONE) self.__view.set_activate_on_single_click(True) self.__view.show() self.__spinner = builder.get_object('spinner') self.__header_stack = builder.get_object('stack') self.__switch = builder.get_object('search-switch') if GLib.find_program_in_path("youtube-dl") is None: self.__switch.set_tooltip_text(_("You need to install youtube-dl")) else: self.__switch.set_state(Lp().settings.get_value('network-search')) self.__scrolled = builder.get_object('scrolled') self.__scrolled.add(self.__view) # Connect here because we don't want previous switch.set_state() # to emit a signal on init builder.connect_signals(self) self.__stack = Gtk.Stack() self.__stack.set_transition_duration(250) self.__stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE) self.__stack.show() self.__stack.add_named(builder.get_object('widget'), "search") self.add(self.__stack)
def find_program(program): program = program.strip() if len(program) == 0: return None params = list(GLib.shell_parse_argv(program)[1]) executable = params[0] if os.path.exists(executable): return executable path = GLib.find_program_in_path(executable) if path is not None: return path return None
def get_youtube_dl(): """ Get youtube-dl path and env @return (str, []) """ if App().settings.get_value("recent-youtube-dl"): python_path = GLib.get_user_data_dir() + "/lollypop/python" path = "%s/bin/youtube-dl" % python_path env = ["PYTHONPATH=%s" % python_path] f = Gio.File.new_for_path(path) if f.query_exists(): return (path, env) if GLib.find_program_in_path("youtube-dl"): return ("youtube-dl", []) else: return (None, [])
def check_exec(self, program): program = program.strip() if len(program) == 0: return False params = list(GLib.shell_parse_argv(program)[1]) executable = params[0] if os.path.exists(executable): return True path = GLib.find_program_in_path(executable) if path is not None: return True return False
def _on_button_press(self, widget, event): """ On button press, set album popularity @param widget as Gtk.EventBox @param event as Gdk.Event """ if Lp().scanner.is_locked(): return event_star = widget.get_children()[0] if event_star in self._stars: position = self._stars.index(event_star) else: position = -1 pop = position + 1 self._object.set_popularity(pop) # Save to tags if needed if Lp().settings.get_value('save-to-tags') and\ GLib.find_program_in_path("kid3-cli") is not None and\ isinstance(self._object, Track) and\ not self._object.is_web: if pop == 0: value = 0 elif pop == 1: value = 1 elif pop == 2: value = 64 elif pop == 3: value = 128 elif pop == 4: value = 196 else: value = 255 path = GLib.filename_from_uri(self._object.uri)[0] try: bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) proxy = Gio.DBusProxy.new_sync(bus, Gio.DBusProxyFlags.NONE, None, 'org.gnome.Lollypop.Portal', '/org/gnome/LollypopPortal', 'org.gnome.Lollypop.Portal', None) proxy.call_sync('SetPopularity', GLib.Variant('(is)', (value, path)), Gio.DBusCallFlags.NO_AUTO_START, 500, None) except Exception as e: print("RatingWidget::_on_button_press():", e) return True
def start_xorg(klass): '''start X.org server with dummy driver''' conf = os.path.join(os.path.dirname(__file__), 'xorg-dummy.conf') # some distros like Fedora install Xorg as suid root; copy it into our # workdir to drop the suid bit and run it as user if GLib.file_test('/usr/libexec/Xorg.bin', GLib.FileTest.IS_EXECUTABLE): xorg = '/usr/libexec/Xorg.bin' else: out = GLib.find_program_in_path ('Xorg') if not out: sys.stderr.write('ERROR: Xorg not installed\n') sys.exit(1) xorg = os.path.join(klass.workdir, 'Xorg') shutil.copy(out, xorg) display_num = 99 if os.path.isfile('/tmp/.X%d-lock' % display_num): sys.stderr.write('Cannot start X.org, an instance already exists\n') sys.exit(1) # You can rename the log file to *.log if you want to see it on test # case failures log = os.path.join(klass.workdir, 'Xorg.out') klass.xorg = subprocess.Popen([xorg, '-config', conf, '-logfile', log, ':%d' % display_num], stderr=subprocess.PIPE) os.environ['DISPLAY'] = ':%d' % display_num # wait until the server is ready timeout = 50 while timeout > 0: time.sleep(0.1) timeout -= 1 if klass.xorg.poll(): # ended prematurely timeout = -1 break if subprocess.call(['xprop', '-root'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0: break if timeout <= 0: with open(log) as f: sys.stderr.write('Cannot start X.org with dummy driver. Log:\n%s\n--------' % f.read()) sys.exit(1)
def save_album_artwork(self, data, album_id): """ Save data for album id @param data as bytes @param album id as int """ try: arturi = None save_to_tags = Lp().settings.get_value('save-to-tags') and\ GLib.find_program_in_path("kid3-cli") is not None album = Album(album_id) uri_count = Lp().albums.get_uri_count(album.uri) filename = self.get_album_cache_name(album) + ".jpg" if save_to_tags: t = Thread(target=self.__save_artwork_tags, args=(data, album)) t.daemon = True t.start() store_path = self._STORE_PATH + "/" + filename if album.uri == "" or is_readonly(album.uri): arturi = GLib.filename_to_uri(store_path) # Many albums with same path, suffix with artist_album name elif uri_count > 1: arturi = album.uri + "/" + filename favorite_uri = album.uri + "/" + self.__favorite favorite = Gio.File.new_for_uri(favorite_uri) if favorite.query_exists(): favorite.trash() else: arturi = album.uri + "/" + self.__favorite f = Gio.File.new_for_uri(arturi) # Update cover file if exists even if we have written to tags if not save_to_tags or f.query_exists(): stream = Gio.MemoryInputStream.new_from_data(data, None) pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale( stream, ArtSize.MONSTER, ArtSize.MONSTER, True, None) pixbuf.savev(store_path, "jpeg", ["quality"], ["90"]) dst = Gio.File.new_for_uri(arturi) src = Gio.File.new_for_path(store_path) src.move(dst, Gio.FileCopyFlags.OVERWRITE, None, None) del pixbuf self.clean_album_cache(album) GLib.idle_add(self.album_artwork_update, album.id) except Exception as e: print("Art::save_album_artwork(): %s" % e)
def do_startup(self): """ Init application """ Gtk.Application.do_startup(self) Notify.init("Lollypop") if not self.window: self.init() menu = self.__setup_app_menu() # If GNOME/Unity, add appmenu if is_gnome() or is_unity(): self.set_app_menu(menu) self.window = Window() # If not GNOME/Unity add menu to toolbar if not is_gnome() and not is_unity(): self.window.setup_menu(menu) self.window.connect('delete-event', self.__hide_on_delete) self.window.init_list_one() self.window.show() self.player.restore_state() # We add to mainloop as we want to run # after player::restore_state() signals GLib.idle_add(self.window.toolbar.set_mark) # Will not start sooner # Ubuntu > 16.04 if Gtk.get_minor_version() > 18: from lollypop.inhibitor import Inhibitor # Ubuntu <= 16.04, Debian Jessie, ElementaryOS else: from lollypop.inhibitor_legacy import Inhibitor self.inhibitor = Inhibitor() self.charts = None if self.settings.get_value('show-charts'): if GLib.find_program_in_path("youtube-dl") is not None: from lollypop.charts import Charts self.charts = Charts() if get_network_available(): self.charts.update() else: self.settings.set_value('network-search', GLib.Variant('b', False)) t = Thread(target=self.__preload_portal) t.daemon = True t.start()
def fake_path(path=None, keep_utils=None): keep_utils = keep_utils or [] created_utils = set() if path: for util in keep_utils: util_path = GLib.find_program_in_path(util) if util_path: os.symlink(util_path, os.path.join(path, util)) created_utils.add(util) old_path = os.environ.get("PATH", "") os.environ["PATH"] = path or "" try: yield finally: os.environ["PATH"] = old_path for util in created_utils: os.unlink(os.path.join(path, util))
def __init__(self, object_id, is_album, is_youtube): """ Init edit menu @param object id as int @param is album as int @param is youtube as bool """ BaseMenu.__init__(self, object_id, [], [], is_album) if is_youtube: self.__set_remove_action() elif is_album: favorite = Lp().settings.get_value('tag-editor').get_string() for editor in [favorite] + self.__TAG_EDITORS: if GLib.find_program_in_path(editor) is not None: self.__tag_editor = editor self.__set_edit_actions() break
def check_logind_gnome_session(self): '''Check that gnome-session is built with logind support''' path = GLib.find_program_in_path ('gnome-session') assert(path) (success, data) = GLib.file_get_contents (path) lines = data.split('\n') new_path = None for line in lines: items = line.split() if items and items[0] == 'exec': new_path = items[1] if not new_path: self.fail("could not get gnome-session's real path from %s" % path) path = new_path ldd = subprocess.Popen(['ldd', path], stdout=subprocess.PIPE) out = ldd.communicate()[0] if not 'libsystemd.so.0' in out: self.fail('gnome-session is not built with logind support')
def __on_map(self, widget): """ Init signals and grab focus @param widget as Gtk.Widget """ App().enable_special_shortcuts(False) if GLib.find_program_in_path("youtube-dl") is None or\ not get_network_available("SPOTIFY") or\ not get_network_available("YOUTUBE"): self.__bottom_buttons.hide() else: self.__bottom_buttons.show() if self.__new_album_signal_id is None: self.__new_album_signal_id = App().spotify.connect( "new-album", self.__on_new_spotify_album) if self.__search_finished_signal_id is None: self.__search_finished_signal_id = App().spotify.connect( "search-finished", self.__on_search_finished) GLib.idle_add(self.__entry.grab_focus)
def check_logind_gnome_session(self): '''Check that gnome-session is built with logind support''' path = GLib.find_program_in_path('gnome-session') assert (path) (success, data) = GLib.file_get_contents(path) lines = data.split('\n') new_path = None for line in lines: items = line.split() if items and items[0] == 'exec': new_path = items[1] if not new_path: self.fail("could not get gnome-session's real path from %s" % path) path = new_path ldd = subprocess.Popen(['ldd', path], stdout=subprocess.PIPE) out = ldd.communicate()[0] if not 'libsystemd.so.0' in out: self.fail('gnome-session is not built with logind support')
def update(self): """ Update database """ if not Gio.NetworkMonitor.get_default().get_network_available(): return # Update adblock_js repo git = GLib.find_program_in_path("git") if git is None: print(_("For stronger ad blocking, install git command")) else: if GLib.file_test(ADBLOCK_JS, GLib.FileTest.IS_DIR): argv = [git, "-C", ADBLOCK_JS, "pull"] else: argv = [ git, "clone", "https://gitlab.gnome.org/gnumdk/eolie-adblock.git", ADBLOCK_JS ] (pid, a1, a2, a3) = GLib.spawn_async(argv, flags=GLib.SpawnFlags.STDOUT_TO_DEV_NULL) GLib.spawn_close_pid(pid) # Check entries in DB, do we need to update? mtime = 0 with SqlCursor(self) as sql: result = sql.execute("SELECT mtime FROM adblock\ ORDER BY mtime LIMIT 1") v = result.fetchone() if v is not None: mtime = v[0] self.__cancellable.reset() if self.__adblock_mtime - mtime > self.__UPDATE: # Update host rules uris = list(self.__URIS) uri = uris.pop(0) self.__task_helper.load_uri_content(uri, self.__cancellable, self.__on_load_uri_content, uris) else: self.__on_save_rules()
def __on_edit_button_clicked(self, button): """ Run tags editor @param button as Gtk.Button """ path = GLib.filename_from_uri(self.__object.uri)[0] if GLib.find_program_in_path("flatpak-spawn") is not None: argv = ["flatpak-spawn", "--host", App().art.tag_editor, path] else: argv = [App().art.tag_editor, path] try: (pid, stdin, stdout, stderr) = GLib.spawn_async(argv, flags=GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.STDOUT_TO_DEV_NULL, standard_input=False, standard_output=False, standard_error=False) except Exception as e: Logger.error("ContextWidget::__on_edit_button_clicked(): %s" % e) self.hide()
def __edit_tag(self, action, variant): """ Run tag editor @param Gio.SimpleAction @param GLib.Variant """ path = GLib.filename_from_uri(self._object.uri)[0] if GLib.find_program_in_path("flatpak-spawn") is not None: argv = ["flatpak-spawn", "--host", App().art.tag_editor, path] else: argv = [App().art.tag_editor, path] try: (pid, stdin, stdout, stderr) = GLib.spawn_async( argv, flags=GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.STDOUT_TO_DEV_NULL, standard_input=False, standard_output=False, standard_error=False ) except Exception as e: Logger.error("MenuPopover::__edit_tag(): %s" % e)
def __init__(self, object): """ Init edit menu @param object as Album/Track """ # Ignore genre_ids/artist_ids if isinstance(object, Album): obj = Album(object.id) else: obj = Track(object.id) BaseMenu.__init__(self, obj) if self._object.is_web: self.__set_remove_action() else: favorite = Lp().settings.get_value('tag-editor').get_string() for editor in [favorite] + TAG_EDITORS: if GLib.find_program_in_path(editor) is not None: self.__tag_editor = editor self.__set_edit_actions() break
def _on_button_press(self, widget, event): """ On button press, set album popularity @param widget as Gtk.EventBox @param event as Gdk.Event """ if Lp().scanner.is_locked(): return event_star = widget.get_children()[0] if event_star in self._stars: position = self._stars.index(event_star) else: position = -1 pop = position + 1 self._object.set_popularity(pop) # Save to tags if needed if Lp().settings.get_value('save-to-tags') and\ GLib.find_program_in_path("kid3-cli") is not None and\ isinstance(self._object, Track) and\ not self._object.is_web: if pop == 0: value = 0 elif pop == 1: value = 1 elif pop == 2: value = 64 elif pop == 3: value = 128 elif pop == 4: value = 196 else: value = 255 path = GLib.filename_from_uri(self._object.uri)[0] argv = [ "kid3-cli", "-c", "select all", "-c", "set pop: %s" % value, path, None ] GLib.spawn_sync(None, argv, None, GLib.SpawnFlags.SEARCH_PATH, None) return True
def update(self): """ Update database """ if not Gio.NetworkMonitor.get_default().get_network_available(): return # Update adblock_js repo git = GLib.find_program_in_path("git") if git is None: print(_("For stronger ad blocking, install git command")) else: d = Gio.File.new_for_path(ADBLOCK_JS) if d.query_exists(): argv = [git, "-C", ADBLOCK_JS, "pull"] else: argv = [ git, "clone", "https://github.com/gnumdk/eolie-adblock.git", ADBLOCK_JS ] (pid, a1, a2, a3) = GLib.spawn_async(argv, flags=GLib.SpawnFlags.STDOUT_TO_DEV_NULL) GLib.spawn_close_pid(pid) # Get in db mtime # Only update if filters older than one week mtime = 0 with SqlCursor(self) as sql: result = sql.execute("SELECT mtime FROM adblock LIMIT 1") v = result.fetchone() if v is not None: mtime = v[0] self.__mtime = int(time()) if self.__mtime - mtime < 604800: return # Update adblock db thread = Thread(target=self.__update) thread.daemon = True thread.start()
def __set_popularity(self, pop): """ Set popularity as kid3 is installed @param pop as int """ try: if App().art.kid3_available: if pop == 0: value = 0 elif pop == 1: value = 1 elif pop == 2: value = 64 elif pop == 3: value = 128 elif pop == 4: value = 196 else: value = 255 path = GLib.filename_from_uri(self.__object.uri)[0] if GLib.find_program_in_path("flatpak-spawn") is not None: argv = [ "flatpak-spawn", "--host", "kid3-cli", "-c", "set POPM %s" % value, path ] else: argv = ["kid3-cli", "-c", "set POPM %s" % value, path] if App().scanner.inotify is not None: App().scanner.inotify.disable() (pid, stdin, stdout, stderr) = GLib.spawn_async( argv, flags=GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.STDOUT_TO_DEV_NULL) # Force mtime update to not run a collection update App().tracks.set_mtime(self.__object.id, int(time()) + 10) except Exception as e: Logger.error("RatingWidget::__on_can_set_popularity(): %s" % e)
def do_startup(self): """ Init application """ Gtk.Application.do_startup(self) Notify.init("Lollypop") if not self.window: self.init() menu = self.__setup_app_menu() # If GNOME/Unity, add appmenu if is_gnome() or is_unity(): self.set_app_menu(menu) self.window = Window() # If not GNOME/Unity add menu to toolbar if not is_gnome() and not is_unity(): self.window.setup_menu(menu) self.window.connect('delete-event', self.__hide_on_delete) self.window.init_list_one() self.window.show() self.player.restore_state() # We add to mainloop as we want to run # after player::restore_state() signals GLib.idle_add(self.window.toolbar.set_mark) self.charts = None if self.settings.get_value('show-charts'): if GLib.find_program_in_path("youtube-dl") is not None: from lollypop.charts import Charts self.charts = Charts() if get_network_available(): self.charts.start() else: self.settings.set_value('network-search', GLib.Variant('b', False)) t = Thread(target=self.__preload_portal) t.daemon = True t.start()
def do_startup(self): """ Init application """ Gtk.Application.do_startup(self) Notify.init("Lollypop") if not self.window: self.init() menu = self.__setup_app_menu() # If GNOME/Unity, add appmenu if is_gnome() or is_unity(): self.set_app_menu(menu) self.window = Window() # If not GNOME/Unity add menu to toolbar if not is_gnome() and not is_unity(): self.window.setup_menu(menu) self.window.connect("delete-event", self.__hide_on_delete) self.window.init_list_one() self.window.show() self.player.restore_state() # We add to mainloop as we want to run # after player::restore_state() signals GLib.idle_add(self.window.toolbar.set_mark) self.charts = None if self.settings.get_value("show-charts"): if GLib.find_program_in_path("youtube-dl") is not None: from lollypop.charts import Charts self.charts = Charts() if get_network_available(): self.charts.start() else: self.settings.set_value("network-search", GLib.Variant("b", False)) t = Thread(target=self.__preload_portal) t.daemon = True t.start()
def start_xorg(klass): '''start Xvfb server''' xorg = GLib.find_program_in_path('Xvfb') display_num = 99 if os.path.isfile('/tmp/.X%d-lock' % display_num): sys.stderr.write( 'Cannot start X.org, an instance already exists\n') sys.exit(1) # Composite extension won't load unless at least 24bpp is set klass.xorg = subprocess.Popen([ xorg, ':%d' % display_num, "-screen", "0", "1280x1024x24", "+extension", "GLX" ], stderr=subprocess.PIPE) os.environ['DISPLAY'] = ':%d' % display_num # wait until the server is ready timeout = 50 while timeout > 0: time.sleep(0.1) timeout -= 1 if klass.xorg.poll(): # ended prematurely timeout = -1 break if subprocess.call(['xprop', '-root'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0: break if timeout <= 0: sys.stderr.write('Cannot start Xvfb.\n--------') sys.exit(1)
def __set_outputs(self, combo): """ Set outputs in combo @parma combo as Gtk.ComboxBoxText """ renderer = combo.get_cells()[0] renderer.set_property("ellipsize", Pango.EllipsizeMode.END) renderer.set_property("max-width-chars", 60) if GLib.find_program_in_path("flatpak-spawn") is not None: argv = ["flatpak-spawn", "--host", "pacmd", "list-sinks"] else: argv = ["pacmd", "list-sinks"] try: (pid, stdin, stdout, stderr) = GLib.spawn_async(argv, flags=GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, standard_input=False, standard_output=True, standard_error=False) GLib.child_watch_add(GLib.PRIORITY_DEFAULT_IDLE, pid, self.__on_pacmd_result, stdout, combo) except Exception as e: Logger.error("SettingsDialog::__set_outputs(): %s" % e)
def process (self): name = self.name.replace("pkexec ", "") name = name.split()[0] return GLib.find_program_in_path(name) is not None
def __init__(self): """ Init dialog """ self.__choosers = [] self.__cover_tid = None self.__mix_tid = None self.__popover = None cs_api_key = Lp().settings.get_value('cs-api-key').get_string() default_cs_api_key = Lp().settings.get_default_value( 'cs-api-key').get_string() if (not cs_api_key or cs_api_key == default_cs_api_key) and\ get_network_available() and\ Lp().notify is not None: Lp().notify.send( _("Google Web Services need a custom API key"), _("Lollypop needs this to search artwork and music.")) builder = Gtk.Builder() builder.add_from_resource('/org/gnome/Lollypop/SettingsDialog.ui') self.__progress = builder.get_object('progress') self.__infobar = builder.get_object('infobar') self.__reset_button = builder.get_object('reset_button') if Lp().lastfm is None or Lp().lastfm.is_goa: builder.get_object('lastfm_grid').hide() if Lp().scanner.is_locked(): builder.get_object('reset_button').set_sensitive(False) artists = Lp().artists.count() albums = Lp().albums.count() tracks = Lp().tracks.count() builder.get_object('artists').set_text( ngettext("%d artist", "%d artists", artists) % artists) builder.get_object('albums').set_text( ngettext("%d album", "%d albums", albums) % albums) builder.get_object('tracks').set_text( ngettext("%d track", "%d tracks", tracks) % tracks) self.__popover_content = builder.get_object('popover') duration = builder.get_object('duration') duration.set_range(1, 20) duration.set_value(Lp().settings.get_value('mix-duration').get_int32()) self.__settings_dialog = builder.get_object('settings_dialog') self.__settings_dialog.set_transient_for(Lp().window) if Lp().settings.get_value('disable-csd'): self.__settings_dialog.set_title(_("Preferences")) else: headerbar = builder.get_object('header_bar') headerbar.set_title(_("Preferences")) self.__settings_dialog.set_titlebar(headerbar) switch_scan = builder.get_object('switch_scan') switch_scan.set_state(Lp().settings.get_value('auto-update')) switch_view = builder.get_object('switch_dark') switch_view.set_state(Lp().settings.get_value('dark-ui')) switch_background = builder.get_object('switch_background') switch_background.set_state(Lp().settings.get_value('background-mode')) switch_state = builder.get_object('switch_state') switch_state.set_state(Lp().settings.get_value('save-state')) switch_mix = builder.get_object('switch_mix') switch_mix.set_state(Lp().settings.get_value('mix')) self.__helper = TouchHelper(switch_mix, None, None) self.__helper.set_long_func(self.__mix_long_func, switch_mix) self.__helper.set_short_func(self.__mix_short_func, switch_mix) switch_mix_party = builder.get_object('switch_mix_party') switch_mix_party.set_state(Lp().settings.get_value('party-mix')) switch_librefm = builder.get_object('switch_librefm') switch_librefm.set_state(Lp().settings.get_value('use-librefm')) switch_artwork_tags = builder.get_object('switch_artwork_tags') # Check portal for kid3-cli can_set_cover = False try: bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) proxy = Gio.DBusProxy.new_sync(bus, Gio.DBusProxyFlags.NONE, None, 'org.gnome.Lollypop.Portal', '/org/gnome/LollypopPortal', 'org.gnome.Lollypop.Portal', None) can_set_cover = proxy.call_sync('CanSetCover', None, Gio.DBusCallFlags.NO_AUTO_START, 500, None)[0] except Exception as e: print("You are missing lollypop-portal: " "https://github.com/gnumdk/lollypop-portal", e) if not can_set_cover: grid = builder.get_object('grid_behaviour') h = grid.child_get_property(switch_artwork_tags, 'height') w = grid.child_get_property(switch_artwork_tags, 'width') l = grid.child_get_property(switch_artwork_tags, 'left-attach') t = grid.child_get_property(switch_artwork_tags, 'top-attach') switch_artwork_tags.destroy() label = Gtk.Label.new(_("You need to install kid3-cli")) label.get_style_context().add_class('dim-label') label.set_property('halign', Gtk.Align.END) label.show() grid.attach(label, l, t, w, h) else: switch_artwork_tags.set_state( Lp().settings.get_value('save-to-tags')) if GLib.find_program_in_path("youtube-dl") is None: builder.get_object('charts_grid').hide() else: switch_charts = builder.get_object('switch_charts') switch_charts.set_state(Lp().settings.get_value('show-charts')) switch_genres = builder.get_object('switch_genres') switch_genres.set_state(Lp().settings.get_value('show-genres')) switch_compilations = builder.get_object('switch_compilations') switch_compilations.set_state( Lp().settings.get_value('show-compilations')) switch_artwork = builder.get_object('switch_artwork') switch_artwork.set_state(Lp().settings.get_value('artist-artwork')) switch_spotify = builder.get_object('switch_spotify') switch_spotify.set_state(Lp().settings.get_value('search-spotify')) switch_itunes = builder.get_object('switch_itunes') switch_itunes.set_state(Lp().settings.get_value('search-itunes')) if GLib.find_program_in_path("youtube-dl") is None: builder.get_object('yt-dl').show() combo_orderby = builder.get_object('combo_orderby') combo_orderby.set_active(Lp().settings.get_enum(('orderby'))) combo_preview = builder.get_object('combo_preview') scale_coversize = builder.get_object('scale_coversize') scale_coversize.set_range(150, 300) scale_coversize.set_value( Lp().settings.get_value('cover-size').get_int32()) self.__settings_dialog.connect('destroy', self.__edit_settings_close) builder.connect_signals(self) main_chooser_box = builder.get_object('main_chooser_box') self.__chooser_box = builder.get_object('chooser_box') self.__set_outputs(combo_preview) # # Music tab # dirs = [] for directory in Lp().settings.get_value('music-uris'): dirs.append(directory) # Main chooser self.__main_chooser = ChooserWidget() image = Gtk.Image.new_from_icon_name("list-add-symbolic", Gtk.IconSize.MENU) self.__main_chooser.set_icon(image) self.__main_chooser.set_action(self.__add_chooser) main_chooser_box.pack_start(self.__main_chooser, False, True, 0) if len(dirs) > 0: uri = dirs.pop(0) else: filename = GLib.get_user_special_dir( GLib.UserDirectory.DIRECTORY_MUSIC) if filename: uri = GLib.filename_to_uri(filename) else: uri = "" self.__main_chooser.set_dir(uri) # Others choosers for directory in dirs: self.__add_chooser(directory) # # Google tab # builder.get_object('cs-entry').set_text( Lp().settings.get_value('cs-api-key').get_string()) # # Last.fm tab # if Lp().lastfm is not None and Secret is not None: self.__test_img = builder.get_object('test_img') self.__login = builder.get_object('login') self.__password = builder.get_object('password') schema = Secret.Schema.new("org.gnome.Lollypop", Secret.SchemaFlags.NONE, SecretSchema) Secret.password_lookup(schema, SecretAttributes, None, self.__on_password_lookup) builder.get_object('lastfm_grid').set_sensitive(True) builder.get_object('lastfm_error').hide() self.__login.set_text( Lp().settings.get_value('lastfm-login').get_string())
def test_method(self): """GLib method call""" self.assertEqual(GLib.find_program_in_path("bash"), "/bin/bash")
def resync_validity(self, *args): name_text = self.builder.get_object('name-entry').get_text() exec_text = self.builder.get_object('exec-entry').get_text() valid = (name_text != "" and GLib.find_program_in_path(exec_text) is not None) self.builder.get_object('ok').set_sensitive(valid)
def session_is_cinnamon(): if "cinnamon" in GLib.getenv("DESKTOP_SESSION"): if GLib.find_program_in_path("cinnamon-session-quit"): return True return False
def __init__(self): """ Init dialog """ self.__choosers = [] self.__cover_tid = None self.__mix_tid = None self.__popover = None cs_api_key = Lp().settings.get_value('cs-api-key').get_string() default_cs_api_key = Lp().settings.get_default_value( 'cs-api-key').get_string() if (not cs_api_key or cs_api_key == default_cs_api_key) and\ get_network_available() and\ Lp().notify is not None: Lp().notify.send( _("Google Web Services need a custom API key"), _("Lollypop needs this to search artwork and music.")) builder = Gtk.Builder() builder.add_from_resource('/org/gnome/Lollypop/SettingsDialog.ui') self.__progress = builder.get_object('progress') self.__infobar = builder.get_object('infobar') self.__reset_button = builder.get_object('reset_button') if Lp().lastfm is None or Lp().lastfm.is_goa: builder.get_object('lastfm_grid').hide() if Lp().scanner.is_locked(): builder.get_object('reset_button').set_sensitive(False) artists = Lp().artists.count() albums = Lp().albums.count() tracks = Lp().tracks.count() builder.get_object('artists').set_text( ngettext("%d artist", "%d artists", artists) % artists) builder.get_object('albums').set_text( ngettext("%d album", "%d albums", albums) % albums) builder.get_object('tracks').set_text( ngettext("%d track", "%d tracks", tracks) % tracks) self.__popover_content = builder.get_object('popover') duration = builder.get_object('duration') duration.set_range(1, 20) duration.set_value(Lp().settings.get_value('mix-duration').get_int32()) self.__settings_dialog = builder.get_object('settings_dialog') self.__settings_dialog.set_transient_for(Lp().window) if Lp().settings.get_value('disable-csd'): self.__settings_dialog.set_title(_("Preferences")) else: headerbar = builder.get_object('header_bar') headerbar.set_title(_("Preferences")) self.__settings_dialog.set_titlebar(headerbar) switch_scan = builder.get_object('switch_scan') switch_scan.set_state(Lp().settings.get_value('auto-update')) switch_view = builder.get_object('switch_dark') if Lp().gtk_application_prefer_dark_theme: switch_view.set_sensitive(False) else: switch_view.set_state(Lp().settings.get_value('dark-ui')) switch_background = builder.get_object('switch_background') switch_background.set_state(Lp().settings.get_value('background-mode')) switch_state = builder.get_object('switch_state') switch_state.set_state(Lp().settings.get_value('save-state')) switch_mix = builder.get_object('switch_mix') switch_mix.set_state(Lp().settings.get_value('mix')) self.__helper = TouchHelper(switch_mix, None, None) self.__helper.set_long_func(self.__mix_long_func, switch_mix) self.__helper.set_short_func(self.__mix_short_func, switch_mix) switch_mix_party = builder.get_object('switch_mix_party') switch_mix_party.set_state(Lp().settings.get_value('party-mix')) switch_librefm = builder.get_object('switch_librefm') switch_librefm.set_state(Lp().settings.get_value('use-librefm')) switch_artwork_tags = builder.get_object('switch_artwork_tags') # Check portal for kid3-cli can_set_cover = False try: bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) proxy = Gio.DBusProxy.new_sync(bus, Gio.DBusProxyFlags.NONE, None, 'org.gnome.Lollypop.Portal', '/org/gnome/LollypopPortal', 'org.gnome.Lollypop.Portal', None) can_set_cover = proxy.call_sync('CanSetCover', None, Gio.DBusCallFlags.NO_AUTO_START, 500, None)[0] except Exception as e: print( "You are missing lollypop-portal: " "https://github.com/gnumdk/lollypop-portal", e) if not can_set_cover: grid = builder.get_object('grid_behaviour') h = grid.child_get_property(switch_artwork_tags, 'height') w = grid.child_get_property(switch_artwork_tags, 'width') l = grid.child_get_property(switch_artwork_tags, 'left-attach') t = grid.child_get_property(switch_artwork_tags, 'top-attach') switch_artwork_tags.destroy() label = Gtk.Label.new(_("You need to install kid3-cli")) label.get_style_context().add_class('dim-label') label.set_property('halign', Gtk.Align.END) label.show() grid.attach(label, l, t, w, h) else: switch_artwork_tags.set_state( Lp().settings.get_value('save-to-tags')) if GLib.find_program_in_path("youtube-dl") is None: builder.get_object('charts_grid').hide() else: switch_charts = builder.get_object('switch_charts') switch_charts.set_state(Lp().settings.get_value('show-charts')) switch_genres = builder.get_object('switch_genres') switch_genres.set_state(Lp().settings.get_value('show-genres')) switch_compilations = builder.get_object('switch_compilations') switch_compilations.set_state( Lp().settings.get_value('show-compilations')) switch_artwork = builder.get_object('switch_artwork') switch_artwork.set_state(Lp().settings.get_value('artist-artwork')) switch_spotify = builder.get_object('switch_spotify') switch_spotify.set_state(Lp().settings.get_value('search-spotify')) switch_itunes = builder.get_object('switch_itunes') switch_itunes.set_state(Lp().settings.get_value('search-itunes')) if GLib.find_program_in_path("youtube-dl") is None: builder.get_object('yt-dl').show() combo_orderby = builder.get_object('combo_orderby') combo_orderby.set_active(Lp().settings.get_enum(('orderby'))) combo_preview = builder.get_object('combo_preview') scale_coversize = builder.get_object('scale_coversize') scale_coversize.set_range(150, 300) scale_coversize.set_value( Lp().settings.get_value('cover-size').get_int32()) self.__settings_dialog.connect('destroy', self.__edit_settings_close) builder.connect_signals(self) main_chooser_box = builder.get_object('main_chooser_box') self.__chooser_box = builder.get_object('chooser_box') self.__set_outputs(combo_preview) # # Music tab # dirs = [] for directory in Lp().settings.get_value('music-uris'): dirs.append(directory) # Main chooser self.__main_chooser = ChooserWidget() image = Gtk.Image.new_from_icon_name("list-add-symbolic", Gtk.IconSize.MENU) self.__main_chooser.set_icon(image) self.__main_chooser.set_action(self.__add_chooser) main_chooser_box.pack_start(self.__main_chooser, False, True, 0) if len(dirs) > 0: uri = dirs.pop(0) else: filename = GLib.get_user_special_dir( GLib.UserDirectory.DIRECTORY_MUSIC) if filename: uri = GLib.filename_to_uri(filename) else: uri = "" self.__main_chooser.set_dir(uri) # Others choosers for directory in dirs: self.__add_chooser(directory) # # Google tab # builder.get_object('cs-entry').set_text( Lp().settings.get_value('cs-api-key').get_string()) # # Last.fm tab # if Lp().lastfm is not None and Secret is not None: self.__test_img = builder.get_object('test_img') self.__login = builder.get_object('login') self.__password = builder.get_object('password') schema = Secret.Schema.new("org.gnome.Lollypop", Secret.SchemaFlags.NONE, SecretSchema) Secret.password_lookup(schema, SecretAttributes, None, self.__on_password_lookup) builder.get_object('lastfm_grid').set_sensitive(True) builder.get_object('lastfm_error').hide() self.__login.set_text( Lp().settings.get_value('lastfm-login').get_string())
def __init__(self): if not GLib.find_program_in_path("7z"): raise Exception
def main(): sh_path = GLib.find_program_in_path('sh') if sh_path == "/bin/sh": return True return False
def test_find_program_in_path(self): bash_path = GLib.find_program_in_path('bash') self.assertTrue(bash_path.endswith('/bash')) self.assertTrue(os.path.exists(bash_path)) self.assertEqual(GLib.find_program_in_path('non existing'), None)
def get_command_runable(self): command = self.command_entry.get_text() return GLib.find_program_in_path(command)
def process(self): name = self.name.replace("pkexec ", "") name = name.split()[0] return GLib.find_program_in_path(name) is not None
def __init__(self): """ Init dialog """ self.__choosers = [] self.__cover_tid = None self.__mix_tid = None self.__popover = None builder = Gtk.Builder() builder.add_from_resource("/org/gnome/Lollypop/SettingsDialog.ui") self.__progress = builder.get_object("progress") self.__infobar = builder.get_object("infobar") self.__reset_button = builder.get_object("reset_button") if Lp().lastfm is None or Lp().lastfm.is_goa: builder.get_object("lastfm_grid").hide() if Lp().scanner.is_locked(): builder.get_object("reset_button").set_sensitive(False) artists = Lp().artists.count() albums = Lp().albums.count() tracks = Lp().tracks.count() builder.get_object("artists").set_text( ngettext("%d artist", "%d artists", artists) % artists) builder.get_object("albums").set_text( ngettext("%d album", "%d albums", albums) % albums) builder.get_object("tracks").set_text( ngettext("%d track", "%d tracks", tracks) % tracks) self.__popover_content = builder.get_object("popover") duration = builder.get_object("duration") duration.set_range(1, 20) duration.set_value(Lp().settings.get_value("mix-duration").get_int32()) self.__settings_dialog = builder.get_object("settings_dialog") self.__settings_dialog.set_transient_for(Lp().window) if Lp().settings.get_value("disable-csd"): self.__settings_dialog.set_title(_("Preferences")) else: headerbar = builder.get_object("header_bar") headerbar.set_title(_("Preferences")) self.__settings_dialog.set_titlebar(headerbar) switch_scan = builder.get_object("switch_scan") switch_scan.set_state(Lp().settings.get_value("auto-update")) switch_view = builder.get_object("switch_dark") if Lp().gtk_application_prefer_dark_theme: switch_view.set_sensitive(False) else: switch_view.set_state(Lp().settings.get_value("dark-ui")) switch_background = builder.get_object("switch_background") switch_background.set_state(Lp().settings.get_value("background-mode")) switch_state = builder.get_object("switch_state") switch_state.set_state(Lp().settings.get_value("save-state")) switch_mix = builder.get_object("switch_mix") switch_mix.set_state(Lp().settings.get_value("mix")) self._switch_song_notifications = builder.get_object( "switch_song_notifications", ) self._switch_song_notifications.set_state( not Lp().settings.get_value("disable-song-notifications"), ) self._switch_song_notifications.set_sensitive( not Lp().settings.get_value("disable-notifications"), ) Lp().settings.connect( "changed::disable-notifications", self._on_notifications_setting_changed, ) self.__helper = TouchHelper(switch_mix, None, None) self.__helper.set_long_func(self.__mix_long_func, switch_mix) self.__helper.set_short_func(self.__mix_short_func, switch_mix) switch_mix_party = builder.get_object("switch_mix_party") switch_mix_party.set_state(Lp().settings.get_value("party-mix")) switch_artwork_tags = builder.get_object("switch_artwork_tags") grid_behaviour = builder.get_object("grid_behaviour") # Check portal for kid3-cli dbus_helper = DBusHelper() dbus_helper.call("CanSetCover", None, self.__on_can_set_cover, (switch_artwork_tags, grid_behaviour)) if GLib.find_program_in_path("youtube-dl") is None or\ not Lp().settings.get_value("network-access"): builder.get_object("charts_grid").hide() else: switch_charts = builder.get_object("switch_charts") switch_charts.set_state(Lp().settings.get_value("show-charts")) switch_genres = builder.get_object("switch_genres") switch_genres.set_state(Lp().settings.get_value("show-genres")) switch_compilations = builder.get_object("switch_compilations") switch_compilations.set_state( Lp().settings.get_value("show-compilations")) switch_artwork = builder.get_object("switch_artwork") switch_artwork.set_state(Lp().settings.get_value("artist-artwork")) switch_spotify = builder.get_object("switch_spotify") switch_spotify.set_state(Lp().settings.get_value("search-spotify")) switch_itunes = builder.get_object("switch_itunes") switch_itunes.set_state(Lp().settings.get_value("search-itunes")) if GLib.find_program_in_path("youtube-dl") is None: builder.get_object("yt-dl").show() combo_orderby = builder.get_object("combo_orderby") combo_orderby.set_active(Lp().settings.get_enum(("orderby"))) combo_preview = builder.get_object("combo_preview") scale_coversize = builder.get_object("scale_coversize") scale_coversize.set_range(150, 300) scale_coversize.set_value( Lp().settings.get_value("cover-size").get_int32()) self.__settings_dialog.connect("destroy", self.__edit_settings_close) builder.connect_signals(self) main_chooser_box = builder.get_object("main_chooser_box") self.__chooser_box = builder.get_object("chooser_box") self.__set_outputs(combo_preview) # # Music tab # dirs = [] for directory in Lp().settings.get_value("music-uris"): dirs.append(directory) # Main chooser self.__main_chooser = ChooserWidget() image = Gtk.Image.new_from_icon_name("list-add-symbolic", Gtk.IconSize.MENU) self.__main_chooser.set_icon(image) self.__main_chooser.set_action(self.__add_chooser) main_chooser_box.pack_start(self.__main_chooser, False, True, 0) if len(dirs) > 0: uri = dirs.pop(0) else: filename = GLib.get_user_special_dir( GLib.UserDirectory.DIRECTORY_MUSIC) if filename: uri = GLib.filename_to_uri(filename) else: uri = "" self.__main_chooser.set_dir(uri) # Others choosers for directory in dirs: self.__add_chooser(directory) # # Google tab # key = Lp().settings.get_value("cs-api-key").get_string() or\ Lp().settings.get_default_value("cs-api-key").get_string() builder.get_object("cs-entry").set_text(key) from lollypop.helper_passwords import PasswordsHelper helper = PasswordsHelper() # # Last.fm tab # if Lp().lastfm is not None: self.__lastfm_test_image = builder.get_object("lastfm_test_image") self.__lastfm_login = builder.get_object("lastfm_login") self.__lastfm_password = builder.get_object("lastfm_password") helper.get("lastfm", self.__on_get_password) builder.get_object("lastfm_grid").set_sensitive(True) builder.get_object("lastfm_error_label").hide() # # Libre.fm tab # if Lp().librefm is not None: self.__librefm_test_image = builder.get_object( "librefm_test_image") self.__librefm_login = builder.get_object("librefm_login") self.__librefm_password = builder.get_object("librefm_password") helper.get("librefm", self.__on_get_password) builder.get_object("librefm_grid").set_sensitive(True) builder.get_object("librefm_error_label").hide()
def test_find_program_in_path(self): bash_path = GLib.find_program_in_path("bash") self.assertTrue(bash_path.endswith("/bash")) self.assertTrue(os.path.exists(bash_path)) self.assertEqual(GLib.find_program_in_path("non existing"), None)
class Display: PIBOOTCTL = GLib.find_program_in_path('pibootctl') MODE_ARG = 'video.firmware.mode' MEM_ARG = 'gpu.mem' CONFIG = '/boot/firmware/config.txt' PI_KMSMODE = '/usr/lib/budgie-desktop/arm/pi-kmsmode.sh' MODE = ['fkms', 'kms', 'legacy'] MEM = ['128', '256', '512'] def __init__(self, builder, device): self.displaygrid = builder.get_object("DisplayGrid") self.moderadiobuttons = [ builder.get_object("FkmsRadioButton"), builder.get_object("KmsRadioButton"), builder.get_object("LegacyRadioButton") ] self.memradiobuttons = [ builder.get_object("Mem128RadioButton"), builder.get_object("Mem256RadioButton"), builder.get_object("Mem512RadioButton") ] self.modebutton = builder.get_object("ModeButton") self.current_mode = '' self.membutton = builder.get_object("MemoryButton") self.current_mem = '' self.rebootlabel = builder.get_object("RebootLabel") self.rebootlabel.set_visible(False) self.app_statuslabel = builder.get_object("AppStatusLabel") tab = builder.get_object("DisplayTab") for button in self.moderadiobuttons: hint.add(button, self.app_statuslabel, hint.VIDEO_MODE) for button in self.memradiobuttons: hint.add(button, self.app_statuslabel, hint.GPU_MEMORY) hint.add(tab, self.app_statuslabel, hint.DISPLAY_TAB) hint.add(self.modebutton, self.app_statuslabel, hint.UPDATE_VIDEO) hint.add(self.membutton, self.app_statuslabel, hint.UPDATE_MEMORY) if device.pi_model is not None: if self.load_initial(): self.modebutton.connect("clicked", self.on_modebutton_clicked) self.memsignal = self.membutton.connect("clicked", self.on_membutton_clicked) if not self.safe_to_change_mode(): self.disable_mode_selection() else: #self.disable_controls() self.displaygrid.set_visible(False) def on_modebutton_clicked(self, *args): for i in range(len(self.moderadiobuttons)): if self.moderadiobuttons[i].get_active() and self.MODE[i] != self.current_mode: if self.run_pibootctl('set', self.MODE_ARG+'='+self.MODE[i]) != 'error': self.current_mode = self.MODE[i] self.rebootlabel.set_visible(True) def on_membutton_clicked(self, *args): for i in range(len(self.memradiobuttons)): if self.memradiobuttons[i].get_active() and self.MEM[i] != self.current_mem: if self.run_pibootctl('set', self.MEM_ARG+'='+self.MEM[i]) != 'error': self.current_mem = self.MEM[i] self.rebootlabel.set_visible(True) def disable_controls(self): for button in (self.moderadiobuttons + self.memradiobuttons): button.set_sensitive(False) hint.add(self.modebutton, self.app_statuslabel, hint.NO_PIBOOTCTL) hint.add(self.membutton, self.app_statuslabel, hint.NO_PIBOOTCTL) def load_initial(self): result = self.run_pibootctl('get', self.MODE_ARG, self.MEM_ARG, '--shell') # If pibootctl is missing or unsuccessful (i.e. run on a non-Pi device) if result == 'error': print("Unable to run pibootctl") self.disable_controls() return False else: mode, mem = result.replace('=','\n').splitlines()[1::2] for i in range(len(self.moderadiobuttons)): if mode == self.MODE[i]: self.moderadiobuttons[i].set_active(True) self.current_mode = self.MODE[i] for i in range(len(self.memradiobuttons)): if mem == self.MEM[i]: self.memradiobuttons[i].set_active(True) self.current_mem = self.MEM[i] return True def run_pibootctl(self, method, *params): if method == 'set': args = ['pkexec', self.PIBOOTCTL, method] # Fix for wrong overlay location - to be removed when resolved if len(params) >= 1 and "=kms" in params[0]: args = ['pkexec', self.PI_KMSMODE] # End fix else: args = [self.PIBOOTCTL, method] for item in params: args.append(item) try: output = subprocess.check_output(args, stderr=subprocess.STDOUT).decode("utf-8").strip('\'\n') except subprocess.CalledProcessError as e: output = e.output.decode("utf-8") return 'error' except FileNotFoundError: return 'error' return output def disable_mode_selection(self): # Disable mode buttons when pibootctl can't be safely used for widget in ([self.modebutton] + self.moderadiobuttons): widget.set_sensitive(False) widget.set_tooltip_text("Can't change mode from vc4-kms-v3d-pi4") def safe_to_change_mode(self): # Check if video mode is currently vc4-kms-v3d-pi4 safe = True try: with open(self.CONFIG) as file: content = file.readlines() except IOError: return True for line in content: if 'dtoverlay=vc4-kms-v3d-pi4' in line and line.strip()[0] != '#': safe = False return safe
def __init__(self, transient_for): self.builder = Gtk.Builder.new_from_file( os.path.join(config.pkgdatadir, "prefs-window.ui")) self.window = self.builder.get_object("prefs_window") self.content_box = self.builder.get_object("content_box") self.page_switcher = self.builder.get_object("page_switcher") self.window.set_title(title=_("Warpinator Preferences")) self.window.set_icon_name("preferences-system") self.window.set_transient_for(transient_for) size_group = Gtk.SizeGroup.new(Gtk.SizeGroupMode.HORIZONTAL) page_stack = SettingsStack() self.content_box.pack_start(page_stack, True, True, 0) self.page_switcher.set_stack(page_stack) # Settings page = SettingsPage() page_stack.add_titled(page, "general", _("General")) section = page.add_section(_("Desktop")) widget = GSettingsSwitch(_("Show an icon in the notification area"), PREFS_SCHEMA, TRAY_ICON_KEY) section.add_row(widget) widget = GSettingsSwitch(_("Start with main window open"), PREFS_SCHEMA, START_WITH_WINDOW_KEY) section.add_reveal_row(widget, PREFS_SCHEMA, TRAY_ICON_KEY) widget = GSettingsSwitch(_("Start automatically"), PREFS_SCHEMA, AUTOSTART_KEY) section.add_row(widget) section = page.add_section(_("File Transfers")) widget = GSettingsSwitch( _("Use compression when possible."), PREFS_SCHEMA, USE_COMPRESSION_KEY, tooltip= _("Warning: This may have a negative impact on performance on some faster networks." )) section.add_row(widget) widget = GSettingsFileChooser(_("Location for received files"), PREFS_SCHEMA, FOLDER_NAME_KEY, size_group=size_group, dir_select=True) section.add_row(widget) widget = GSettingsSwitch(_("Require approval before accepting files"), PREFS_SCHEMA, ASK_PERMISSION_KEY) section.add_row(widget) widget = GSettingsSwitch( _("Require approval when files would be overwritten"), PREFS_SCHEMA, NO_OVERWRITE_KEY) section.add_row(widget) widget = GSettingsSwitch( _("Display a notification when someone sends (or tries to send) you files" ), PREFS_SCHEMA, SHOW_NOTIFICATIONS_KEY) section.add_row(widget) page = SettingsPage() page_stack.add_titled(page, "network", _("Connection")) section = page.add_section(_("Identification")) entry_size_group = Gtk.SizeGroup.new(Gtk.SizeGroupMode.VERTICAL) button_size_group = Gtk.SizeGroup.new(Gtk.SizeGroupMode.BOTH) widget = GroupCodeEntry( _("Group Code"), tooltip= _("You cannot communicate with computers that do not use the same code." ), entry_size_group=entry_size_group, button_size_group=button_size_group) section.add_row(widget) section = page.add_section(_("Network")) options = [] options.append(("auto", _("Automatic"))) current_selection_exists = get_preferred_iface() == "auto" or False devices = networkmonitor.get_network_monitor().get_devices() for dev in devices: iface = dev.get_iface() if iface == get_preferred_iface(): current_selection_exists = True desc = dev.get_product() if (desc != None and desc != ""): orig_label = "%s - %s" % (iface, desc) if len(orig_label) > 50: label = orig_label[:47] + "..." else: label = orig_label options.append((iface, label)) else: options.append((iface, iface)) if not current_selection_exists: # translation: combobox item shown when a previosuly set interface can no longer be found - 'wlan0 - not found' options.append((get_preferred_iface(), _("%s - not found") % get_preferred_iface())) self.iface_combo = ComboBox(_("Network interface to use"), options, valtype=str) self.iface_combo.content_widget.set_active_iter( self.iface_combo.option_map[get_preferred_iface()]) self.iface_combo.label.set_line_wrap(False) section.add_row(self.iface_combo) self.main_port = PortSpinButton(_("Incoming port for transfers"), mini=1024, maxi=49151, step=1, page=10, size_group=size_group, entry_size_group=entry_size_group, button_size_group=button_size_group) section.add_row(self.main_port) self.auth_port = PortSpinButton(_("Incoming port for registration"), mini=1024, maxi=49151, step=1, page=10, size_group=size_group, entry_size_group=entry_size_group, button_size_group=button_size_group) section.add_row(self.auth_port) self.main_port.content_widget.set_value(get_port()) self.auth_port.content_widget.set_value(get_auth_port()) self.settings = Gio.Settings(schema_id=PREFS_SCHEMA) self.main_port.content_widget.connect("value-changed", self.net_values_changed) self.auth_port.content_widget.connect("value-changed", self.net_values_changed) self.iface_combo_id = self.iface_combo.content_widget.connect( "changed", self.net_values_changed) self.port_button = Button(_("Apply network changes"), self.apply_net_settings) self.port_button.content_widget.set_sensitive(False) self.port_button.content_widget.get_style_context().add_class( "suggested-action") section.add_row(self.port_button) widget = SettingsWidget() if config.include_firewall_mod and GLib.find_program_in_path("ufw"): button = Gtk.Button(label=_("Update firewall rules"), valign=Gtk.Align.CENTER) button.connect("clicked", self.open_port) widget.pack_end(button, False, False, 0) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) widget.pack_start(box, True, True, 0) # Pulling in a label with attributes was simpler than trying to add attributes # to a label here - the PangoAttribute python binding for font weight is missing. box.pack_start(self.builder.get_object("port_help_heading"), False, False, 0) label = Gtk.Label(wrap=True, xalign=0.0, label=_("""\ Any port numbers will work for the application, but using the same ports for all computers \ can make it simpler to add firewall exceptions if necessary.""")) box.pack_start(label, False, False, 0) section.add_row(widget) self.window.show_all()