Ejemplo n.º 1
0
    def __request(self, line, raw=False, want_reply=True):
        """
        Send a request to the server, if connected, and return its response
        """
        line = line.strip()

        if not (self.is_connected or line.split()[0] == 'login'):
            print_d("Can't do '%s' - not connected" % line.split()[0], self)
            return None

        if self._debug:
            print_(">>>> \"%s\"" % line)
        try:
            self.telnet.write(line + "\n")
            if not want_reply:
                return None
            raw_response = self.telnet.read_until("\n").strip()
        except socket.error as e:
            print_w("Couldn't communicate with squeezebox (%s)" % e)
            self.failures += 1
            if self.failures >= self._MAX_FAILURES:
                print_w("Too many Squeezebox failures. Disconnecting")
                self.is_connected = False
            return None
        response = raw_response if raw else urllib.unquote(raw_response)
        if self._debug:
            print_("<<<< \"%s\"" % (response,))
        return response[len(line) - 1:] if line.endswith("?")\
            else response[len(line) + 1:]
Ejemplo n.º 2
0
    def plugin_on_song_started(self, song):
        """Called when a song is started. Loads the lyrics.

        If there are lyrics associated with `song`, load them into the
        lyrics viewer. Otherwise, hides the lyrics viewer.
        """
        lyrics = None
        if song is not None:
            print_d("Looking for lyrics for %s" % song("~filename"))
            lyrics = song("~lyrics")
            if lyrics:
                self.textbuffer.set_text(lyrics)
                self.adjustment.set_value(0)    # Scroll to the top.
                self.textview.show()
            else:
                title = _("No lyrics found for\n %s") % song("~basename")
                self._set_italicised(title)

            def edit(widget):
                print_d("Launching lyrics editor for %s" % song("~filename"))
                assert isinstance(song, SongWrapper)
                information = Information(app.librarian, [song._song])
                information.get_child()._switch_to_lyrics()
                information.show()

            if self._sig:
                self._edit_button.disconnect(self._sig)
            self._sig = self._edit_button.connect('clicked', edit)
Ejemplo n.º 3
0
    def get_players(self):
        """ Returns (and caches) a list of the Squeezebox players available"""
        if self.players:
            return self.players
        pairs = self.__request("players 0 99", True).split(" ")

        def demunge(string):
            s = urllib.unquote(string)
            cpos = s.index(":")
            return (s[0:cpos], s[cpos + 1:])

        # Do a meaningful URL-unescaping and tuplification for all values
        pairs = map(demunge, pairs)

        # First element is always count
        count = int(pairs.pop(0)[1])
        self.players = []
        for pair in pairs:
            if pair[0] == "playerindex":
                playerindex = int(pair[1])
                self.players.append(SqueezeboxPlayerSettings())
            else:
                # Don't worry playerindex is always the first entry...
                self.players[playerindex][pair[0]] = pair[1]
        if self._debug:
            print_d("Found %d player(s): %s" %
                    (len(self.players), self.players))
        assert (count == len(self.players))
        return self.players
Ejemplo n.º 4
0
 def _load(self, item):
     """Load a item. Return (changed, removed)."""
     # Subclases should override this if they want to check
     # item validity; see FileLibrary.
     print_d("Loading %r." % item.key, self)
     self.dirty = True
     self._contents[item.key] = item
Ejemplo n.º 5
0
 def plugin_songs(self, songs):
     # Check this is a launch, not a configure
     if self.chosen_site:
         url_pat = self.get_url_pattern(self.chosen_site)
         pat = Pattern(url_pat)
         urls = set()
         for song in songs:
             # Generate a sanitised AudioFile; allow through most tags
             subs = AudioFile()
             for k in (USER_TAGS + MACHINE_TAGS):
                 vals = song.comma(k)
                 if vals:
                     try:
                         subs[k] = quote_plus(unicode(vals).encode('utf-8'))
                     # Dodgy unicode problems
                     except KeyError:
                         print_d("Problem with %s tag values: %r"
                                 % (k, vals))
             url = str(pat.format(subs))
             if not url:
                 print_w("Couldn't build URL using \"%s\"."
                         "Check your pattern?" % url_pat)
                 return
             # Grr, set.add() should return boolean...
             if url not in urls:
                 urls.add(url)
                 website(url)
