Exemplo n.º 1
0
QString CPlayer::replace_tokens(QString str, bool hidePlayingState)
{
    QString status_text = "";
    switch(GetState())
    {
    case PLAYER_STOPPED:
        if(GetPlayer()=="")
            status_text = "";
        else
            status_text = "Stopped";
        break;
    case PLAYER_PAUSED:
        status_text = "Paused";
        break;
    case PLAYER_PLAYING:
        status_text = (hidePlayingState? "" : "Playing");
        break;
    }

    replace_token(str,"title"    ,GetTitle());
    replace_token(str,"artist"   ,GetArtist());
    replace_token(str,"album"    ,GetAlbum());
    replace_token(str,"duration" ,GetDuration(),GetDuration());
    replace_token(str,"played"   ,GetPosition(),GetDuration());
    replace_token(str,"remaining",GetDuration() - GetPosition(),GetDuration());
    replace_token(str,"status"   ,status_text);
    replace_token(str,"player"   ,GetPlayer());
    replace_token(str,"file"     ,GetFilePath());
    replace_token(str,"shuffle"  ,(GetShuffle() ? "Shuffle" : ""));
    replace_token(str,"repeat"   ,(GetRepeat() ? "Repeat" : ""));
    replace_token(str,"rating"   ,QString::number(GetRating()));
    replace_token(str,"lyrics"   ,GetLyrics());
    return str;
}
Exemplo n.º 2
0
void SubsonicLibraryScanner::OnGetAlbumFinished(QNetworkReply* reply) {
  reply->deleteLater();
  pending_requests_.remove(reply);

  QXmlStreamReader reader(reply);
  reader.readNextStartElement();
  Q_ASSERT(reader.name() == "subsonic-response");
  if (reader.attributes().value("status") != "ok") {
    // TODO: error handling
    return;
  }

  // Read album information
  reader.readNextStartElement();
  Q_ASSERT(reader.name() == "album");
  QString album_artist = reader.attributes().value("artist").toString();

  // Read song information
  while (reader.readNextStartElement()) {
    Q_ASSERT(reader.name() == "song");
    Song song;
    QString id = reader.attributes().value("id").toString();
    song.set_title(reader.attributes().value("title").toString());
    song.set_album(reader.attributes().value("album").toString());
    song.set_track(reader.attributes().value("track").toString().toInt());
    song.set_disc(reader.attributes().value("discNumber").toString().toInt());
    song.set_artist(reader.attributes().value("artist").toString());
    song.set_albumartist(album_artist);
    song.set_bitrate(reader.attributes().value("bitRate").toString().toInt());
    song.set_year(reader.attributes().value("year").toString().toInt());
    song.set_genre(reader.attributes().value("genre").toString());
    qint64 length = reader.attributes().value("duration").toString().toInt();
    length *= kNsecPerSec;
    song.set_length_nanosec(length);
    QUrl url = QUrl(QString("subsonic://%1").arg(id));
    song.set_url(url);
    song.set_filesize(reader.attributes().value("size").toString().toInt());
    // We need to set these to satisfy the database constraints
    song.set_directory_id(0);
    song.set_mtime(0);
    song.set_ctime(0);
    songs_ << song;
    reader.skipCurrentElement();
  }

  // Start the next request if albums remain
  if (!album_queue_.empty()) {
    GetAlbum(album_queue_.dequeue());
  }

  // If this was the last response, we're done!
  if (album_queue_.empty() && pending_requests_.empty()) {
    scanning_ = false;
    emit ScanFinished();
  }
}
	void AlbumArtManagerDialog::request ()
	{
		Model_->clear ();

		const auto& artist = GetArtist ();
		const auto& album = GetAlbum ();
		if (artist.isEmpty () || album.isEmpty ())
			return;

		AAMgr_->CheckAlbumArt (artist, album, true);
		RequestScheduled_ = false;
	}
	void AlbumArtManagerDialog::on_BrowseButton__released ()
	{
		const auto& filename = QFileDialog::getOpenFileName (this,
				tr ("Choose album art"),
				QDir::homePath (),
				tr ("Images (*.png *.jpg *.jpeg);;All files (*.*)"));
		if (filename.isEmpty ())
			return;

		QImage image (filename);
		if (image.isNull ())
			return;

		handleImages ({ GetArtist (), GetAlbum () }, { image });
	}
