feat: initial qobuz-qt source

Lightweight Qt6 desktop client for Qobuz with a Rust audio backend
(Symphonia/CPAL via staticlib FFI). Mirrors the spotify-qt layout:
toolbar with playback controls, library/context docks on the left,
tabbed search side panel on the right, queue panel, now-playing dock.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
joren
2026-03-24 00:41:04 +01:00
parent 35ae649fc9
commit cb2323bc32
85 changed files with 4484 additions and 249 deletions

View File

@@ -1,6 +1,7 @@
#pragma once
#include "../backend/qobuzbackend.hpp"
#include "../playqueue.hpp"
#include "../widget/volumebutton.hpp"
#include "../widget/clickableslider.hpp"
#include "../util/icon.hpp"
@@ -9,26 +10,27 @@
#include <QToolButton>
#include <QLabel>
#include <QAction>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonObject>
/// Main playback toolbar — mirrors MainToolBar from spotify-qt.
class MainToolBar : public QToolBar
{
Q_OBJECT
public:
explicit MainToolBar(QobuzBackend *backend, QWidget *parent = nullptr);
explicit MainToolBar(QobuzBackend *backend, PlayQueue *queue, QWidget *parent = nullptr);
void setPlaying(bool playing);
void setCurrentTrack(const QJsonObject &track);
void updateProgress(quint64 position, quint64 duration);
void setVolume(int volume);
signals:
void searchToggled(bool visible);
void queueToggled(bool visible);
private slots:
void onPlayPause(bool checked);
void onPlayPause();
void onPrevious();
void onNext();
void onProgressReleased();
@@ -38,26 +40,31 @@ private slots:
void onTrackChanged(const QJsonObject &track);
void onPositionChanged(quint64 position, quint64 duration);
void onTrackFinished();
void onQueueChanged();
void onShuffleToggled(bool checked);
void fetchAlbumArt(const QString &url);
void onAlbumArtReady(QNetworkReply *reply);
private:
QobuzBackend *m_backend = nullptr;
PlayQueue *m_queue = nullptr;
QLabel *m_artLabel = nullptr;
QLabel *m_trackLabel = nullptr;
ClickableSlider *m_progress = nullptr;
QLabel *m_timeLabel = nullptr;
VolumeButton *m_volume = nullptr;
QAction *m_previous = nullptr;
QAction *m_playPause = nullptr;
QAction *m_next = nullptr;
QAction *m_shuffle = nullptr;
QAction *m_queueBtn = nullptr;
QAction *m_search = nullptr;
ClickableSlider *m_progress = nullptr;
QLabel *m_timeLabel = nullptr;
QLabel *m_trackLabel = nullptr;
VolumeButton *m_volume = nullptr;
bool m_playing = false;
bool m_seeking = false;
// Playback queue (track IDs) for next/prev
QVector<qint64> m_queue;
int m_queueIdx = -1;
void addSpacerWidget();
QNetworkAccessManager *m_nam = nullptr;
QString m_currentArtUrl;
bool m_playing = false;
bool m_seeking = false;
};