Ejemplo n.º 6
0
    def __build_model(klass, library, model):
        print_d("Updating tag model for whole library")
        all_tags = klass.__tags
        model.clear()

        tags = set()
        songs = list(library)
        for count, song in enumerate(songs):
            for tag in song.keys():
                if not (tag.startswith("~#") or tag in MACHINE_TAGS):
                    tags.add(tag)

            if count % 500 == 0 or count + 1 == len(songs):
                tags -= all_tags
                for tag in tags:
                    model.append([tag])
                all_tags.update(tags)
                tags.clear()
                yield True

        tags.update(["~dirname", "~basename", "~people", "~format"])
        for tag in ["track", "disc", "playcount", "skipcount", "lastplayed",
                    "mtime", "added", "rating", "length"]:
            tags.add("#(" + tag)
        for tag in ["date", "bpm"]:
            if tag in all_tags:
                tags.add("#(" + tag)

        tags -= all_tags
        for tag in tags:
            model.append([tag])
        all_tags.update(tags)

        print_d("Done updating tag model for whole library")
Ejemplo n.º 7
0
    def load(self, filename, skip=False):
        """Load a library from a file, containing a picked list.

        Loading does not cause added, changed, or removed signals.
        """
        self.filename = filename
        print_d("Loading contents of %r." % filename, self)
        try:
            if os.path.exists(filename):
                # pickle makes 1000 read syscalls for 6000 songs
                # read the file into memory so that there are less
                # context switches. saves 40% here..
                fileobj = file(filename, "rb")
                try: items = pickle.loads(fileobj.read())
                except (pickle.PickleError, EnvironmentError,
                        ImportError, EOFError):
                    util.print_exc()
                    try: shutil.copy(filename, filename + ".not-valid")
                    except EnvironmentError:
                        util.print_exc()
                    items = []
                fileobj.close()
            else: return
        except EnvironmentError:
            return

        if skip:
            for item in filter(skip, items):
                self._contents[item.key] = item
        else:
            map(self._load, items)
        print_d("Done loading contents of %r." % filename, self)
Ejemplo n.º 8
0
 def __quit(self, widget=None, response=None):
     if response == Gtk.ResponseType.OK or \
             response == Gtk.ResponseType.CLOSE:
         print_d("Exiting plugin on user request...")
     self.finished = True
     self.destroy()
     return
Ejemplo n.º 9
0
def __create_playlist(name, source_dir, files, library):
    playlist = FileBackedPlaylist.new(PLAYLISTS, name, library=library)
    print_d("Created playlist %s" % playlist)
    songs = []
    win = WaitLoadWindow(
        None, len(files),
        _("Importing playlist.\n\n%(current)d/%(total)d songs added."))
    win.show()
    for i, filename in enumerate(files):
        if not uri_is_valid(filename):
            # Plain filename.
            songs.append(_af_for(filename, library, source_dir))
        else:
            try:
                filename = uri2fsn(filename)
            except ValueError:
                # Who knows! Hand it off to GStreamer.
                songs.append(formats.remote.RemoteFile(filename))
            else:
                # URI-encoded local filename.
                songs.append(_af_for(filename, library, source_dir))
        if win.step():
            break
    win.destroy()
    playlist.extend(list(filter(None, songs)))
    return playlist
Ejemplo n.º 10
0
 def _changed(self, items):
     # Called by the changed method and Librarians.
     if not items:
         return
     print_d("Changing %d items." % len(items), self)
     self.dirty = True
     self.emit('changed', items)
Ejemplo n.º 11
0
    def close(self):
        if self._client is None:
            return

        print_d("Disconnecting from XSMP")
        self._client.close()
        self._client = None