Exemplo n.º 5
0
void SubsonicLibraryScanner::OnGetAlbumListFinished(QNetworkReply* reply,
                                                    int offset) {
  reply->deleteLater();

  QXmlStreamReader reader(reply);
  reader.readNextStartElement();
  Q_ASSERT(reader.name() == "subsonic-response");
  if (reader.attributes().value("status") != "ok") {
    reader.readNextStartElement();
    int error = reader.attributes().value("code").toString().toInt();

    // Compatibility with Ampache :
    // When there is no data, Ampache returns NotFound
    // whereas Subsonic returns empty albumList2 tag
    switch (error) {
      case SubsonicService::ApiError_NotFound:
        break;
      default:
        return;
    }
  }

  int albums_added = 0;
  reader.readNextStartElement();
  Q_ASSERT(reader.name() == "albumList2");
  while (reader.readNextStartElement()) {
    Q_ASSERT(reader.name() == "album");
    album_queue_ << reader.attributes().value("id").toString();
    albums_added++;
    reader.skipCurrentElement();
  }

  if (albums_added > 0) {
    // Non-empty reply means potentially more albums to fetch
    GetAlbumList(offset + kAlbumChunkSize);
  } else if (album_queue_.size() == 0) {
    // Empty reply and no albums means an empty Subsonic server
    scanning_ = false;
  } else {
    // Empty reply but we have some albums, time to start fetching songs
    // Start up the maximum number of concurrent requests, finished requests get
    // replaced with new ones
    for (int i = 0; i < kConcurrentRequests && !album_queue_.empty(); ++i) {
      GetAlbum(album_queue_.dequeue());
    }
  }
}
	void AlbumArtManagerDialog::handleImages (const Media::AlbumInfo& info, const QList<QImage>& images)
	{
		qDebug () << Q_FUNC_INFO << images.size ();
		if (info.Album_ != GetAlbum () || info.Artist_ != GetArtist ())
			return;

		auto watcher = new QFutureWatcher<ScaleResult> ();
		connect (watcher,
				SIGNAL (finished ()),
				this,
				SLOT (handleResized ()));
		auto worker = [info] (const QImage& image) -> ScaleResult
		{
			const auto& scaled = image.scaled (200, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation);
			return { scaled, image, info };
		};
		watcher->setFuture (QtConcurrent::mapped (images, std::function<ScaleResult (QImage)> (worker)));
	}
	void AlbumArtManagerDialog::handleResized ()
	{
		auto watcher = dynamic_cast<QFutureWatcher<ScaleResult>*> (sender ());
		watcher->deleteLater ();

		for (const auto& result : watcher->future ())
		{
			if (result.Info_.Album_ != GetAlbum () ||
					result.Info_.Artist_ != GetArtist ())
				continue;

			auto item = new QStandardItem ();
			item->setIcon (QIcon (QPixmap::fromImage (result.Image_)));
			item->setText (QString::fromUtf8 ("%1×%2")
						.arg (result.SourceImage_.width ())
						.arg (result.SourceImage_.height ()));
			item->setEditable (false);
			Model_->appendRow (item);

			FullImages_ << result.SourceImage_;
		}
	}
Exemplo n.º 8
0
void SubsonicLibraryScanner::OnGetAlbumListFinished(
    QNetworkReply* reply, int offset) {
  reply->deleteLater();

  QXmlStreamReader reader(reply);
  reader.readNextStartElement();
  Q_ASSERT(reader.name() == "subsonic-response");
  if (reader.attributes().value("status") != "ok") {
    // TODO: error handling
    return;
  }

  int albums_added = 0;
  reader.readNextStartElement();
  Q_ASSERT(reader.name() == "albumList2");
  while (reader.readNextStartElement()) {
    Q_ASSERT(reader.name() == "album");
    album_queue_ << reader.attributes().value("id").toString();
    albums_added++;
    reader.skipCurrentElement();
  }

  if (albums_added > 0) {
    // Non-empty reply means potentially more albums to fetch
    GetAlbumList(offset + kAlbumChunkSize);
  } else if (album_queue_.size() == 0) {
    // Empty reply and no albums means an empty Subsonic server
    scanning_ = false;
  } else {
    // Empty reply but we have some albums, time to start fetching songs
    // Start up the maximum number of concurrent requests, finished requests get replaced with new ones
    for (int i = 0; i < kConcurrentRequests && !album_queue_.empty(); ++i) {
      GetAlbum(album_queue_.dequeue());
    }
  }
}
PlaylistItemList SubsonicDynamicPlaylist::GenerateMore(int count) {
  SubsonicService* service = InternetModel::Service<SubsonicService>();
  const int task_id =
      service->app_->task_manager()->StartTask(tr("Fetching Playlist Items"));

  BOOST_SCOPE_EXIT((service)(task_id)) {
    // stop task when we're done
    service->app_->task_manager()->SetTaskFinished(task_id);
  }
  BOOST_SCOPE_EXIT_END

  QUrl url = service->BuildRequestUrl("GetAlbumList");
  QNetworkAccessManager network;

  if (count > kMaxCount) count = kMaxCount;

  url.addQueryItem("type", GetTypeString());
  url.addQueryItem("size", QString::number(count));
  url.addQueryItem("offset", QString::number(offset_));

  PlaylistItemList items;

  QNetworkReply* reply = Send(network, url, service->usesslv3_);
  WaitForSignal(reply, SIGNAL(finished()));

  reply->deleteLater();

  if (reply->error() != QNetworkReply::NoError) {
    qLog(Warning) << "HTTP error returned from Subsonic:"
                  << reply->errorString() << ", url:" << url.toString();
    return items;  // empty
  }

  QXmlStreamReader reader(reply);
  reader.readNextStartElement();
  if (reader.name() != "subsonic-response") {
    qLog(Warning) << "Not a subsonic-response, aboring playlist fetch";
    return items;
  }

  if (reader.attributes().value("status") != "ok") {
    reader.readNextStartElement();
    int error = reader.attributes().value("code").toString().toInt();
    qLog(Warning) << "An error occured fetching data.  Code: " << error
                  << " Message: "
                  << reader.attributes().value("message").toString();
  }

  reader.readNextStartElement();
  if (reader.name() != "albumList") {
    qLog(Warning) << "albumList tag expected.  Aboring playlist fetch";
    return items;
  }

  while (reader.readNextStartElement()) {
    if (reader.name() != "album") {
      qLog(Warning) << "album tag expected. Aboring playlist fetch";
      return items;
    }

    qLog(Debug) << "Getting album: "
                << reader.attributes().value("album").toString();
    GetAlbum(service, items, reader.attributes().value("id").toString(),
             network, service->usesslv3_);
    reader.skipCurrentElement();
  }
  offset_ += count;
  return items;
}