feat: qbz-1 streaming, gapless prefetch, accurate scrobbling, Range-seek
Port proven playback architecture from qbqt fork: - Bounded VecDeque buffer with condvar backpressure (4MB cap) - decrypt_and_extract_frames for clean FLAC frame extraction from ISOBMFF - Cancel+restart seeking with sub-segment sample skipping - start_prefetch / QueueNext for gapless transitions with pre-started downloads - track_transitioned signaling for scrobbler during gapless playback - Range-request HTTP seeking for non-segmented (MP3) tracks - OnceLock HTTP client singleton with cancel-aware chunked downloads - Accumulated listening time scrobbling (prevents false scrobbles from seeking) - Array-format Last.fm scrobble params (artist[0], track[0], etc.) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -189,7 +189,7 @@ void Tracks::onContextMenu(const QPoint &pos)
|
||||
menu.addSeparator();
|
||||
auto *openAlbum = menu.addAction(
|
||||
QIcon(":/res/icons/view-media-album-cover.svg"),
|
||||
tr("Open album: %1").arg(m_model->trackAt(index.row()).album));
|
||||
tr("Open album: %1").arg(QString(m_model->trackAt(index.row()).album).replace(QLatin1Char('&'), QStringLiteral("&&"))));
|
||||
connect(openAlbum, &QAction::triggered, this, [this, albumId] {
|
||||
m_backend->getAlbum(albumId);
|
||||
});
|
||||
@@ -202,7 +202,7 @@ void Tracks::onContextMenu(const QPoint &pos)
|
||||
const QString artistName = trackJson["performer"].toObject()["name"].toString();
|
||||
auto *openArtist = menu.addAction(
|
||||
QIcon(":/res/icons/view-media-artist.svg"),
|
||||
tr("Open artist: %1").arg(artistName));
|
||||
tr("Open artist: %1").arg(QString(artistName).replace(QLatin1Char('&'), QStringLiteral("&&"))));
|
||||
connect(openArtist, &QAction::triggered, this, [this, artistId] {
|
||||
m_backend->getArtist(artistId);
|
||||
});
|
||||
@@ -216,7 +216,7 @@ void Tracks::onContextMenu(const QPoint &pos)
|
||||
for (const auto &pl : m_userPlaylists) {
|
||||
const qint64 plId = pl.first;
|
||||
const QString plName = pl.second;
|
||||
auto *act = addToPlMenu->addAction(plName);
|
||||
auto *act = addToPlMenu->addAction(QString(plName).replace(QLatin1Char('&'), QStringLiteral("&&")));
|
||||
connect(act, &QAction::triggered, this, [this, id, plId] {
|
||||
emit addToPlaylistRequested(id, plId);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user