Ejemplo n.º 12
0
    def plugin_songs(self, songs):
        model = DuplicatesTreeModel()
        self.__cfg_cache = {}

        # Index all songs by our custom key
        # TODO: make this cache-friendly
        print_d("Calculating duplicates for %d song(s)..." % len(songs))
        groups = {}
        for song in songs:
            key = self.get_key(song)
            if key and key in groups:
                print_d("Found duplicate based on '%s'" % key)
                groups[key].add(song._song)
            elif key:
                groups[key] = {song._song}

        for song in app.library:
            key = self.get_key(song)
            if key in groups:
                groups[key].add(song)

        # Now display the grouped duplicates
        for (key, children) in groups.items():
            if len(children) < self.MIN_GROUP_SIZE:
                continue
            # The parent (group) label
            model.add_group(key, children)

        dialog = DuplicateDialog(model)
        dialog.show()
        # Mainly for testing...
        return dialog
Ejemplo n.º 13
0
    def enabled(self):
        if not self.running:
            wm = WatchManager()
            self.event_handler = LibraryEvent(app.library)

            # Choose event types to watch for
            # FIXME: watch for IN_CREATE or for some reason folder copies
            # are missed,  --nickb
            FLAGS = ['IN_DELETE', 'IN_CLOSE_WRITE',# 'IN_MODIFY',
                     'IN_MOVED_FROM', 'IN_MOVED_TO', 'IN_CREATE']
            mask = reduce(lambda x, s: x | EventsCodes.ALL_FLAGS[s], FLAGS, 0)

            if self.USE_THREADS:
                print_d("Using threaded notifier")
                self.notifier = ThreadedNotifier(wm, self.event_handler)
                # Daemonize to ensure thread dies on exit
                self.notifier.daemon = True
                self.notifier.start()
            else:
                self.notifier = Notifier(wm, self.event_handler, timeout=100)
                GLib.timeout_add(1000, self.unthreaded_callback)

            for path in get_scan_dirs():
                print_d('Watching directory %s for %s' % (path, FLAGS))
                # See https://github.com/seb-m/pyinotify/wiki/
                # Frequently-Asked-Questions
                wm.add_watch(path, mask, rec=True, auto_add=True)

            self.running = True
Ejemplo n.º 14
0
 def next(self, playlist, iter):
     next = self.wrapped.next(playlist, iter)
     if next:
         return next
     self.wrapped.reset(playlist)
     print_d("Restarting songlist")
     return playlist.get_iter_first()
Ejemplo n.º 15
0
    def _check_feed(self):
        """Validate stream a bit - failing fast where possible.

           Constructs an equivalent(ish) HEAD request,
           without re-writing feedparser completely.
           (it never times out if reading from a stream - see #2257)"""
        req = feedparser._build_urllib2_request(
            self.uri, feedparser.USER_AGENT, None, None, None, None, {})
        req.method = "HEAD"
        opener = build_opener(feedparser._FeedURLHandler())
        try:
            result = opener.open(req)
            ct_hdr = result.headers.get('Content-Type', "Unknown type")
            content_type = ct_hdr.split(';')[0]
            try:
                status = result.status
            except AttributeError:
                print_w("Missing status code for feed %s" % self.uri)
            else:
                print_d("Pre-check: %s returned %s with content type '%s'" %
                        (self.uri, status, content_type))
                if content_type not in feedparser.ACCEPT_HEADER:
                    print_w("Unusable content: %s. Perhaps %s is not a feed?" %
                            (content_type, self.uri))
                    return False
                # No real need to check HTTP Status - errors are very unlikely
                # to be a usable content type, and we should try to parse
        finally:
            opener.close()
        return True
Ejemplo n.º 16
0
 def go_to(self, song, explicit=False):
     self.__iter = None
     if isinstance(song, Gtk.TreeIter):
         self.__iter = song
         self.sourced = True
     elif not self.find_row(song):
         print_d("Failed to find song")
     return self.__iter
