Ejemplo n.º 1
0
class RainbowizerScript(QObject):
  PRIORITY = 1

  def __init__(self):
    QObject.__init__(self)

    # Generate colors
    self.colors = []
    for hue in xrange(0, 255, 30):
      self.colors.append(QColor.fromHsv(hue, 255, 255, 96))

    self.action = QAction("rainbowize_playlist", self)
    self.action.setText("Rainbowize!")
    self.action.setCheckable(True)
    self.action.connect("changed()", self.rainbowize)

    clementine.ui.AddAction('playlist_menu', self.action)

  def rainbowize(self):
    for playlist in clementine.playlists.GetAllPlaylists():
      if self.action.isChecked():
        for i, item in enumerate(playlist.GetAllItems()):
          item.SetBackgroundColor(self.PRIORITY, self.colors[i % len(self.colors)])

      else:
        # undo all rainbow colors
        for item in playlist.GetAllItems():
          item.RemoveBackgroundColor(self.PRIORITY)
class InvalidateDeleted(QObject):
    """
  TODO: actions which are defined here should be implemented here too instead of delegating
  the responsibility to Playlist Manager. Unfortunately, it cannot be done at this moment
  since using PlaylistItemPtrs in Python crashes Clementine.
  """

    def __init__(self):
        QObject.__init__(self)

        self.invalidate = QAction("invalidate_deleted", self)
        self.invalidate.setText("Grey out deleted songs")
        self.invalidate.connect("activated()", self.grey_out_activated)

        self.delete = QAction("remove_deleted", self)
        self.delete.setText("Remove deleted songs")
        self.delete.connect("activated()", self.delete_activated)

        clementine.ui.AddAction('playlist_menu', self.invalidate)
        clementine.ui.AddAction('playlist_menu', self.delete)

    def grey_out_activated(self):
        clementine.playlists.InvalidateDeletedSongs()

    def delete_activated(self):
        clementine.playlists.RemoveDeletedSongs()
Ejemplo n.º 3
0
class SetlistFmScript(QObject):

  def __init__(self):
    QObject.__init__(self)

    # maps QNetworkReply to artist of action which created it
    # every thread knows what artist it's looking for
    self.artist_map = {}

    self.task_id = None
    self.network = clementine.NetworkAccessManager(self)

    self.action = QAction("fill_with_setlist", self)
    self.action.setText("Load latest setlist")
    self.action.connect("activated()", self.load_setlist_activated)

    clementine.ui.AddAction('library_context_menu', self.action)

  def load_setlist_activated(self):
    # wait for the last call to finish
    if self.task_id is not None:
      return

    # find the first artist
    artist = ""
    for song in clementine.library_view.GetSelectedSongs():
      if len(str(song.artist())) > 0:
        artist = str(song.artist())
        break

    # ignore the call if there's no artist in selection
    if len(artist) == 0:
      return

    # start the progress spinner
    self.task_id = clementine.task_manager.StartTask(self.tr("Getting setlist"))

    # finally - request for the setlists of artist
    reply = self.network.get(QNetworkRequest(self.get_setlist_fm_url(artist)))
    self.artist_map[reply] = artist

    reply.connect("finished()", lambda: self.load_setlist_activated_finalize(reply))

  def load_setlist_activated_finalize(self, reply):
    reply.deleteLater()

    if self.task_id is None:
      return

    # stop the progress spinner
    clementine.task_manager.SetTaskFinished(self.task_id)
    self.task_id = None

    artist = self.artist_map.pop(reply)

    # get the titles of songs from the latest setlist available
    # on setlist.fm for the artist
    data = reply.readAll().data()
    titles = self.parse_setlist_fm_reply(data)

    if len(titles) == 0:
      return

    # we uppercase the titles to make the plugin case insensitive
    titles = map(lambda title: title.upper(), titles)

    # get song ids for titles
    query = clementine.LibraryQuery()

    query.SetColumnSpec('ROWID, title')
    query.AddWhere('UPPER(artist)', artist.upper())
    query.AddWhere('UPPER(title)', titles, 'IN')

    # maps titles to ids; also removes possible title duplicates
    # from the query
    title_map = {}
    if clementine.library.ExecQuery(query):
      while query.Next():
        # be super cautious and throw out the faulty ones
        id = query.Value(0)
        title = query.Value(1)

        title_map[str(title).upper()] = id

    if len(title_map) > 0:
      # get complete song objects for ids
      from_lib = clementine.library.GetSongsById(title_map.values())

      # maps ids to song objects
      lib_title_map = {}
      for song in from_lib:
        lib_title_map[song.id()] = song

      unavailable = []

      into_playlist = []
      # iterate over titles to preserve ordering of songs
      # in the setlist
      for title in titles:
        try:
          # fill the list
          into_playlist.append(lib_title_map[title_map[title]])
        except KeyError:
          # TODO: do something with songs not in library?
          unavailable.append(title)

      # finally - fill the playlist with songs!
      current = clementine.playlists.current()
      if current != None and len(into_playlist) > 0:
        current.InsertLibraryItems(into_playlist)

  def parse_setlist_fm_reply(self, response):
    try:
      response = json.loads(response)

      count = response['setlists']['@total']
      # only if we have at least one set
      if count != None and count > 0:
        # look for the first one with any information
        for setlist in response['setlists']['setlist']:
          result = []

          sets = setlist['sets']
          if len(sets) > 0:
            # this may or may not be an array - make sure it always is!
            final_sets = sets['set'] if len(sets['set']) > 1 else [sets['set']]

            # from all the sets (like main + encore)
            for set in final_sets:
              # this may or may not be an array - make sure it always is!
              final_songs = set['song'] if len(set['song']) > 1 else [set['song']]

              for song in final_songs:
                result.append(song['@name'])

          if len(result) > 0:
            return result

      return []

    except:
      LOGGER.debug('No setlists found')
      return []

  def get_setlist_fm_url(self, artist):
    url = QUrl('http://api.setlist.fm/rest/0.1/search/setlists.json')
    url.addQueryItem('artistName', artist)
    return url