Ejemplo n.º 17
0
 def _get_saved_searches(self):
     filename = self.PATTERNS_FILE + ".saved"
     self._url_pats = StandaloneEditor.load_values(filename)
     # Failing all else...
     if not len(self._url_pats):
         print_d("No saved searches found in %s. Using defaults." %
                 filename, context=self)
         self._url_pats = self.DEFAULT_URL_PATS
Ejemplo n.º 18
0
 def show_files_cb(menu_item):
     print_d("Trying to show files...")
     if not show_songs(songs):
         msg = ErrorMessage(self.plugin_window,
                      _("Unable to show files"),
                      _("Error showing files, "
                        "or no program available to show them."))
         msg.run()
Ejemplo n.º 19
0
 def __init__(self, string, star=None, clock=time.time):
     super(SoundcloudQuery, self).__init__(string, star)
     self._clock = clock
     try:
         self.terms = self._extract_terms(self._match)
     except self.error as e:
         print_d("Couldn't use query: %s" % e)
         self.type = QueryType.INVALID
         self.terms = {}
Ejemplo n.º 20
0
 def plugin_enable(self, plugin):
     self.__plugins[plugin.cls] = pl_obj = plugin.get_instance()
     sidebar = pl_obj.create_sidebar()
     app.window.hide_side_book()
     if sidebar:
         print_d("Enabling sidebar for %s" % plugin.cls)
         self.__sidebars[plugin] = app.window.add_sidebar(
             sidebar, name=plugin.name)
         sidebar.show_all()
Ejemplo n.º 21
0
 def _save_images(self, data, img):
     ext = 'jpg' if self.config.re_encode else img.extension
     paths = self._filenames(self.config.save_pattern, ext, full_path=True)
     print_d("Saving %s to %s" % (data, paths))
     first_path = paths.pop()
     img.save_image(first_path)
     # Copying faster than potentially resizing
     for path in paths:
         shutil.copy(first_path, path)
Ejemplo n.º 22
0
 def plugin_enable(self, plugin):
     self.__plugins[plugin.cls] = pl_obj = plugin.get_instance()
     sidebar = pl_obj.create_sidebar()
     app.window.hide_side_book()
     if sidebar:
         print_d("Enabling sidebar for %s" % plugin.cls)
         self.__sidebars[plugin] = app.window.add_sidebar(
             sidebar, name=plugin.name)
         sidebar.show_all()
Ejemplo n.º 23
0
 def add_to_existing_group(self, key, song):
     """Tries to add a song to an existing group. Returns None if not able
     """
     for parent in self:
         if key == parent[0]:
             print_d("Found group", self)
             return self.append(parent.iter, self.__make_row(song))
         # TODO: update group
     return None
Ejemplo n.º 24
0
 def remaining(self, playlist):
     """Gets a map of all song indices to their song from the `playlist`
     that haven't yet been played"""
     all_indices = set(range(len(playlist)))
     played = set(self._played)
     print_d("Played %d of %d song(s)" % (len(self._played), len(playlist)))
     remaining = list(all_indices.difference(played))
     all_songs = playlist.get()
     return {i: all_songs[i] for i in remaining}
Ejemplo n.º 25
0
 def __init__(self, string, star=None, clock=time.time):
     super(SoundcloudQuery, self).__init__(string, star)
     self._clock = clock
     try:
         self.terms = self._extract_terms(self._match)
     except self.error as e:
         print_d("Couldn't use query: %s" % e)
         self.type = QueryType.INVALID
         self.terms = {}
Ejemplo n.º 26
0
 def __update_song(klass, library, songs, model):
     print_d("Updating tag model for %d songs" % len(songs))
     tags = klass.__tags
     for song in songs:
         for tag in song.keys():
             if not (tag.startswith("~#") or tag in MACHINE_TAGS or tag in tags):
                 klass.__tags.add(tag)
                 model.append([tag])
     print_d("Done updating tag model for %d songs" % len(songs))
Ejemplo n.º 27
0
 def go_to(self, song, explicit=False):
     #print_d("Duplicates: told to go to %r" % song, context=self)
     self.__iter = None
     if isinstance(song, Gtk.TreeIter):
         self.__iter = song
         self.sourced = True
     elif not self.find_row(song):
         print_d("Failed to find song", context=self)
     return self.__iter
Ejemplo n.º 28
0
 def disabled(self):
     if not self._pid:
         return
     print_d("Shutting down %s" % self.PLUGIN_NAME)
     try:
         os.kill(self._pid, signal.SIGTERM)
         os.kill(self._pid, signal.SIGKILL)
     except Exception as e:
         print_w("Couldn't shut down cleanly (%s)" % e)
Ejemplo n.º 29
0
 def write_to_song(tag, pattern, value):
     if value is None or value == "":
         return
     existing = song(tag, None)
     if existing and not self.overwrite_existing:
         print_d("Not overwriting existing tag %s (=%s) for %s" %
                 (tag, existing, self.song("~filename")))
         return
     song[tag] = pattern % value
Ejemplo n.º 30
0
 def mask(self, point):
     print_d(f"Masking {point!r}", self._name)
     removed = {}
     for item in self.values():
         if item.mountpoint == point:
             removed[item.key] = item
     if removed:
         self.remove(removed.values())
         self._masked.setdefault(point, {}).update(removed)
Ejemplo n.º 31
0
 def show_files_cb(menu_item):
     print_d("Trying to show files...")
     if not show_songs(songs):
         parent = get_menu_item_top_parent(menu_item)
         msg = ErrorMessage(parent,
                      _("Unable to show files"),
                      _("Error showing files, "
                        "or no program available to show them."))
         msg.run()
Ejemplo n.º 32
0
 def disabled(self):
     if not self._pid:
         return
     print_d("Shutting down %s" % self.PLUGIN_NAME)
     try:
         os.kill(self._pid, signal.SIGTERM)
         os.kill(self._pid, signal.SIGKILL)
     except Exception as e:
         print_w("Couldn't shut down cleanly (%s)" % e)
Ejemplo n.º 33
0
 def __init__(self):
     print_d("Initialising")
     self._globals = {
         'random': random,
         'Random': random.Random,
         'time': time
     }
     self._reported = set()
     self._raw_body = None
Ejemplo n.º 34
0
    def unmonitor_dir(self, path: Path) -> None:
        """Disconnect and remove any monitor for a directory, if found"""

        monitor, handler_id = self._monitors.get(path, (None, None))
        if not monitor:
            print_d(f"Couldn't find path {path} in active monitors", self._name)
            return
        monitor.disconnect(handler_id)
        del self._monitors[path]
Ejemplo n.º 35
0
 def _get_saved_searches(self):
     filename = self.PATTERNS_FILE + ".saved"
     #print_d("Checking saved searches in %s..." % filename, context=self)
     self._url_pats = StandaloneEditor.load_values(filename)
     # Failing all else...
     if not len(self._url_pats):
         print_d("No saved searches found in %s. Using defaults." %
                 filename, context=self)
         self._url_pats = self.DEFAULT_URL_PATS
Ejemplo n.º 36
0
 def remaining(self, playlist):
     """Gets a map of all song indices to their song from the `playlist`
     that haven't yet been played"""
     all_indices = set(range(len(playlist)))
     played = set(self._played)
     print_d("Played %d of %d song(s)" % (len(self._played), len(playlist)))
     remaining = list(all_indices.difference(played))
     all_songs = playlist.get()
     return {i: all_songs[i] for i in remaining}
Ejemplo n.º 37
0
 def go_to(self, song, explicit=False):
     #print_d("Duplicates: told to go to %r" % song, context=self)
     self.__iter = None
     if isinstance(song, Gtk.TreeIter):
         self.__iter = song
         self.sourced = True
     elif not self.find_row(song):
         print_d("Failed to find song", context=self)
     return self.__iter
Ejemplo n.º 38
0
 def add_to_existing_group(self, key, song):
     """Tries to add a song to an existing group. Returns None if not able
     """
     for parent in self:
         if key == parent[0]:
             print_d("Found group", self)
             return self.append(parent.iter, self.__make_row(song))
         # TODO: update group
     return None
Ejemplo n.º 39
0
 def write_to_song(tag, pattern, value):
     if value is None or value == "":
         return
     existing = song(tag, None)
     if existing and not self.overwrite_existing:
         print_d("Not overwriting existing tag %s (=%s) for %s"
                 % (tag, existing, self.song("~filename")))
         return
     song[tag] = pattern % value
Ejemplo n.º 40
0
 def plugin_on_changed(self, songs):
     cur = app.player.info
     if cur:
         fn = cur("~filename")
         for s in songs:
             if s("~filename") == fn:
                 print_d("Active song changed, reloading lyrics")
                 self.plugin_on_song_started(SongWrapper(cur))
     else:
         self._set_italicised(_("No active song"))
Ejemplo n.º 41
0
 def __update_song(klass, library, songs, model):
     print_d("Updating tag model for %d songs" % len(songs))
     tags = klass.__tags
     for song in songs:
         for tag in song.keys():
             if not (tag.startswith("~#") or tag in MACHINE_TAGS
                     or tag in tags):
                 klass.__tags.add(tag)
                 model.append([tag])
     print_d("Done updating tag model for %d songs" % len(songs))
Ejemplo n.º 42
0
 def plugin_on_changed(self, songs):
     cur = app.player.info
     if cur:
         fn = cur("~filename")
         for s in songs:
             if s("~filename") == fn:
                 print_d("Active song changed, reloading lyrics")
                 self.plugin_on_song_started(SongWrapper(cur))
     else:
         self._set_italicised(_("No active song"))
Ejemplo n.º 43
0
 def _finished(p, successes, failures):
     msg = (f"<b>{successes}</b> " + _("successful") +
            f"\n<b>{failures}</b> " + _("failed"))
     print_d(msg.replace("\n", "; "))
     warning = Message(Gtk.MessageType.INFO,
                       app.window,
                       _("Downloads complete"),
                       msg,
                       escape_desc=False)
     warning.run()
Ejemplo n.º 44
0
    def __init__(self, conf):
        print_d("Creating Lyrics web view")
        super(LyricsWebView, self).__init__()
        self.conf = conf

        self._thread = LyricsWikiaSearchThread()
        self.connect("destroy", lambda *x: self._thread.stop())

        self.current_song = None
        self._reload_web_view()
Ejemplo n.º 45
0
    def __init__(self, conf):
        print_d("Creating Lyrics web view")
        super().__init__()
        self.conf = conf

        self._thread = LyricsWikiaSearchThread()
        self.connect("destroy", lambda *x: self._thread.stop())

        self.current_song = None
        self._reload_web_view()
Ejemplo n.º 46
0
 def _save_images(self, data: CoverData, img: Gtk.Image):
     paths = self._filenames(self.config.save_pattern,
                             img.extension,
                             full_path=True)
     first_path = paths.pop()
     print_d(f"Saving {data} to {first_path}")
     img.save_image(first_path)
     # Copying faster than potentially resizing
     for path in paths:
         shutil.copy(first_path, path)
Ejemplo n.º 47
0
 def destroy(self):
     for id_ in self._pids:
         self._player.disconnect(id_)
     for id_ in self._lids:
         print_d(f"Disconnecting signal {id_} from {self._library}")
         self._library.disconnect(id_)
     try:
         os.unlink(self.path)
     except EnvironmentError:
         pass
Ejemplo n.º 48
0
    def rebuild(self, paths, force=False, exclude=None, cofuncid=None):
        """Reload or remove songs if they have changed or been deleted.

        This generator rebuilds the library over the course of iteration.

        Any paths given will be scanned for new files, using the 'scan'
        method.

        Only items present in the library when the rebuild is started
        will be checked.

        If this function is copooled, set "cofuncid" to enable pause/stop
        buttons in the UI.
        """

        print_d(f"Rebuilding, force is {force}", self._name)

        task = Task(_("Library"), _("Checking mount points"))
        if cofuncid:
            task.copool(cofuncid)
        for i, (point, items) in task.list(enumerate(self._masked.items())):
            if ismount(point):
                self._contents.update(items)
                del self._masked[point]
                self.emit('added', list(items.values()))
                yield True

        task = Task(_("Library"), _("Scanning library"))
        if cofuncid:
            task.copool(cofuncid)
        changed, removed = set(), set()
        for i, (key, item) in task.list(enumerate(sorted(self.items()))):
            if key in self._contents and force or not item.valid():
                self.reload(item, changed, removed)
                # These numbers are pretty empirical. We should yield more
            # often than we emit signals; that way the main loop stays
            # interactive and doesn't get bogged down in updates.
            if len(changed) >= 200:
                self.emit('changed', changed)
                changed = set()
            if len(removed) >= 200:
                self.emit('removed', removed)
                removed = set()
            if len(changed) > 20 or i % 200 == 0:
                yield True
        print_d(f"Removing {len(removed)}, changing {len(changed)}).",
                self._name)
        if removed:
            self.emit('removed', removed)
        if changed:
            self.emit('changed', changed)

        for value in self.scan(paths, exclude, cofuncid):
            yield value
Ejemplo n.º 49
0
    def remove(self, items):
        """Remove items. This causes a 'removed' signal."""
        if not items:
            return

        print_d("Removing %d items." % len(items), self)
        for item in items:
            del(self._contents[item.key])

        self.dirty = True
        self.emit('removed', items)
Ejemplo n.º 50
0
    def __init__(self, library):
        self.librarian = None
        print_d("Initializing Album Library to watch %r" % library._name)

        super().__init__("AlbumLibrary for %s" % library._name)

        self._library = library
        self._asig = library.connect('added', self.__added)
        self._rsig = library.connect('removed', self.__removed)
        self._csig = library.connect('changed', self.__changed)
        self.__added(library, library.values(), signal=False)
Ejemplo n.º 51
0
 def save_image(self, fsn):
     fsn = path2fsn(fsn)
     if self.config.re_encode:
         ret = self._pixbuf.savev(fsn, 'jpeg', ['quality'],
                                  [str(JPEG_QUALITY)])
         if not ret:
             raise IOError("Couldn't save to %s" % fsn)
     else:
         print_d("Saving original image to %s" % fsn)
         with open(fsn, "wb") as f:
             f.write(self._original)
Ejemplo n.º 52
0
def link_many(elements: Iterable[Gst.Element]) -> None:
    """Links all elements together
    :raises OSError: if they can't all be linked"""
    last = None
    print_d(f"Attempting to link Gstreamer element(s): "
            f"{[type(e).__name__ for e in elements]}")
    for element in elements:
        if last:
            if not Gst.Element.link(last, element):
                raise OSError(f"Failed on element: {type(element).__name__}")
        last = element
Ejemplo n.º 53
0
 def _save_lyrics(self, song, text):
     # First, try writing to the tags.
     song["lyrics"] = text
     try:
         song.write()
     except AudioFileError as e:
         print_w("Couldn't write embedded lyrics (%s)" % e)
         self._save_to_file(song, text)
     else:
         print_d("Wrote embedded lyrics into %s" % song("~filename"))
         app.librarian.emit('changed', [song])
         self._delete_file(song.lyric_filename)
Ejemplo n.º 54
0
    def __init__(self, string: str, star: Optional[Iterable[str]] = None):
        """Parses the query string and returns a match object.

        :param string: The text to parse
        :param star: Tags to look in, if none are specified in the query.
                     Defaults to those specified in `STAR`.

        This parses the query language as well as some tagless shortcuts:
            "foo bar" ->  &(star1,star2=foo,star1,star2=bar)
            "!foo" -> !star1,star2=foo
            "&(foo, bar)" -> &(star1,star2=foo, star1,star2=bar)
            "&(foo, !bar)" -> &(star1,star2=foo, !star1,star2=bar)
            "|(foo, bar)" -> |(star1,star2=foo, star1,star2=bar)
            "!&(foo, bar)" -> !&(star1,star2=foo, star1,star2=bar)
            "!(foo, bar)" -> !star1,star2=(foo, bar)
            etc...
        """
        print_d(f"Creating query {string!r}")
        if star is None:
            star = self.STAR

        assert isinstance(string, str)

        self.star = list(star)
        self.string = string

        self.type = QueryType.VALID
        try:
            self._match = QueryParser(string, star=star).StartQuery()
            breakpoint()
            if not self._match.valid:
                self.type = QueryType.INVALID
            return
        except self.Error:
            pass

        if not set("#=").intersection(string):
            for c in config.get("browsers", "ignored_characters"):
                string = string.replace(c, "")
            parts = ["/%s/d" % re_escape(s) for s in string.split()]
            string = "&(" + ",".join(parts) + ")"
            self.string = string

            try:
                self.type = QueryType.TEXT
                self._match = QueryParser(string, star=star).StartQuery()
                return
            except self.Error:
                pass

        print_d("Query '%s' is invalid" % string)
        self.type = QueryType.INVALID
        self._match = False_()
Ejemplo n.º 55
0
 def save_image(self, fsn):
     fsn = path2fsn(fsn)
     if self.config.re_encode:
         quality = str(self.config.jpg_quality)
         print_d(f"Converting image to JPEG @ {quality}%")
         ret = self._pixbuf.savev(fsn, "jpeg", ["quality"], [quality])
         if not ret:
             raise IOError("Couldn't save to %s" % fsn)
     else:
         print_d("Saving original image to %s" % fsn)
         with open(fsn, "wb") as f:
             f.write(self._original)
Ejemplo n.º 56
0
 def _save_lyrics(self, song, text):
     # First, try writing to the tags.
     song["lyrics"] = text
     try:
         song.write()
     except AudioFileError as e:
         print_w("Couldn't write embedded lyrics (%s)" % e)
         self._save_to_file(song, text)
     else:
         print_d("Wrote embedded lyrics into %s" % song("~filename"))
         app.librarian.emit('changed', [song])
         self._delete_file(song.lyric_filename)
Ejemplo n.º 57
0
 def _delete_file(self, filename):
     try:
         os.unlink(filename)
         print_d("Removed lyrics file '%s'" % filename)
     except EnvironmentError:
         pass
     lyric_dir = os.path.dirname(filename)
     try:
         os.rmdir(lyric_dir)
         print_d("Removed lyrics directory '%s'" % lyric_dir)
     except EnvironmentError:
         pass
Ejemplo n.º 58
0
 def _save_to_file(self, song, text):
     lyricname = song.lyric_filename
     try:
         os.makedirs(os.path.dirname(lyricname), exist_ok=True)
     except EnvironmentError:
         errorhook()
     try:
         with open(lyricname, "w") as f:
             f.write(text)
         print_d("Saved lyrics to file (%s)" % lyricname)
     except EnvironmentError:
         errorhook()
Ejemplo n.º 59
0
 def _callback(self, message, json, data):
     if json is None:
         print_d(f"[HTTP {message.status_code}] Invalid / empty JSON. "
                 f"Body: {message.response_body.data!r} (request: {data})")
         return
     if 'errors' in json:
         raise ValueError("Got HTTP %d (%s)" %
                          (message.status_code, json['errors']))
     if 'error' in json:
         raise ValueError("Got HTTP %d (%s)" %
                          (message.status_code, json['error']))
     return wrapped(self, json, data)
Ejemplo n.º 60
0
 def get_next_album(self):
     next_album = None
     while not next_album:
         if not self._todo:
             print_d("No more albums to process")
             return None
         next_album = self._todo.pop(0)
         if not next_album.should_process:
             print_d("%s needs no processing" % next_album.title)
             self._done.append(next_album)
             self.__update_view_for(next_album)
             next_album = None
     return next_album