Rename EngineBase

This commit is contained in:
Jonas Kvinge 2023-04-22 19:13:42 +02:00
parent c3534affdb
commit e9f3281694
35 changed files with 451 additions and 500 deletions

View File

@ -58,10 +58,10 @@ set(SOURCES
utilities/coverutils.cpp
utilities/screenutils.cpp
engine/enginetype.cpp
engine/enginebase.cpp
engine/devicefinders.cpp
engine/devicefinder.cpp
engine/enginemetadata.cpp
analyzer/fht.cpp
analyzer/analyzerbase.cpp

View File

@ -108,8 +108,8 @@ void Analyzer::Base::paintEvent(QPaintEvent *e) {
p.fillRect(e->rect(), palette().color(QPalette::Window));
switch (engine_->state()) {
case Engine::State::Playing: {
const Engine::Scope &thescope = engine_->scope(timeout_);
case EngineBase::State::Playing: {
const EngineBase::Scope &thescope = engine_->scope(timeout_);
int i = 0;
// convert to mono here - our built in analyzers need mono, but the engines provide interleaved pcm
@ -126,7 +126,7 @@ void Analyzer::Base::paintEvent(QPaintEvent *e) {
break;
}
case Engine::State::Paused:
case EngineBase::State::Paused:
is_playing_ = false;
analyze(p, lastscope_, new_frame_);
break;

View File

@ -39,7 +39,6 @@
#include <QPainter>
#include "analyzer/fht.h"
#include "engine/engine_fwd.h"
#include "engine/enginebase.h"
class QHideEvent;

View File

@ -44,7 +44,6 @@
#include "core/logging.h"
#include "engine/enginebase.h"
#include "engine/enginetype.h"
using namespace std::chrono_literals;
@ -104,7 +103,7 @@ AnalyzerContainer::AnalyzerContainer(QWidget *parent)
void AnalyzerContainer::mouseReleaseEvent(QMouseEvent *e) {
if (engine_->type() != Engine::EngineType::GStreamer) {
if (engine_->type() != EngineBase::Type::GStreamer) {
return;
}

View File

@ -30,7 +30,7 @@
#include <QAction>
#include <QActionGroup>
#include "engine/engine_fwd.h"
#include "engine/enginebase.h"
class QTimer;
class QMouseEvent;

View File

@ -32,7 +32,6 @@
#include <QPalette>
#include <QColor>
#include "engine/engine_fwd.h"
#include "engine/enginebase.h"
#include "fht.h"
#include "analyzerbase.h"
@ -110,7 +109,7 @@ void BoomAnalyzer::transform(Scope &s) {
void BoomAnalyzer::analyze(QPainter &p, const Scope &scope, const bool new_frame) {
if (!new_frame || engine_->state() == Engine::State::Paused) {
if (!new_frame || engine_->state() == EngineBase::State::Paused) {
p.drawPixmap(0, 0, canvas_);
return;
}

View File

@ -24,6 +24,8 @@
#include <QPainter>
#include <QResizeEvent>
#include "engine/enginebase.h"
#include "sonogram.h"
const char *Sonogram::kName = QT_TRANSLATE_NOOP("AnalyzerContainer", "Sonogram");
@ -42,7 +44,7 @@ void Sonogram::resizeEvent(QResizeEvent *e) {
void Sonogram::analyze(QPainter &p, const Analyzer::Scope &s, bool new_frame) {
if (!new_frame || engine_->state() == Engine::State::Paused) {
if (!new_frame || engine_->state() == EngineBase::State::Paused) {
p.drawPixmap(0, 0, canvas_);
return;
}

View File

@ -55,9 +55,7 @@
#include "utilities/strutils.h"
#include "utilities/timeutils.h"
#include "widgets/resizabletextedit.h"
#include "engine/engine_fwd.h"
#include "engine/enginebase.h"
#include "engine/enginetype.h"
#include "engine/devicefinders.h"
#include "engine/devicefinder.h"
#include "collection/collectionbackend.h"
@ -544,12 +542,12 @@ void ContextView::SetSong() {
if (action_show_output_->isChecked()) {
widget_play_output_->show();
Engine::EngineType enginetype(Engine::EngineType::None);
EngineBase::Type enginetype = EngineBase::Type::None;
if (app_->player()->engine()) enginetype = app_->player()->engine()->type();
QIcon icon_engine = IconLoader::Load(EngineName(enginetype), true, 32);
QIcon icon_engine = IconLoader::Load(EngineBase::Name(enginetype), true, 32);
label_engine_icon_->setPixmap(icon_engine.pixmap(QSize(32, 32)));
label_engine_->setText(EngineDescription(enginetype));
label_engine_->setText(EngineBase::Description(enginetype));
spacer_play_output_->changeSize(20, 20, QSizePolicy::Fixed);
DeviceFinder::Device device;

View File

@ -103,9 +103,7 @@
#include "utilities/filemanagerutils.h"
#include "utilities/timeconstants.h"
#include "utilities/screenutils.h"
#include "engine/enginetype.h"
#include "engine/enginebase.h"
#include "engine/engine_fwd.h"
#include "dialogs/errordialog.h"
#include "dialogs/about.h"
#include "dialogs/console.h"
@ -1246,7 +1244,7 @@ void MainWindow::Exit() {
if (app_->player()->engine()->is_fadeout_enabled()) {
// To shut down the application when fadeout will be finished
QObject::connect(app_->player()->engine(), &EngineBase::FadeoutFinishedSignal, this, &MainWindow::DoExit);
if (app_->player()->GetState() == Engine::State::Playing) {
if (app_->player()->GetState() == EngineBase::State::Playing) {
app_->player()->Stop();
ignore_close_ = true;
close();
@ -1275,11 +1273,11 @@ void MainWindow::ExitFinished() {
}
void MainWindow::EngineChanged(Engine::EngineType enginetype) {
void MainWindow::EngineChanged(const EngineBase::Type enginetype) {
ui_->action_equalizer->setEnabled(enginetype == Engine::EngineType::GStreamer);
ui_->action_equalizer->setEnabled(enginetype == EngineBase::Type::GStreamer);
#if defined(HAVE_AUDIOCD) && !defined(Q_OS_WIN)
ui_->action_open_cd->setEnabled(enginetype == Engine::EngineType::GStreamer);
ui_->action_open_cd->setEnabled(enginetype == EngineBase::Type::GStreamer);
#else
ui_->action_open_cd->setEnabled(false);
ui_->action_open_cd->setVisible(false);
@ -1460,7 +1458,7 @@ void MainWindow::SavePlaybackStatus() {
s.beginGroup(Player::kSettingsGroup);
s.setValue("playback_state", static_cast<int>(app_->player()->GetState()));
if (app_->player()->GetState() == Engine::State::Playing || app_->player()->GetState() == Engine::State::Paused) {
if (app_->player()->GetState() == EngineBase::State::Playing || app_->player()->GetState() == EngineBase::State::Paused) {
s.setValue("playback_playlist", app_->playlist_manager()->active()->id());
s.setValue("playback_position", app_->player()->engine()->position_nanosec() / kNsecPerSec);
}
@ -1482,10 +1480,10 @@ void MainWindow::LoadPlaybackStatus() {
s.endGroup();
s.beginGroup(Player::kSettingsGroup);
const Engine::State playback_state = static_cast<Engine::State>(s.value("playback_state", static_cast<int>(Engine::State::Empty)).toInt());
const EngineBase::State playback_state = static_cast<EngineBase::State>(s.value("playback_state", static_cast<int>(EngineBase::State::Empty)).toInt());
s.endGroup();
if (resume_playback && playback_state != Engine::State::Empty && playback_state != Engine::State::Idle) {
if (resume_playback && playback_state != EngineBase::State::Empty && playback_state != EngineBase::State::Idle) {
std::shared_ptr<QMetaObject::Connection> connection = std::make_shared<QMetaObject::Connection>();
*connection = QObject::connect(app_->playlist_manager(), &PlaylistManager::AllPlaylistsLoaded, this, [this, connection]() {
QObject::disconnect(*connection);
@ -1501,7 +1499,7 @@ void MainWindow::ResumePlayback() {
QSettings s;
s.beginGroup(Player::kSettingsGroup);
const Engine::State playback_state = static_cast<Engine::State>(s.value("playback_state", static_cast<int>(Engine::State::Empty)).toInt());
const EngineBase::State playback_state = static_cast<EngineBase::State>(s.value("playback_state", static_cast<int>(EngineBase::State::Empty)).toInt());
int playback_playlist = s.value("playback_playlist", -1).toInt();
int playback_position = s.value("playback_position", 0).toInt();
s.endGroup();
@ -1509,7 +1507,7 @@ void MainWindow::ResumePlayback() {
if (playback_playlist == app_->playlist_manager()->current()->id()) {
// Set active to current to resume playback on correct playlist.
app_->playlist_manager()->SetActiveToCurrent();
if (playback_state == Engine::State::Paused) {
if (playback_state == EngineBase::State::Paused) {
std::shared_ptr<QMetaObject::Connection> connection = std::make_shared<QMetaObject::Connection>();
*connection = QObject::connect(app_->player(), &Player::Playing, app_->player(), [this, connection]() {
QObject::disconnect(*connection);
@ -1521,7 +1519,7 @@ void MainWindow::ResumePlayback() {
// Reset saved playback status so we don't resume again from the same position.
s.beginGroup(Player::kSettingsGroup);
s.setValue("playback_state", static_cast<int>(Engine::State::Empty));
s.setValue("playback_state", static_cast<int>(EngineBase::State::Empty));
s.setValue("playback_playlist", -1);
s.setValue("playback_position", 0);
s.endGroup();
@ -1539,7 +1537,7 @@ void MainWindow::PlayIndex(const QModelIndex &idx, Playlist::AutoScroll autoscro
}
app_->playlist_manager()->SetActiveToCurrent();
app_->player()->PlayAt(row, 0, Engine::TrackChangeType::Manual, autoscroll, true);
app_->player()->PlayAt(row, 0, EngineBase::TrackChangeType::Manual, autoscroll, true);
}
@ -1556,14 +1554,14 @@ void MainWindow::PlaylistDoubleClick(const QModelIndex &idx) {
switch (doubleclick_playlist_addmode_) {
case BehaviourSettingsPage::PlaylistAddBehaviour::Play:
app_->playlist_manager()->SetActiveToCurrent();
app_->player()->PlayAt(source_idx.row(), 0, Engine::TrackChangeType::Manual, Playlist::AutoScroll::Never, true, true);
app_->player()->PlayAt(source_idx.row(), 0, EngineBase::TrackChangeType::Manual, Playlist::AutoScroll::Never, true, true);
break;
case BehaviourSettingsPage::PlaylistAddBehaviour::Enqueue:
app_->playlist_manager()->current()->queue()->ToggleTracks(QModelIndexList() << source_idx);
if (app_->player()->GetState() != Engine::State::Playing) {
if (app_->player()->GetState() != EngineBase::State::Playing) {
app_->playlist_manager()->SetActiveToCurrent();
app_->player()->PlayAt(app_->playlist_manager()->current()->queue()->TakeNext(), 0, Engine::TrackChangeType::Manual, Playlist::AutoScroll::Never, true);
app_->player()->PlayAt(app_->playlist_manager()->current()->queue()->TakeNext(), 0, EngineBase::TrackChangeType::Manual, Playlist::AutoScroll::Never, true);
}
break;
}
@ -1749,7 +1747,7 @@ void MainWindow::ApplyPlayBehaviour(const BehaviourSettingsPage::PlayBehaviour b
break;
case BehaviourSettingsPage::PlayBehaviour::IfStopped:
mimedata->play_now_ = !(app_->player()->GetState() == Engine::State::Playing);
mimedata->play_now_ = !(app_->player()->GetState() == EngineBase::State::Playing);
break;
}
}
@ -1835,7 +1833,7 @@ void MainWindow::PlaylistRightClick(const QPoint global_pos, const QModelIndex &
playlist_menu_index_ = source_index;
// Is this song currently playing?
if (app_->playlist_manager()->current()->current_row() == source_index.row() && app_->player()->GetState() == Engine::State::Playing) {
if (app_->playlist_manager()->current()->current_row() == source_index.row() && app_->player()->GetState() == EngineBase::State::Playing) {
playlist_play_pause_->setText(tr("Pause"));
playlist_play_pause_->setIcon(IconLoader::Load("media-playback-pause"));
}
@ -2480,7 +2478,7 @@ void MainWindow::CommandlineOptionsReceived(const CommandlineOptions &options) {
app_->player()->SeekTo(app_->player()->engine()->position_nanosec() / kNsecPerSec + options.seek_by());
}
if (options.play_track_at() != -1) app_->player()->PlayAt(options.play_track_at(), 0, Engine::TrackChangeType::Manual, Playlist::AutoScroll::Maybe, true);
if (options.play_track_at() != -1) app_->player()->PlayAt(options.play_track_at(), 0, EngineBase::TrackChangeType::Manual, Playlist::AutoScroll::Maybe, true);
if (options.show_osd()) app_->player()->ShowOSD();
@ -3189,13 +3187,13 @@ void MainWindow::PlaylistDelete() {
if (DeleteConfirmationDialog::warning(files) != QDialogButtonBox::Yes) return;
if (app_->player()->GetState() == Engine::State::Playing && app_->playlist_manager()->current()->rowCount() == selected_songs.count()) {
if (app_->player()->GetState() == EngineBase::State::Playing && app_->playlist_manager()->current()->rowCount() == selected_songs.count()) {
app_->player()->Stop();
}
ui_->playlist->view()->RemoveSelected();
if (app_->player()->GetState() == Engine::State::Playing && is_current_item) {
if (app_->player()->GetState() == EngineBase::State::Playing && is_current_item) {
app_->player()->Next();
}

View File

@ -52,8 +52,7 @@
#include "platforminterface.h"
#include "song.h"
#include "tagreaderclient.h"
#include "engine/enginetype.h"
#include "engine/engine_fwd.h"
#include "engine/enginebase.h"
#include "osd/osdbase.h"
#include "collection/collectionmodel.h"
#include "playlist/playlist.h"
@ -142,7 +141,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
private slots:
void FilePathChanged(const QString &path);
void EngineChanged(Engine::EngineType enginetype);
void EngineChanged(const EngineBase::Type enginetype);
void MediaStopped();
void MediaPaused();
void MediaPlaying();

View File

@ -47,9 +47,8 @@
#include "song.h"
#include "engine/engine_fwd.h"
#include "engine/enginebase.h"
#include "engine/enginetype.h"
#include "engine/enginemetadata.h"
#ifdef HAVE_GSTREAMER
# include "engine/gstenginepipeline.h"
#endif
@ -103,11 +102,11 @@ void RegisterMetaTypes() {
qRegisterMetaType<SongMap>("SongMap");
qRegisterMetaType<Song::Source>("Song::Source");
qRegisterMetaType<Song::FileType>("Song::FileType");
qRegisterMetaType<Engine::EngineType>("Engine::EngineType");
qRegisterMetaType<Engine::SimpleMetaBundle>("Engine::SimpleMetaBundle");
qRegisterMetaType<Engine::State>("Engine::State");
qRegisterMetaType<Engine::TrackChangeFlags>("Engine::TrackChangeFlags");
qRegisterMetaType<EngineBase::Type>("EngineBase::Type");
qRegisterMetaType<EngineBase::State>("EngineBase::State");
qRegisterMetaType<EngineBase::TrackChangeFlags>("EngineBase::TrackChangeFlags");
qRegisterMetaType<EngineBase::OutputDetails>("EngineBase::OutputDetails");
qRegisterMetaType<EngineMetadata>("EngineMetadata");
#ifdef HAVE_GSTREAMER
qRegisterMetaType<GstBuffer*>("GstBuffer*");
qRegisterMetaType<GstElement*>("GstElement*");

View File

@ -162,9 +162,9 @@ void Mpris2::PlaylistManagerInitialized() {
QObject::connect(app_->playlist_manager()->sequence(), &PlaylistSequence::RepeatModeChanged, this, &Mpris2::RepeatModeChanged);
}
void Mpris2::EngineStateChanged(Engine::State newState) {
void Mpris2::EngineStateChanged(EngineBase::State newState) {
if (newState != Engine::State::Playing && newState != Engine::State::Paused) {
if (newState != EngineBase::State::Playing && newState != EngineBase::State::Paused) {
last_metadata_ = QVariantMap();
EmitNotification("Metadata");
}
@ -172,7 +172,7 @@ void Mpris2::EngineStateChanged(Engine::State newState) {
EmitNotification("CanPlay");
EmitNotification("CanPause");
EmitNotification("PlaybackStatus", PlaybackStatus(newState));
if (newState == Engine::State::Playing) EmitNotification("CanSeek", CanSeek(newState));
if (newState == EngineBase::State::Playing) EmitNotification("CanSeek", CanSeek(newState));
}
@ -304,11 +304,11 @@ QString Mpris2::PlaybackStatus() const {
return PlaybackStatus(app_->player()->GetState());
}
QString Mpris2::PlaybackStatus(Engine::State state) const {
QString Mpris2::PlaybackStatus(EngineBase::State state) const {
switch (state) {
case Engine::State::Playing: return "Playing";
case Engine::State::Paused: return "Paused";
case EngineBase::State::Playing: return "Playing";
case EngineBase::State::Paused: return "Paused";
default: return "Stopped";
}
@ -449,13 +449,13 @@ bool Mpris2::CanPlay() const {
// This one's a bit different than MPRIS 1 - we want this to be true even when the song is already paused or stopped.
bool Mpris2::CanPause() const {
return (app_->player()->GetCurrentItem() && app_->player()->GetState() == Engine::State::Playing && !(app_->player()->GetCurrentItem()->options() & PlaylistItem::Option::PauseDisabled)) || PlaybackStatus() == "Paused" || PlaybackStatus() == "Stopped";
return (app_->player()->GetCurrentItem() && app_->player()->GetState() == EngineBase::State::Playing && !(app_->player()->GetCurrentItem()->options() & PlaylistItem::Option::PauseDisabled)) || PlaybackStatus() == "Paused" || PlaybackStatus() == "Stopped";
}
bool Mpris2::CanSeek() const { return CanSeek(app_->player()->GetState()); }
bool Mpris2::CanSeek(Engine::State state) const {
return app_->player()->GetCurrentItem() && state != Engine::State::Empty && !app_->player()->GetCurrentItem()->Metadata().is_stream();
bool Mpris2::CanSeek(EngineBase::State state) const {
return app_->player()->GetCurrentItem() && state != EngineBase::State::Empty && !app_->player()->GetCurrentItem()->Metadata().is_stream();
}
bool Mpris2::CanControl() const { return true; }
@ -473,7 +473,7 @@ void Mpris2::Previous() {
}
void Mpris2::Pause() {
if (CanPause() && app_->player()->GetState() != Engine::State::Paused) {
if (CanPause() && app_->player()->GetState() != EngineBase::State::Paused) {
app_->player()->Pause();
}
}

View File

@ -38,7 +38,7 @@
#include <qdbusextratypes.h>
#include <QJsonObject>
#include "engine/engine_fwd.h"
#include "engine/enginebase.h"
#include "covermanager/albumcoverloaderresult.h"
class Application;
@ -203,7 +203,7 @@ class Mpris2 : public QObject {
private slots:
void AlbumCoverLoaded(const Song &song, AlbumCoverLoaderResultPtr result = AlbumCoverLoaderResultPtr());
void EngineStateChanged(Engine::State newState);
void EngineStateChanged(EngineBase::State newState);
void VolumeChanged();
void PlaylistManagerInitialized();
@ -218,11 +218,11 @@ class Mpris2 : public QObject {
void EmitNotification(const QString &name, const QVariant &value);
void EmitNotification(const QString &name, const QVariant &value, const QString &mprisEntity);
QString PlaybackStatus(Engine::State state) const;
QString PlaybackStatus(EngineBase::State state) const;
QString current_track_id() const;
bool CanSeek(Engine::State state) const;
bool CanSeek(EngineBase::State state) const;
QString DesktopEntryAbsolutePath() const;

View File

@ -43,7 +43,7 @@
#include "application.h"
#include "engine/enginebase.h"
#include "engine/enginetype.h"
#include "engine/enginemetadata.h"
#ifdef HAVE_GSTREAMER
# include "engine/gstengine.h"
@ -79,9 +79,9 @@ Player::Player(Application *app, QObject *parent)
#endif
analyzer_(nullptr),
equalizer_(nullptr),
stream_change_type_(Engine::TrackChangeType::First),
stream_change_type_(EngineBase::TrackChangeType::First),
autoscroll_(Playlist::AutoScroll::Maybe),
last_state_(Engine::State::Empty),
last_state_(EngineBase::State::Empty),
nb_errors_received_(0),
volume_(100),
volume_before_mute_(100),
@ -94,23 +94,23 @@ Player::Player(Application *app, QObject *parent)
QSettings s;
s.beginGroup(BackendSettingsPage::kSettingsGroup);
Engine::EngineType enginetype = Engine::EngineTypeFromName(s.value("engine", EngineName(Engine::EngineType::GStreamer)).toString().toLower());
EngineBase::Type enginetype = EngineBase::TypeFromName(s.value("engine", EngineBase::Name(EngineBase::Type::GStreamer)).toString().toLower());
s.endGroup();
CreateEngine(enginetype);
}
Engine::EngineType Player::CreateEngine(Engine::EngineType enginetype) {
EngineBase::Type Player::CreateEngine(EngineBase::Type enginetype) {
Engine::EngineType use_enginetype(Engine::EngineType::None);
EngineBase::Type use_enginetype = EngineBase::Type::None;
for (int i = 0; use_enginetype == Engine::EngineType::None; i++) {
for (int i = 0; use_enginetype == EngineBase::Type::None; i++) {
switch (enginetype) {
case Engine::EngineType::None:
case EngineBase::Type::None:
#ifdef HAVE_GSTREAMER
case Engine::EngineType::GStreamer:{
use_enginetype=Engine::EngineType::GStreamer;
case EngineBase::Type::GStreamer:{
use_enginetype=EngineBase::Type::GStreamer;
std::unique_ptr<GstEngine> gst_engine(new GstEngine(app_->task_manager()));
gst_engine->SetStartup(gst_startup_);
engine_.reset(gst_engine.release());
@ -118,8 +118,8 @@ Engine::EngineType Player::CreateEngine(Engine::EngineType enginetype) {
}
#endif
#ifdef HAVE_VLC
case Engine::EngineType::VLC:
use_enginetype = Engine::EngineType::VLC;
case EngineBase::Type::VLC:
use_enginetype = EngineBase::Type::VLC;
engine_ = std::make_shared<VLCEngine>(app_->task_manager());
break;
#endif
@ -127,7 +127,7 @@ Engine::EngineType Player::CreateEngine(Engine::EngineType enginetype) {
if (i > 0) {
qFatal("No engine available!");
}
enginetype = Engine::EngineType::None;
enginetype = EngineBase::Type::None;
break;
}
}
@ -135,7 +135,7 @@ Engine::EngineType Player::CreateEngine(Engine::EngineType enginetype) {
if (use_enginetype != enginetype) { // Engine was set to something else. Reset output and device.
QSettings s;
s.beginGroup(BackendSettingsPage::kSettingsGroup);
s.setValue("engine", EngineName(use_enginetype));
s.setValue("engine", EngineBase::Name(use_enginetype));
s.setValue("output", engine_->DefaultOutput());
s.setValue("device", QVariant());
s.endGroup();
@ -157,7 +157,7 @@ void Player::Init() {
if (!engine_) {
s.beginGroup(BackendSettingsPage::kSettingsGroup);
Engine::EngineType enginetype = Engine::EngineTypeFromName(s.value("engine", EngineName(Engine::EngineType::GStreamer)).toString().toLower());
EngineBase::Type enginetype = EngineBase::TypeFromName(s.value("engine", EngineBase::Name(EngineBase::Type::GStreamer)).toString().toLower());
s.endGroup();
CreateEngine(enginetype);
}
@ -363,9 +363,9 @@ void Player::HandleLoadResult(const UrlHandler::LoadResult &result) {
}
void Player::Next() { NextInternal(Engine::TrackChangeType::Manual, Playlist::AutoScroll::Always); }
void Player::Next() { NextInternal(EngineBase::TrackChangeType::Manual, Playlist::AutoScroll::Always); }
void Player::NextInternal(const Engine::TrackChangeFlags change, const Playlist::AutoScroll autoscroll) {
void Player::NextInternal(const EngineBase::TrackChangeFlags change, const Playlist::AutoScroll autoscroll) {
pause_time_ = QDateTime();
play_offset_nanosec_ = 0;
@ -376,7 +376,7 @@ void Player::NextInternal(const Engine::TrackChangeFlags change, const Playlist:
}
void Player::NextItem(const Engine::TrackChangeFlags change, const Playlist::AutoScroll autoscroll) {
void Player::NextItem(const EngineBase::TrackChangeFlags change, const Playlist::AutoScroll autoscroll) {
pause_time_ = QDateTime();
play_offset_nanosec_ = 0;
@ -384,7 +384,7 @@ void Player::NextItem(const Engine::TrackChangeFlags change, const Playlist::Aut
Playlist *active_playlist = app_->playlist_manager()->active();
// If we received too many errors in auto change, with repeat enabled, we stop
if (change == Engine::TrackChangeType::Auto) {
if (change == EngineBase::TrackChangeType::Auto) {
const PlaylistSequence::RepeatMode repeat_mode = active_playlist->sequence()->repeat_mode();
if (repeat_mode != PlaylistSequence::RepeatMode::Off) {
if ((repeat_mode == PlaylistSequence::RepeatMode::Track && nb_errors_received_ >= 3) || (nb_errors_received_ >= app_->playlist_manager()->active()->filter()->rowCount())) {
@ -397,7 +397,7 @@ void Player::NextItem(const Engine::TrackChangeFlags change, const Playlist::Aut
}
// Manual track changes override "Repeat track"
const bool ignore_repeat_track = change & Engine::TrackChangeType::Manual;
const bool ignore_repeat_track = change & EngineBase::TrackChangeType::Manual;
int i = active_playlist->next_row(ignore_repeat_track);
if (i == -1) {
@ -413,10 +413,10 @@ void Player::NextItem(const Engine::TrackChangeFlags change, const Playlist::Aut
}
void Player::PlayPlaylist(const QString &playlist_name) {
PlayPlaylistInternal(Engine::TrackChangeType::Manual, Playlist::AutoScroll::Always, playlist_name);
PlayPlaylistInternal(EngineBase::TrackChangeType::Manual, Playlist::AutoScroll::Always, playlist_name);
}
void Player::PlayPlaylistInternal(const Engine::TrackChangeFlags change, const Playlist::AutoScroll autoscroll, const QString &playlist_name) {
void Player::PlayPlaylistInternal(const EngineBase::TrackChangeFlags change, const Playlist::AutoScroll autoscroll, const QString &playlist_name) {
pause_time_ = QDateTime();
play_offset_nanosec_ = 0;
@ -474,19 +474,19 @@ void Player::TrackEnded() {
if (HandleStopAfter(Playlist::AutoScroll::Maybe)) return;
NextInternal(Engine::TrackChangeType::Auto, Playlist::AutoScroll::Maybe);
NextInternal(EngineBase::TrackChangeType::Auto, Playlist::AutoScroll::Maybe);
}
void Player::PlayPause(const quint64 offset_nanosec, const Playlist::AutoScroll autoscroll) {
switch (engine_->state()) {
case Engine::State::Paused:
case EngineBase::State::Paused:
UnPause();
emit Resumed();
break;
case Engine::State::Playing: {
case EngineBase::State::Playing: {
if (current_item_->options() & PlaylistItem::Option::PauseDisabled) {
Stop();
}
@ -498,9 +498,9 @@ void Player::PlayPause(const quint64 offset_nanosec, const Playlist::AutoScroll
break;
}
case Engine::State::Empty:
case Engine::State::Error:
case Engine::State::Idle: {
case EngineBase::State::Empty:
case EngineBase::State::Error:
case EngineBase::State::Idle: {
pause_time_ = QDateTime();
play_offset_nanosec_ = offset_nanosec;
app_->playlist_manager()->SetActivePlaylist(app_->playlist_manager()->current_id());
@ -508,7 +508,7 @@ void Player::PlayPause(const quint64 offset_nanosec, const Playlist::AutoScroll
int i = app_->playlist_manager()->active()->current_row();
if (i == -1) i = app_->playlist_manager()->active()->last_played_row();
if (i == -1) i = 0;
PlayAt(i, offset_nanosec, Engine::TrackChangeType::First, autoscroll, true);
PlayAt(i, offset_nanosec, EngineBase::TrackChangeType::First, autoscroll, true);
break;
}
}
@ -572,14 +572,14 @@ bool Player::PreviousWouldRestartTrack() const {
}
void Player::Previous() { PreviousItem(Engine::TrackChangeType::Manual); }
void Player::Previous() { PreviousItem(EngineBase::TrackChangeType::Manual); }
void Player::PreviousItem(const Engine::TrackChangeFlags change) {
void Player::PreviousItem(const EngineBase::TrackChangeFlags change) {
pause_time_ = QDateTime();
play_offset_nanosec_ = 0;
const bool ignore_repeat_track = change & Engine::TrackChangeType::Manual;
const bool ignore_repeat_track = change & EngineBase::TrackChangeType::Manual;
if (menu_previousmode_ == BehaviourSettingsPage::PreviousBehaviour::Restart) {
// Check if it has been over two seconds since previous button was pressed
@ -604,9 +604,9 @@ void Player::PreviousItem(const Engine::TrackChangeFlags change) {
}
void Player::EngineStateChanged(const Engine::State state) {
void Player::EngineStateChanged(const EngineBase::State state) {
if (state == Engine::State::Error) {
if (state == EngineBase::State::Error) {
nb_errors_received_++;
}
else {
@ -614,21 +614,21 @@ void Player::EngineStateChanged(const Engine::State state) {
}
switch (state) {
case Engine::State::Paused:
case EngineBase::State::Paused:
pause_time_ = QDateTime::currentDateTime();
play_offset_nanosec_ = engine_->position_nanosec();
emit Paused();
break;
case Engine::State::Playing:
case EngineBase::State::Playing:
pause_time_ = QDateTime();
play_offset_nanosec_ = 0;
emit Playing();
break;
case Engine::State::Error:
case EngineBase::State::Error:
emit Error();
[[fallthrough]];
case Engine::State::Empty:
case Engine::State::Idle:
case EngineBase::State::Empty:
case EngineBase::State::Idle:
pause_time_ = QDateTime();
play_offset_nanosec_ = 0;
emit Stopped();
@ -695,17 +695,17 @@ void Player::VolumeDown() {
}
void Player::PlayAt(const int index, const quint64 offset_nanosec, Engine::TrackChangeFlags change, const Playlist::AutoScroll autoscroll, const bool reshuffle, const bool force_inform) {
void Player::PlayAt(const int index, const quint64 offset_nanosec, EngineBase::TrackChangeFlags change, const Playlist::AutoScroll autoscroll, const bool reshuffle, const bool force_inform) {
pause_time_ = QDateTime();
play_offset_nanosec_ = offset_nanosec;
if (current_item_ && change == Engine::TrackChangeType::Manual && engine_->position_nanosec() != engine_->length_nanosec()) {
if (current_item_ && change == EngineBase::TrackChangeType::Manual && engine_->position_nanosec() != engine_->length_nanosec()) {
emit TrackSkipped(current_item_);
}
if (current_item_ && app_->playlist_manager()->active()->has_item_at(index) && current_item_->Metadata().IsOnSameAlbum(app_->playlist_manager()->active()->item_at(index)->Metadata())) {
change |= Engine::TrackChangeType::SameAlbum;
change |= EngineBase::TrackChangeType::SameAlbum;
}
if (reshuffle) app_->playlist_manager()->active()->ReshuffleIndices();
@ -774,25 +774,25 @@ void Player::SeekBackward() {
SeekTo(engine()->position_nanosec() / kNsecPerSec - seek_step_sec_);
}
void Player::EngineMetadataReceived(const Engine::SimpleMetaBundle &bundle) {
void Player::EngineMetadataReceived(const EngineMetadata &engine_metadata) {
if (bundle.type == Engine::SimpleMetaBundle::Type::Any || bundle.type == Engine::SimpleMetaBundle::Type::Current) {
if (engine_metadata.type == EngineMetadata::Type::Any || engine_metadata.type == EngineMetadata::Type::Current) {
PlaylistItemPtr item = app_->playlist_manager()->active()->current_item();
if (item && bundle.media_url == item->Url()) {
if (item && engine_metadata.media_url == item->Url()) {
Song song = item->Metadata();
bool minor = song.MergeFromSimpleMetaBundle(bundle);
bool minor = song.MergeFromEngineMetadata(engine_metadata);
app_->playlist_manager()->active()->SetStreamMetadata(item->Url(), song, minor);
return;
}
}
if (bundle.type == Engine::SimpleMetaBundle::Type::Any || bundle.type == Engine::SimpleMetaBundle::Type::Next) {
if (engine_metadata.type == EngineMetadata::Type::Any || engine_metadata.type == EngineMetadata::Type::Next) {
int next_row = app_->playlist_manager()->active()->next_row();
if (next_row != -1) {
PlaylistItemPtr next_item = app_->playlist_manager()->active()->item_at(next_row);
if (bundle.media_url == next_item->Url()) {
if (engine_metadata.media_url == next_item->Url()) {
Song song = next_item->Metadata();
song.MergeFromSimpleMetaBundle(bundle);
song.MergeFromEngineMetadata(engine_metadata);
next_item->SetTemporaryMetadata(song);
app_->playlist_manager()->active()->ItemChanged(next_row);
}
@ -828,10 +828,10 @@ void Player::Pause() { engine_->Pause(); }
void Player::Play(const quint64 offset_nanosec) {
switch (GetState()) {
case Engine::State::Playing:
case EngineBase::State::Playing:
SeekTo(offset_nanosec);
break;
case Engine::State::Paused:
case EngineBase::State::Paused:
UnPause();
break;
default:
@ -929,7 +929,7 @@ void Player::InvalidSongRequested(const QUrl &url) {
return;
}
NextItem(Engine::TrackChangeType::Auto, Playlist::AutoScroll::Maybe);
NextItem(EngineBase::TrackChangeType::Auto, Playlist::AutoScroll::Maybe);
}

View File

@ -34,8 +34,8 @@
#include <QUrl>
#include "urlhandler.h"
#include "engine/engine_fwd.h"
#include "engine/enginetype.h"
#include "engine/enginebase.h"
#include "engine/enginemetadata.h"
#include "playlist/playlist.h"
#include "playlist/playlistitem.h"
#include "settings/behavioursettingspage.h"
@ -48,10 +48,6 @@ class Equalizer;
class GstStartup;
#endif
namespace Engine {
struct SimpleMetaBundle;
} // namespace Engine
class PlayerInterface : public QObject {
Q_OBJECT
@ -59,7 +55,7 @@ class PlayerInterface : public QObject {
explicit PlayerInterface(QObject *parent = nullptr) : QObject(parent) {}
virtual EngineBase *engine() const = 0;
virtual Engine::State GetState() const = 0;
virtual EngineBase::State GetState() const = 0;
virtual uint GetVolume() const = 0;
virtual PlaylistItemPtr GetCurrentItem() const = 0;
@ -74,7 +70,7 @@ class PlayerInterface : public QObject {
virtual void SaveVolume() = 0;
// Manual track change to the specified track
virtual void PlayAt(const int index, const quint64 offset_nanosec, Engine::TrackChangeFlags change, const Playlist::AutoScroll autoscroll, const bool reshuffle, const bool force_inform = false) = 0;
virtual void PlayAt(const int index, const quint64 offset_nanosec, EngineBase::TrackChangeFlags change, const Playlist::AutoScroll autoscroll, const bool reshuffle, const bool force_inform = false) = 0;
// If there's currently a song playing, pause it, otherwise play the track that was playing last, or the first one on the playlist
virtual void PlayPause(const quint64 offset_nanosec = 0, const Playlist::AutoScroll autoscroll = Playlist::AutoScroll::Always) = 0;
@ -138,11 +134,11 @@ class Player : public PlayerInterface {
static const char *kSettingsGroup;
Engine::EngineType CreateEngine(Engine::EngineType enginetype);
EngineBase::Type CreateEngine(EngineBase::Type Type);
void Init();
EngineBase *engine() const override { return engine_.get(); }
Engine::State GetState() const override { return last_state_; }
EngineBase::State GetState() const override { return last_state_; }
uint GetVolume() const override;
PlaylistItemPtr GetCurrentItem() const override { return current_item_; }
@ -163,7 +159,7 @@ class Player : public PlayerInterface {
void LoadVolume() override;
void SaveVolume() override;
void PlayAt(const int index, const quint64 offset_nanosec, Engine::TrackChangeFlags change, const Playlist::AutoScroll autoscroll, const bool reshuffle, const bool force_inform = false) override;
void PlayAt(const int index, const quint64 offset_nanosec, EngineBase::TrackChangeFlags change, const Playlist::AutoScroll autoscroll, const bool reshuffle, const bool force_inform = false) override;
void PlayPause(const quint64 offset_nanosec = 0, const Playlist::AutoScroll autoscroll = Playlist::AutoScroll::Always) override;
void PlayPauseHelper() override { PlayPause(play_offset_nanosec_); }
void RestartOrPrevious() override;
@ -193,19 +189,19 @@ class Player : public PlayerInterface {
void HandleAuthentication();
signals:
void EngineChanged(const Engine::EngineType enginetype);
void EngineChanged(const EngineBase::Type Type);
private slots:
void EngineStateChanged(const Engine::State);
void EngineMetadataReceived(const Engine::SimpleMetaBundle &bundle);
void EngineStateChanged(const EngineBase::State);
void EngineMetadataReceived(const EngineMetadata &engine_metadata);
void TrackAboutToEnd();
void TrackEnded();
// Play the next item on the playlist - disregarding radio stations like last.fm that might have more tracks.
void NextItem(const Engine::TrackChangeFlags change, const Playlist::AutoScroll autoscroll);
void PreviousItem(const Engine::TrackChangeFlags change);
void NextItem(const EngineBase::TrackChangeFlags change, const Playlist::AutoScroll autoscroll);
void PreviousItem(const EngineBase::TrackChangeFlags change);
void NextInternal(const Engine::TrackChangeFlags, const Playlist::AutoScroll autoscroll);
void PlayPlaylistInternal(const Engine::TrackChangeFlags, const Playlist::AutoScroll autoscroll, const QString &playlist_name);
void NextInternal(const EngineBase::TrackChangeFlags, const Playlist::AutoScroll autoscroll);
void PlayPlaylistInternal(const EngineBase::TrackChangeFlags, const Playlist::AutoScroll autoscroll, const QString &playlist_name);
void FatalError();
void ValidSongRequested(const QUrl&);
@ -231,9 +227,9 @@ class Player : public PlayerInterface {
PlaylistItemPtr current_item_;
Engine::TrackChangeFlags stream_change_type_;
EngineBase::TrackChangeFlags stream_change_type_;
Playlist::AutoScroll autoscroll_;
Engine::State last_state_;
EngineBase::State last_state_;
int nb_errors_received_;
QMap<QString, UrlHandler*> url_handlers_;

View File

@ -48,8 +48,7 @@
#include <QStandardPaths>
#include "core/iconloader.h"
#include "engine/enginebase.h"
#include "engine/enginemetadata.h"
#include "utilities/strutils.h"
#include "utilities/timeutils.h"
#include "utilities/coverutils.h"
@ -1386,7 +1385,7 @@ void Song::ToMTP(LIBMTP_track_t *track) const {
}
#endif
bool Song::MergeFromSimpleMetaBundle(const Engine::SimpleMetaBundle &bundle) {
bool Song::MergeFromEngineMetadata(const EngineMetadata &engine_metadata) {
d->valid_ = true;
@ -1394,47 +1393,47 @@ bool Song::MergeFromSimpleMetaBundle(const Engine::SimpleMetaBundle &bundle) {
if (d->init_from_file_ || is_collection_song() || d->url_.isLocalFile()) {
// This Song was already loaded using taglib. Our tags are probably better than the engine's.
if (title() != bundle.title && title().isEmpty() && !bundle.title.isEmpty()) {
set_title(bundle.title);
if (title() != engine_metadata.title && title().isEmpty() && !engine_metadata.title.isEmpty()) {
set_title(engine_metadata.title);
minor = false;
}
if (artist() != bundle.artist && artist().isEmpty() && !bundle.artist.isEmpty()) {
set_artist(bundle.artist);
if (artist() != engine_metadata.artist && artist().isEmpty() && !engine_metadata.artist.isEmpty()) {
set_artist(engine_metadata.artist);
minor = false;
}
if (album() != bundle.album && album().isEmpty() && !bundle.album.isEmpty()) {
set_album(bundle.album);
if (album() != engine_metadata.album && album().isEmpty() && !engine_metadata.album.isEmpty()) {
set_album(engine_metadata.album);
minor = false;
}
if (comment().isEmpty() && !bundle.comment.isEmpty()) set_comment(bundle.comment);
if (genre().isEmpty() && !bundle.genre.isEmpty()) set_genre(bundle.genre);
if (lyrics().isEmpty() && !bundle.lyrics.isEmpty()) set_lyrics(bundle.lyrics);
if (comment().isEmpty() && !engine_metadata.comment.isEmpty()) set_comment(engine_metadata.comment);
if (genre().isEmpty() && !engine_metadata.genre.isEmpty()) set_genre(engine_metadata.genre);
if (lyrics().isEmpty() && !engine_metadata.lyrics.isEmpty()) set_lyrics(engine_metadata.lyrics);
}
else {
if (title() != bundle.title && !bundle.title.isEmpty()) {
set_title(bundle.title);
if (title() != engine_metadata.title && !engine_metadata.title.isEmpty()) {
set_title(engine_metadata.title);
minor = false;
}
if (artist() != bundle.artist && !bundle.artist.isEmpty()) {
set_artist(bundle.artist);
if (artist() != engine_metadata.artist && !engine_metadata.artist.isEmpty()) {
set_artist(engine_metadata.artist);
minor = false;
}
if (album() != bundle.album && !bundle.album.isEmpty()) {
set_album(bundle.album);
if (album() != engine_metadata.album && !engine_metadata.album.isEmpty()) {
set_album(engine_metadata.album);
minor = false;
}
if (!bundle.comment.isEmpty()) set_comment(bundle.comment);
if (!bundle.genre.isEmpty()) set_genre(bundle.genre);
if (!bundle.lyrics.isEmpty()) set_lyrics(bundle.lyrics);
if (!engine_metadata.comment.isEmpty()) set_comment(engine_metadata.comment);
if (!engine_metadata.genre.isEmpty()) set_genre(engine_metadata.genre);
if (!engine_metadata.lyrics.isEmpty()) set_lyrics(engine_metadata.lyrics);
}
if (bundle.length > 0) set_length_nanosec(bundle.length);
if (bundle.year > 0) d->year_ = bundle.year;
if (bundle.track > 0) d->track_ = bundle.track;
if (bundle.filetype != FileType::Unknown) d->filetype_ = bundle.filetype;
if (bundle.samplerate > 0) d->samplerate_ = bundle.samplerate;
if (bundle.bitdepth > 0) d->bitdepth_ = bundle.bitdepth;
if (bundle.bitrate > 0) d->bitrate_ = bundle.bitrate;
if (engine_metadata.length > 0) set_length_nanosec(engine_metadata.length);
if (engine_metadata.year > 0) d->year_ = engine_metadata.year;
if (engine_metadata.track > 0) d->track_ = engine_metadata.track;
if (engine_metadata.filetype != FileType::Unknown) d->filetype_ = engine_metadata.filetype;
if (engine_metadata.samplerate > 0) d->samplerate_ = engine_metadata.samplerate;
if (engine_metadata.bitdepth > 0) d->bitdepth_ = engine_metadata.bitdepth;
if (engine_metadata.bitrate > 0) d->bitrate_ = engine_metadata.bitrate;
return minor;

View File

@ -41,9 +41,7 @@
class SqlQuery;
namespace Engine {
struct SimpleMetaBundle;
} // namespace Engine
class EngineMetadata;
namespace spb {
namespace tagreader {
@ -172,7 +170,7 @@ class Song {
void InitArtManual();
void InitArtAutomatic();
bool MergeFromSimpleMetaBundle(const Engine::SimpleMetaBundle &bundle);
bool MergeFromEngineMetadata(const EngineMetadata &engine_metadata);
#ifdef HAVE_LIBGPOD
void InitFromItdb(_Itdb_Track *track, const QString &prefix);

View File

@ -51,7 +51,6 @@
#include "tagreaderclient.h"
#include "database.h"
#include "sqlrow.h"
#include "engine/enginetype.h"
#include "engine/enginebase.h"
#include "collection/collectionbackend.h"
#include "collection/collectionquery.h"
@ -125,7 +124,7 @@ SongLoader::Result SongLoader::Load(const QUrl &url) {
return Result::Success;
}
if (player_->engine()->type() == Engine::EngineType::GStreamer) {
if (player_->engine()->type() == EngineBase::Type::GStreamer) {
#ifdef HAVE_GSTREAMER
preload_func_ = std::bind(&SongLoader::LoadRemote, this);
return Result::BlockingLoadRequired;
@ -190,7 +189,7 @@ SongLoader::Result SongLoader::LoadLocalPartial(const QString &filename) {
SongLoader::Result SongLoader::LoadAudioCD() {
#if defined(HAVE_AUDIOCD) && defined(HAVE_GSTREAMER)
if (player_->engine()->type() == Engine::EngineType::GStreamer) {
if (player_->engine()->type() == EngineBase::Type::GStreamer) {
CddaSongLoader *cdda_song_loader = new CddaSongLoader(QUrl(), this);
QObject::connect(cdda_song_loader, &CddaSongLoader::SongsDurationLoaded, this, &SongLoader::AudioCDTracksLoadFinishedSlot);
QObject::connect(cdda_song_loader, &CddaSongLoader::SongsMetadataLoaded, this, &SongLoader::AudioCDTracksTagsLoaded);

View File

@ -1,51 +0,0 @@
#ifndef ENGINE_FWD_H
#define ENGINE_FWD_H
#include <QtGlobal>
/// Used by eg engineobserver.h, and thus we reduce header dependencies on enginebase.h
namespace Engine {
struct SimpleMetaBundle;
class Base;
/**
* You should return:
* Playing when playing,
* Paused when paused
* Idle when you still have a URL loaded (ie you have not been told to stop())
* Empty when you have been told to stop(),
* Error when an error occurred and you stopped yourself
*
* It is vital to be Idle just after the track has ended!
*/
enum class State {
Empty,
Idle,
Playing,
Paused,
Error
};
enum TrackChangeType {
// One of:
First = 0x01,
Manual = 0x02,
Auto = 0x04,
Intro = 0x08,
// Any of:
SameAlbum = 0x10
};
Q_DECLARE_FLAGS(TrackChangeFlags, TrackChangeType)
} // namespace Engine
using EngineBase = Engine::Base;
Q_DECLARE_METATYPE(Engine::State)
Q_DECLARE_METATYPE(Engine::TrackChangeType)
#endif // ENGINE_FWD_H

View File

@ -33,14 +33,12 @@
#include "utilities/envutils.h"
#include "utilities/timeconstants.h"
#include "core/networkproxyfactory.h"
#include "engine_fwd.h"
#include "enginebase.h"
#include "settings/backendsettingspage.h"
#include "settings/networkproxysettingspage.h"
Engine::Base::Base(const EngineType type, QObject *parent)
EngineBase::EngineBase(QObject *parent)
: QObject(parent),
type_(type),
volume_control_(true),
volume_(100),
beginning_nanosec_(0),
@ -73,9 +71,40 @@ Engine::Base::Base(const EngineType type, QObject *parent)
strict_ssl_enabled_(false),
about_to_end_emitted_(false) {}
Engine::Base::~Base() = default;
EngineBase::~EngineBase() = default;
bool Engine::Base::Load(const QUrl &media_url, const QUrl &stream_url, const TrackChangeFlags, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec) {
EngineBase::Type EngineBase::TypeFromName(const QString &name) {
if (name.compare("gstreamer", Qt::CaseInsensitive) == 0) return Type::GStreamer;
if (name.compare("vlc", Qt::CaseInsensitive) == 0) return Type::VLC;
return Type::None;
}
QString EngineBase::Name(const Type type) {
switch (type) {
case Type::GStreamer: return QString("gstreamer");
case Type::VLC: return QString("vlc");
case Type::None:
default: return QString("None");
}
}
QString EngineBase::Description(const Type type) {
switch (type) {
case Type::GStreamer: return QString("GStreamer");
case Type::VLC: return QString("VLC");
case Type::None:
default: return QString("None");
}
}
bool EngineBase::Load(const QUrl &media_url, const QUrl &stream_url, const TrackChangeFlags, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec) {
Q_UNUSED(force_stop_at_end);
@ -90,7 +119,7 @@ bool Engine::Base::Load(const QUrl &media_url, const QUrl &stream_url, const Tra
}
bool Engine::Base::Play(const QUrl &media_url, const QUrl &stream_url, const TrackChangeFlags flags, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec, const quint64 offset_nanosec) {
bool EngineBase::Play(const QUrl &media_url, const QUrl &stream_url, const TrackChangeFlags flags, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec, const quint64 offset_nanosec) {
if (!Load(media_url, stream_url, flags, force_stop_at_end, beginning_nanosec, end_nanosec)) {
return false;
@ -100,21 +129,21 @@ bool Engine::Base::Play(const QUrl &media_url, const QUrl &stream_url, const Tra
}
void Engine::Base::UpdateVolume(const uint volume) {
void EngineBase::UpdateVolume(const uint volume) {
volume_ = volume;
emit VolumeChanged(volume);
}
void Engine::Base::SetVolume(const uint volume) {
void EngineBase::SetVolume(const uint volume) {
volume_ = volume;
SetVolumeSW(volume);
}
void Engine::Base::ReloadSettings() {
void EngineBase::ReloadSettings() {
QSettings s;
@ -190,7 +219,7 @@ void Engine::Base::ReloadSettings() {
}
void Engine::Base::EmitAboutToFinish() {
void EngineBase::EmitAboutToFinish() {
if (about_to_end_emitted_) {
return;
@ -202,7 +231,7 @@ void Engine::Base::EmitAboutToFinish() {
}
bool Engine::Base::ValidOutput(const QString &output) {
bool EngineBase::ValidOutput(const QString &output) {
Q_UNUSED(output);

View File

@ -38,25 +38,54 @@
#include <QString>
#include <QUrl>
#include "engine_fwd.h"
#include "enginetype.h"
#include "devicefinders.h"
#include "enginemetadata.h"
#include "core/song.h"
namespace Engine {
struct SimpleMetaBundle;
using Scope = std::vector<int16_t>;
class Base : public QObject {
class EngineBase : public QObject {
Q_OBJECT
protected:
Base(const EngineType type = EngineType::None, QObject *parent = nullptr);
EngineBase(QObject *parent = nullptr);
public:
~Base() override;
~EngineBase() override;
enum class Type {
None,
GStreamer,
VLC,
Xine
};
// State:
// Playing when playing,
// Paused when paused
// Idle when you still have a URL loaded (ie you have not been told to stop())
// Empty when you have been told to stop(),
// Error when an error occurred and you stopped yourself
//
// It is vital to be Idle just after the track has ended!
enum class State {
Empty,
Idle,
Playing,
Paused,
Error
};
enum TrackChangeType {
// One of:
First = 0x01,
Manual = 0x02,
Auto = 0x04,
Intro = 0x08,
// Any of:
SameAlbum = 0x10
};
Q_DECLARE_FLAGS(TrackChangeFlags, TrackChangeType)
struct OutputDetails {
QString name;
@ -65,6 +94,13 @@ class Base : public QObject {
};
using OutputDetailsList = QList<OutputDetails>;
using Scope = std::vector<int16_t>;
static Type TypeFromName(const QString &name);
static QString Name(const Type type);
static QString Description(const Type type);
virtual Type type() const = 0;
virtual bool Init() = 0;
virtual State state() const = 0;
virtual void StartPreloading(const QUrl&, const QUrl&, const bool, const qint64, const qint64) {}
@ -105,9 +141,7 @@ class Base : public QObject {
void EmitAboutToFinish();
public:
// Simple accessors
EngineType type() const { return type_; }
bool volume_control() const { return volume_control_; }
inline uint volume() const { return volume_; }
@ -145,16 +179,15 @@ class Base : public QObject {
// Emitted when Engine successfully started playing a song with the given QUrl.
void ValidSongRequested(const QUrl &url);
void MetaData(const Engine::SimpleMetaBundle &bundle);
void MetaData(const EngineMetadata &metadata);
// Signals that the engine's state has changed (a stream was stopped for example).
// Always use the state from event, because it's not guaranteed that immediate subsequent call to state() won't return a stale value.
void StateChanged(const Engine::State state);
void StateChanged(const State state);
void VolumeChanged(const uint volume);
protected:
EngineType type_;
bool volume_control_;
uint volume_;
quint64 beginning_nanosec_;
@ -208,38 +241,13 @@ class Base : public QObject {
bool strict_ssl_enabled_;
bool about_to_end_emitted_;
Q_DISABLE_COPY(Base)
Q_DISABLE_COPY(EngineBase)
};
struct SimpleMetaBundle {
SimpleMetaBundle() : type(Type::Any), length(-1), year(-1), track(-1), filetype(Song::FileType::Unknown), samplerate(-1), bitdepth(-1), bitrate(-1) {}
enum class Type {
Any,
Current,
Next
};
Type type;
QUrl media_url;
QUrl stream_url;
QString title;
QString artist;
QString album;
QString comment;
QString genre;
qint64 length;
int year;
int track;
Song::FileType filetype;
int samplerate;
int bitdepth;
int bitrate;
QString lyrics;
};
} // namespace Engine
Q_DECLARE_METATYPE(EngineBase::Type);
Q_DECLARE_METATYPE(EngineBase::State)
Q_DECLARE_METATYPE(EngineBase::TrackChangeType)
Q_DECLARE_METATYPE(EngineBase::OutputDetails)
Q_DECLARE_METATYPE(Engine::SimpleMetaBundle)
#endif // ENGINEBASE_H

View File

@ -0,0 +1,31 @@
/*
* Strawberry Music Player
* Copyright 2018-2023, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Strawberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "enginemetadata.h"
#include "core/song.h"
EngineMetadata::EngineMetadata()
: type(Type::Any),
length(-1),
year(-1),
track(-1),
filetype(Song::FileType::Unknown),
samplerate(-1),
bitdepth(-1),
bitrate(-1) {}

View File

@ -0,0 +1,56 @@
/*
* Strawberry Music Player
* Copyright 2018-2023, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Strawberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ENGINEMETADATA_H
#define ENGINEMETADATA_H
#include <QMetaType>
#include <QString>
#include <QUrl>
#include "core/song.h"
class EngineMetadata {
public:
EngineMetadata();
enum class Type {
Any,
Current,
Next
};
Type type;
QUrl media_url;
QUrl stream_url;
QString title;
QString artist;
QString album;
QString comment;
QString genre;
qint64 length;
int year;
int track;
Song::FileType filetype;
int samplerate;
int bitdepth;
int bitrate;
QString lyrics;
};
Q_DECLARE_METATYPE(EngineMetadata)
#endif // ENGINEMETADATA_H

View File

@ -1,54 +0,0 @@
/*
* Strawberry Music Player
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Strawberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include <QString>
#include "enginetype.h"
namespace Engine {
Engine::EngineType EngineTypeFromName(const QString &enginename) {
QString lower = enginename.toLower();
if (lower == "gstreamer") return Engine::EngineType::GStreamer;
else if (lower == "vlc") return Engine::EngineType::VLC;
else return Engine::EngineType::None;
}
QString EngineName(const Engine::EngineType enginetype) {
switch (enginetype) {
case Engine::EngineType::GStreamer: return QString("gstreamer");
case Engine::EngineType::VLC: return QString("vlc");
case Engine::EngineType::None:
default: return QString("None");
}
}
QString EngineDescription(Engine::EngineType enginetype) {
switch (enginetype) {
case Engine::EngineType::GStreamer: return QString("GStreamer");
case Engine::EngineType::VLC: return QString("VLC");
case Engine::EngineType::None:
default: return QString("None");
}
}
} // namespace Engine

View File

@ -1,45 +0,0 @@
/*
* Strawberry Music Player
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Strawberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ENGINETYPE_H
#define ENGINETYPE_H
#include "config.h"
#include <QMetaType>
#include <QString>
namespace Engine {
enum class EngineType {
None,
GStreamer,
VLC,
Xine
};
Engine::EngineType EngineTypeFromName(const QString &enginename);
QString EngineName(const Engine::EngineType enginetype);
QString EngineDescription(const Engine::EngineType enginetype);
} // namespace Engine
Q_DECLARE_METATYPE(Engine::EngineType)
#endif // ENGINETYPE_H

View File

@ -52,10 +52,10 @@
#include "core/signalchecker.h"
#include "utilities/timeconstants.h"
#include "enginebase.h"
#include "enginetype.h"
#include "gstengine.h"
#include "gstenginepipeline.h"
#include "gstbufferconsumer.h"
#include "enginemetadata.h"
const char *GstEngine::kAutoSink = "autoaudiosink";
const char *GstEngine::kALSASink = "alsasink";
@ -75,7 +75,7 @@ const qint64 GstEngine::kPreloadGapNanosec = 8000 * kNsecPerMsec; // 8s
const qint64 GstEngine::kSeekDelayNanosec = 100 * kNsecPerMsec; // 100msec
GstEngine::GstEngine(TaskManager *task_manager, QObject *parent)
: Engine::Base(Engine::EngineType::GStreamer, parent),
: EngineBase(parent),
task_manager_(task_manager),
gst_startup_(nullptr),
discoverer_(nullptr),
@ -138,21 +138,21 @@ bool GstEngine::Init() {
}
Engine::State GstEngine::state() const {
EngineBase::State GstEngine::state() const {
if (!current_pipeline_) return stream_url_.isEmpty() ? Engine::State::Empty : Engine::State::Idle;
if (!current_pipeline_) return stream_url_.isEmpty() ? EngineBase::State::Empty : EngineBase::State::Idle;
switch (current_pipeline_->state()) {
case GST_STATE_NULL:
return Engine::State::Empty;
return EngineBase::State::Empty;
case GST_STATE_READY:
return Engine::State::Idle;
return EngineBase::State::Idle;
case GST_STATE_PLAYING:
return Engine::State::Playing;
return EngineBase::State::Playing;
case GST_STATE_PAUSED:
return Engine::State::Paused;
return EngineBase::State::Paused;
default:
return Engine::State::Empty;
return EngineBase::State::Empty;
}
}
@ -176,21 +176,21 @@ void GstEngine::StartPreloading(const QUrl &media_url, const QUrl &stream_url, c
}
bool GstEngine::Load(const QUrl &media_url, const QUrl &stream_url, const Engine::TrackChangeFlags change, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec) {
bool GstEngine::Load(const QUrl &media_url, const QUrl &stream_url, const EngineBase::TrackChangeFlags change, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec) {
EnsureInitialized();
Engine::Base::Load(stream_url, media_url, change, force_stop_at_end, beginning_nanosec, end_nanosec);
EngineBase::Load(stream_url, media_url, change, force_stop_at_end, beginning_nanosec, end_nanosec);
const QByteArray gst_url = FixupUrl(stream_url);
bool crossfade = current_pipeline_ && ((crossfade_enabled_ && change & Engine::TrackChangeType::Manual) || (autocrossfade_enabled_ && change & Engine::TrackChangeType::Auto) || ((crossfade_enabled_ || autocrossfade_enabled_) && change & Engine::TrackChangeType::Intro));
bool crossfade = current_pipeline_ && ((crossfade_enabled_ && change & EngineBase::TrackChangeType::Manual) || (autocrossfade_enabled_ && change & EngineBase::TrackChangeType::Auto) || ((crossfade_enabled_ || autocrossfade_enabled_) && change & EngineBase::TrackChangeType::Intro));
if (change & Engine::TrackChangeType::Auto && change & Engine::TrackChangeType::SameAlbum && !crossfade_same_album_) {
if (change & EngineBase::TrackChangeType::Auto && change & EngineBase::TrackChangeType::SameAlbum && !crossfade_same_album_) {
crossfade = false;
}
if (!crossfade && current_pipeline_ && current_pipeline_->stream_url() == stream_url && change & Engine::TrackChangeType::Auto) {
if (!crossfade && current_pipeline_ && current_pipeline_->stream_url() == stream_url && change & EngineBase::TrackChangeType::Auto) {
// We're not crossfading, and the pipeline is already playing the URI we want, so just do nothing.
return true;
}
@ -279,7 +279,7 @@ void GstEngine::Stop(const bool stop_after) {
current_pipeline_.reset();
BufferingFinished();
emit StateChanged(Engine::State::Empty);
emit StateChanged(EngineBase::State::Empty);
}
@ -293,7 +293,7 @@ void GstEngine::Pause() {
current_pipeline_->StartFader(fadeout_pause_duration_nanosec_, QTimeLine::Forward, QEasingCurve::InOutQuad, false);
is_fading_out_to_pause_ = false;
has_faded_out_ = false;
emit StateChanged(Engine::State::Playing);
emit StateChanged(EngineBase::State::Playing);
return;
}
@ -303,7 +303,7 @@ void GstEngine::Pause() {
}
else {
current_pipeline_->SetState(GST_STATE_PAUSED);
emit StateChanged(Engine::State::Paused);
emit StateChanged(EngineBase::State::Paused);
StopTimers();
}
}
@ -325,7 +325,7 @@ void GstEngine::Unpause() {
has_faded_out_ = false;
}
emit StateChanged(Engine::State::Playing);
emit StateChanged(EngineBase::State::Playing);
StartTimers();
}
@ -373,7 +373,7 @@ qint64 GstEngine::length_nanosec() const {
}
const Engine::Scope &GstEngine::scope(const int chunk_length) {
const EngineBase::Scope &GstEngine::scope(const int chunk_length) {
// The new buffer could have a different size
if (have_new_buffer_) {
@ -448,7 +448,7 @@ bool GstEngine::ALSADeviceSupport(const QString &output) {
void GstEngine::ReloadSettings() {
Engine::Base::ReloadSettings();
EngineBase::ReloadSettings();
if (output_.isEmpty()) output_ = kAutoSink;
@ -553,7 +553,7 @@ void GstEngine::HandlePipelineError(const int pipeline_id, const int domain, con
current_pipeline_.reset();
BufferingFinished();
emit StateChanged(Engine::State::Error);
emit StateChanged(EngineBase::State::Error);
if (
(domain == static_cast<int>(GST_RESOURCE_ERROR) && (
@ -574,10 +574,10 @@ void GstEngine::HandlePipelineError(const int pipeline_id, const int domain, con
}
void GstEngine::NewMetaData(const int pipeline_id, const Engine::SimpleMetaBundle &bundle) {
void GstEngine::NewMetaData(const int pipeline_id, const EngineMetadata &engine_metadata) {
if (!current_pipeline_|| current_pipeline_->id() != pipeline_id) return;
emit MetaData(bundle);
emit MetaData(engine_metadata);
}
@ -609,7 +609,7 @@ void GstEngine::FadeoutPauseFinished() {
fadeout_pause_pipeline_->SetState(GST_STATE_PAUSED);
current_pipeline_->SetState(GST_STATE_PAUSED);
emit StateChanged(Engine::State::Paused);
emit StateChanged(EngineBase::State::Paused);
StopTimers();
is_fading_out_to_pause_ = false;
@ -664,7 +664,7 @@ void GstEngine::PlayDone(const GstStateChangeReturn ret, const quint64 offset_na
Seek(offset_nanosec);
}
emit StateChanged(Engine::State::Playing);
emit StateChanged(EngineBase::State::Playing);
// We've successfully started playing a media stream with this url
emit ValidSongRequested(stream_url_);
@ -819,7 +819,7 @@ std::shared_ptr<GstEnginePipeline> GstEngine::CreatePipeline(const QUrl &media_u
if (!ret->InitFromUrl(media_url, stream_url, gst_url, end_nanosec, error)) {
ret.reset();
emit Error(error);
emit StateChanged(Engine::State::Error);
emit StateChanged(EngineBase::State::Error);
emit FatalError();
}
@ -829,7 +829,7 @@ std::shared_ptr<GstEnginePipeline> GstEngine::CreatePipeline(const QUrl &media_u
void GstEngine::UpdateScope(const int chunk_length) {
using sample_type = Engine::Scope::value_type;
using sample_type = EngineBase::Scope::value_type;
// Prevent dbz or invalid chunk size
if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_DURATION(latest_buffer_))) return;
@ -858,10 +858,10 @@ void GstEngine::UpdateScope(const int chunk_length) {
// Make sure we don't go beyond the end of the buffer
if (scope_chunk_ == scope_chunks_ - 1) {
bytes = qMin(static_cast<Engine::Scope::size_type>(map.size - (chunk_size * scope_chunk_)), scope_.size() * sizeof(sample_type));
bytes = qMin(static_cast<EngineBase::Scope::size_type>(map.size - (chunk_size * scope_chunk_)), scope_.size() * sizeof(sample_type));
}
else {
bytes = qMin(static_cast<Engine::Scope::size_type>(chunk_size), scope_.size() * sizeof(sample_type));
bytes = qMin(static_cast<EngineBase::Scope::size_type>(chunk_size), scope_.size() * sizeof(sample_type));
}
scope_chunk_++;
@ -908,20 +908,20 @@ void GstEngine::StreamDiscovered(GstDiscoverer*, GstDiscovererInfo *info, GError
GstDiscovererStreamInfo *stream_info = reinterpret_cast<GstDiscovererStreamInfo*>(g_list_first(audio_streams)->data);
Engine::SimpleMetaBundle bundle;
EngineMetadata engine_metadata;
if (discovered_url == instance->current_pipeline_->gst_url()) {
bundle.type = Engine::SimpleMetaBundle::Type::Current;
bundle.media_url = instance->current_pipeline_->media_url();
bundle.stream_url = instance->current_pipeline_->stream_url();
engine_metadata.type = EngineMetadata::Type::Current;
engine_metadata.media_url = instance->current_pipeline_->media_url();
engine_metadata.stream_url = instance->current_pipeline_->stream_url();
}
else if (discovered_url == instance->current_pipeline_->next_gst_url()) {
bundle.type = Engine::SimpleMetaBundle::Type::Next;
bundle.media_url = instance->current_pipeline_->next_media_url();
bundle.stream_url = instance->current_pipeline_->next_stream_url();
engine_metadata.type = EngineMetadata::Type::Next;
engine_metadata.media_url = instance->current_pipeline_->next_media_url();
engine_metadata.stream_url = instance->current_pipeline_->next_stream_url();
}
bundle.samplerate = static_cast<int>(gst_discoverer_audio_info_get_sample_rate(GST_DISCOVERER_AUDIO_INFO(stream_info)));
bundle.bitdepth = static_cast<int>(gst_discoverer_audio_info_get_depth(GST_DISCOVERER_AUDIO_INFO(stream_info)));
bundle.bitrate = static_cast<int>(gst_discoverer_audio_info_get_bitrate(GST_DISCOVERER_AUDIO_INFO(stream_info)) / 1000);
engine_metadata.samplerate = static_cast<int>(gst_discoverer_audio_info_get_sample_rate(GST_DISCOVERER_AUDIO_INFO(stream_info)));
engine_metadata.bitdepth = static_cast<int>(gst_discoverer_audio_info_get_depth(GST_DISCOVERER_AUDIO_INFO(stream_info)));
engine_metadata.bitrate = static_cast<int>(gst_discoverer_audio_info_get_bitrate(GST_DISCOVERER_AUDIO_INFO(stream_info)) / 1000);
GstCaps *caps = gst_discoverer_stream_info_get_caps(stream_info);
@ -931,20 +931,20 @@ void GstEngine::StreamDiscovered(GstDiscoverer*, GstDiscovererInfo *info, GError
if (!gst_structure) continue;
QString mimetype = gst_structure_get_name(gst_structure);
if (!mimetype.isEmpty() && mimetype != "audio/mpeg") {
bundle.filetype = Song::FiletypeByMimetype(mimetype);
if (bundle.filetype == Song::FileType::Unknown) {
engine_metadata.filetype = Song::FiletypeByMimetype(mimetype);
if (engine_metadata.filetype == Song::FileType::Unknown) {
qLog(Error) << "Unknown mimetype" << mimetype;
}
}
}
if (bundle.filetype == Song::FileType::Unknown) {
if (engine_metadata.filetype == Song::FileType::Unknown) {
gchar *codec_description = gst_pb_utils_get_codec_description(caps);
QString filetype_description = (codec_description ? QString(codec_description) : QString());
g_free(codec_description);
if (!filetype_description.isEmpty()) {
bundle.filetype = Song::FiletypeByDescription(filetype_description);
if (bundle.filetype == Song::FileType::Unknown) {
engine_metadata.filetype = Song::FiletypeByDescription(filetype_description);
if (engine_metadata.filetype == Song::FileType::Unknown) {
qLog(Error) << "Unknown filetype" << filetype_description;
}
}
@ -953,9 +953,9 @@ void GstEngine::StreamDiscovered(GstDiscoverer*, GstDiscovererInfo *info, GError
gst_caps_unref(caps);
gst_discoverer_stream_info_list_free(audio_streams);
qLog(Debug) << "Got stream info for" << discovered_url + ":" << Song::TextForFiletype(bundle.filetype);
qLog(Debug) << "Got stream info for" << discovered_url + ":" << Song::TextForFiletype(engine_metadata.filetype);
emit instance->MetaData(bundle);
emit instance->MetaData(engine_metadata);
}
else {

View File

@ -39,7 +39,6 @@
#include <QUrl>
#include "utilities/timeconstants.h"
#include "engine_fwd.h"
#include "enginebase.h"
#include "gststartup.h"
#include "gstbufferconsumer.h"
@ -49,7 +48,7 @@ class QTimerEvent;
class TaskManager;
class GstEnginePipeline;
class GstEngine : public Engine::Base, public GstBufferConsumer {
class GstEngine : public EngineBase, public GstBufferConsumer {
Q_OBJECT
public:
@ -58,10 +57,11 @@ class GstEngine : public Engine::Base, public GstBufferConsumer {
static const char *kAutoSink;
Type type() const override { return Type::GStreamer; }
bool Init() override;
Engine::State state() const override;
EngineBase::State state() const override;
void StartPreloading(const QUrl &media_url, const QUrl &stream_url, const bool force_stop_at_end, const qint64 beginning_nanosec, const qint64 end_nanosec) override;
bool Load(const QUrl &media_url, const QUrl &stream_url, const Engine::TrackChangeFlags change, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec) override;
bool Load(const QUrl &media_url, const QUrl &stream_url, const EngineBase::TrackChangeFlags change, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec) override;
bool Play(const quint64 offset_nanosec) override;
void Stop(const bool stop_after = false) override;
void Pause() override;
@ -74,7 +74,7 @@ class GstEngine : public Engine::Base, public GstBufferConsumer {
public:
qint64 position_nanosec() const override;
qint64 length_nanosec() const override;
const Engine::Scope &scope(const int chunk_length) override;
const EngineBase::Scope &scope(const int chunk_length) override;
OutputDetailsList GetOutputsList() const override;
bool ValidOutput(const QString &output) override;
@ -111,7 +111,7 @@ class GstEngine : public Engine::Base, public GstBufferConsumer {
private slots:
void EndOfStreamReached(const int pipeline_id, const bool has_next_track);
void HandlePipelineError(const int pipeline_id, const int domain, const int error_code, const QString &message, const QString &debugstr);
void NewMetaData(const int pipeline_id, const Engine::SimpleMetaBundle &bundle);
void NewMetaData(const int pipeline_id, const EngineMetadata &engine_metadata);
void AddBufferToScope(GstBuffer *buf, const int pipeline_id, const QString &format);
void FadeoutFinished();
void FadeoutPauseFinished();

View File

@ -1307,24 +1307,24 @@ void GstEnginePipeline::TagMessageReceived(GstMessage *msg) {
GstTagList *taglist = nullptr;
gst_message_parse_tag(msg, &taglist);
Engine::SimpleMetaBundle bundle;
bundle.type = Engine::SimpleMetaBundle::Type::Current;
bundle.media_url = media_url_;
bundle.stream_url = stream_url_;
bundle.title = ParseStrTag(taglist, GST_TAG_TITLE);
bundle.artist = ParseStrTag(taglist, GST_TAG_ARTIST);
bundle.comment = ParseStrTag(taglist, GST_TAG_COMMENT);
bundle.album = ParseStrTag(taglist, GST_TAG_ALBUM);
bundle.bitrate = static_cast<int>(ParseUIntTag(taglist, GST_TAG_BITRATE) / 1000);
bundle.lyrics = ParseStrTag(taglist, GST_TAG_LYRICS);
EngineMetadata engine_metadata;
engine_metadata.type = EngineMetadata::Type::Current;
engine_metadata.media_url = media_url_;
engine_metadata.stream_url = stream_url_;
engine_metadata.title = ParseStrTag(taglist, GST_TAG_TITLE);
engine_metadata.artist = ParseStrTag(taglist, GST_TAG_ARTIST);
engine_metadata.comment = ParseStrTag(taglist, GST_TAG_COMMENT);
engine_metadata.album = ParseStrTag(taglist, GST_TAG_ALBUM);
engine_metadata.bitrate = static_cast<int>(ParseUIntTag(taglist, GST_TAG_BITRATE) / 1000);
engine_metadata.lyrics = ParseStrTag(taglist, GST_TAG_LYRICS);
if (!bundle.title.isEmpty() && bundle.artist.isEmpty() && bundle.album.isEmpty()) {
if (!engine_metadata.title.isEmpty() && engine_metadata.artist.isEmpty() && engine_metadata.album.isEmpty()) {
QStringList title_splitted;
if (bundle.title.contains(" - ")) {
title_splitted = bundle.title.split(" - ");
if (engine_metadata.title.contains(" - ")) {
title_splitted = engine_metadata.title.split(" - ");
}
else if (bundle.title.contains('~')) {
title_splitted = bundle.title.split('~');
else if (engine_metadata.title.contains('~')) {
title_splitted = engine_metadata.title.split('~');
}
if (!title_splitted.isEmpty() && title_splitted.count() >= 2) {
int i = 0;
@ -1332,13 +1332,13 @@ void GstEnginePipeline::TagMessageReceived(GstMessage *msg) {
++i;
switch (i) {
case 1:
bundle.artist = title_part.trimmed();
engine_metadata.artist = title_part.trimmed();
break;
case 2:
bundle.title = title_part.trimmed();
engine_metadata.title = title_part.trimmed();
break;
case 3:
bundle.album = title_part.trimmed();
engine_metadata.album = title_part.trimmed();
break;
default:
break;
@ -1349,7 +1349,7 @@ void GstEnginePipeline::TagMessageReceived(GstMessage *msg) {
gst_tag_list_unref(taglist);
emit MetadataFound(id(), bundle);
emit MetadataFound(id(), engine_metadata);
}

View File

@ -44,12 +44,10 @@
#include <QString>
#include <QUrl>
#include "enginemetadata.h"
class QTimerEvent;
class GstBufferConsumer;
namespace Engine {
struct SimpleMetaBundle;
} // namespace Engine
struct GstPlayBin;
class GstEnginePipeline : public QObject {
@ -132,7 +130,7 @@ class GstEnginePipeline : public QObject {
void Error(const int pipeline_id, const int domain, const int error_code, const QString &message, const QString &debug);
void EndOfStreamReached(const int pipeline_id, const bool has_next_track);
void MetadataFound(const int pipeline_id, const Engine::SimpleMetaBundle &bundle);
void MetadataFound(const int pipeline_id, const EngineMetadata &bundle);
void VolumeChanged(const uint volume);
void FaderFinished();

View File

@ -32,17 +32,15 @@
#include "core/taskmanager.h"
#include "core/logging.h"
#include "utilities/timeconstants.h"
#include "engine_fwd.h"
#include "enginebase.h"
#include "enginetype.h"
#include "vlcengine.h"
#include "vlcscopedref.h"
VLCEngine::VLCEngine(TaskManager *task_manager, QObject *parent)
: Engine::Base(Engine::EngineType::VLC, parent),
: EngineBase(parent),
instance_(nullptr),
player_(nullptr),
state_(Engine::State::Empty) {
state_(State::Empty) {
Q_UNUSED(task_manager);
@ -52,7 +50,7 @@ VLCEngine::VLCEngine(TaskManager *task_manager, QObject *parent)
VLCEngine::~VLCEngine() {
if (state_ == Engine::State::Playing || state_ == Engine::State::Paused) {
if (state_ == State::Playing || state_ == State::Paused) {
libvlc_media_player_stop(player_);
}
@ -100,7 +98,7 @@ bool VLCEngine::Init() {
}
bool VLCEngine::Load(const QUrl &media_url, const QUrl &stream_url, const Engine::TrackChangeFlags change, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec) {
bool VLCEngine::Load(const QUrl &media_url, const QUrl &stream_url, const EngineBase::TrackChangeFlags change, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec) {
Q_UNUSED(media_url);
Q_UNUSED(change);
@ -197,7 +195,7 @@ void VLCEngine::SetVolumeSW(const uint percent) {
qint64 VLCEngine::position_nanosec() const {
if (state_ == Engine::State::Empty) return 0;
if (state_ == State::Empty) return 0;
const qint64 result = (position() * kNsecPerMsec);
return qMax(0LL, result);
@ -205,7 +203,7 @@ qint64 VLCEngine::position_nanosec() const {
qint64 VLCEngine::length_nanosec() const {
if (state_ == Engine::State::Empty) return 0;
if (state_ == State::Empty) return 0;
const qint64 result = (end_nanosec_ - static_cast<qint64>(beginning_nanosec_));
if (result > 0) {
return result;
@ -297,32 +295,32 @@ void VLCEngine::StateChangedCallback(const libvlc_event_t *e, void *data) {
break;
case libvlc_MediaPlayerStopped:{
const Engine::State state = engine->state_;
engine->state_ = Engine::State::Empty;
if (state == Engine::State::Playing) {
const EngineBase::State state = engine->state_;
engine->state_ = EngineBase::State::Empty;
if (state == EngineBase::State::Playing) {
emit engine->StateChanged(engine->state_);
}
break;
}
case libvlc_MediaPlayerEncounteredError:
engine->state_ = Engine::State::Error;
engine->state_ = EngineBase::State::Error;
emit engine->StateChanged(engine->state_);
emit engine->FatalError();
break;
case libvlc_MediaPlayerPlaying:
engine->state_ = Engine::State::Playing;
engine->state_ = EngineBase::State::Playing;
emit engine->StateChanged(engine->state_);
break;
case libvlc_MediaPlayerPaused:
engine->state_ = Engine::State::Paused;
engine->state_ = EngineBase::State::Paused;
emit engine->StateChanged(engine->state_);
break;
case libvlc_MediaPlayerEndReached:
engine->state_ = Engine::State::Idle;
engine->state_ = EngineBase::State::Idle;
emit engine->TrackEnded();
break;
}

View File

@ -31,23 +31,23 @@
#include <QString>
#include <QUrl>
#include "engine_fwd.h"
#include "enginebase.h"
struct libvlc_event_t;
class TaskManager;
class VLCEngine : public Engine::Base {
class VLCEngine : public EngineBase {
Q_OBJECT
public:
explicit VLCEngine(TaskManager *task_manager, QObject *parent = nullptr);
~VLCEngine() override;
Type type() const override { return Type::VLC; }
bool Init() override;
Engine::State state() const override { return state_; }
bool Load(const QUrl &media_url, const QUrl &stream_url, const Engine::TrackChangeFlags change, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec) override;
EngineBase::State state() const override { return state_; }
bool Load(const QUrl &media_url, const QUrl &stream_url, const EngineBase::TrackChangeFlags change, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec) override;
bool Play(const quint64 offset_nanosec) override;
void Stop(const bool stop_after = false) override;
void Pause() override;
@ -70,7 +70,7 @@ class VLCEngine : public Engine::Base {
private:
libvlc_instance_t *instance_;
libvlc_media_player_t *player_;
Engine::State state_;
State state_;
bool Initialized() const { return (instance_ && player_); }
uint position() const;

View File

@ -22,7 +22,7 @@
#include "core/application.h"
#include "core/player.h"
#include "core/song.h"
#include "engine/engine_fwd.h"
#include "engine/enginebase.h"
#include "settings/moodbarsettingspage.h"
#include "playlist/playlistmanager.h"
@ -94,9 +94,9 @@ void MoodbarController::AsyncLoadComplete(MoodbarPipeline *pipeline, const QUrl
}
// Did we stop the song?
switch (app_->player()->GetState()) {
case Engine::State::Error:
case Engine::State::Empty:
case Engine::State::Idle:
case EngineBase::State::Error:
case EngineBase::State::Empty:
case EngineBase::State::Idle:
return;
default:

View File

@ -43,10 +43,8 @@
#include "core/iconloader.h"
#include "core/player.h"
#include "core/logging.h"
#include "engine/engine_fwd.h"
#include "engine/enginebase.h"
#include "engine/devicefinders.h"
#include "engine/enginetype.h"
#include "engine/devicefinder.h"
#include "widgets/lineedit.h"
#include "widgets/stickyslider.h"
@ -67,7 +65,7 @@ BackendSettingsPage::BackendSettingsPage(SettingsDialog *dialog, QWidget *parent
ui_(new Ui_BackendSettingsPage),
configloaded_(false),
engineloaded_(false),
enginetype_current_(Engine::EngineType::None) {
enginetype_current_(EngineBase::Type::None) {
ui_->setupUi(this);
setWindowIcon(IconLoader::Load("soundcard", true, 0, 32));
@ -113,15 +111,15 @@ void BackendSettingsPage::Load() {
QSettings s;
s.beginGroup(kSettingsGroup);
Engine::EngineType enginetype = Engine::EngineTypeFromName(s.value("engine", EngineName(Engine::EngineType::None)).toString());
if (enginetype == Engine::EngineType::None && engine()) enginetype = engine()->type();
EngineBase::Type enginetype = EngineBase::TypeFromName(s.value("engine", EngineBase::Name(EngineBase::Type::None)).toString());
if (enginetype == EngineBase::Type::None && engine()) enginetype = engine()->type();
ui_->combobox_engine->clear();
#ifdef HAVE_GSTREAMER
ui_->combobox_engine->addItem(IconLoader::Load("gstreamer"), EngineDescription(Engine::EngineType::GStreamer), static_cast<int>(Engine::EngineType::GStreamer));
ui_->combobox_engine->addItem(IconLoader::Load("gstreamer"), EngineBase::Description(EngineBase::Type::GStreamer), static_cast<int>(EngineBase::Type::GStreamer));
#endif
#ifdef HAVE_VLC
ui_->combobox_engine->addItem(IconLoader::Load("vlc"), EngineDescription(Engine::EngineType::VLC), static_cast<int>(Engine::EngineType::VLC));
ui_->combobox_engine->addItem(IconLoader::Load("vlc"), EngineBase::Description(EngineBase::Type::VLC), static_cast<int>(EngineBase::Type::VLC));
#endif
enginetype_current_ = enginetype;
@ -189,7 +187,7 @@ void BackendSettingsPage::Load() {
if (!EngineInitialized()) return;
if (engine()->state() == Engine::State::Empty) {
if (engine()->state() == EngineBase::State::Empty) {
if (ui_->combobox_engine->count() > 1) ui_->combobox_engine->setEnabled(true);
else ui_->combobox_engine->setEnabled(false);
}
@ -208,7 +206,7 @@ void BackendSettingsPage::Load() {
// Check if engine, output or device is set to a different setting than the configured to force saving settings.
enginetype = ui_->combobox_engine->itemData(ui_->combobox_engine->currentIndex()).value<Engine::EngineType>();
enginetype = ui_->combobox_engine->itemData(ui_->combobox_engine->currentIndex()).value<EngineBase::Type>();
QString output_name;
if (ui_->combobox_output->currentText().isEmpty()) {
output_name = engine()->DefaultOutput();
@ -232,7 +230,7 @@ void BackendSettingsPage::Load() {
bool BackendSettingsPage::EngineInitialized() {
if (!engine() || engine()->type() == Engine::EngineType::None) {
if (!engine() || engine()->type() == EngineBase::Type::None) {
errordialog_.ShowMessage("Engine is not initialized! Please restart.");
return false;
}
@ -240,7 +238,7 @@ bool BackendSettingsPage::EngineInitialized() {
}
void BackendSettingsPage::Load_Engine(const Engine::EngineType enginetype) {
void BackendSettingsPage::Load_Engine(const EngineBase::Type enginetype) {
if (!EngineInitialized()) return;
@ -260,7 +258,7 @@ void BackendSettingsPage::Load_Engine(const Engine::EngineType enginetype) {
if (engine()->type() != enginetype) {
qLog(Debug) << "Switching engine.";
Engine::EngineType new_enginetype = dialog()->app()->player()->CreateEngine(enginetype);
EngineBase::Type new_enginetype = dialog()->app()->player()->CreateEngine(enginetype);
dialog()->app()->player()->Init();
if (new_enginetype != enginetype) {
ui_->combobox_engine->setCurrentIndex(ui_->combobox_engine->findData(static_cast<int>(engine()->type())));
@ -307,7 +305,7 @@ void BackendSettingsPage::Load_Output(QString output, QVariant device) {
}
}
if (engine()->type() == Engine::EngineType::GStreamer) {
if (engine()->type() == EngineBase::Type::GStreamer) {
ui_->groupbox_buffer->setEnabled(true);
ui_->groupbox_replaygain->setEnabled(true);
}
@ -333,7 +331,7 @@ void BackendSettingsPage::Load_Device(const QString &output, const QVariant &dev
ui_->lineedit_device->clear();
#ifdef Q_OS_WIN
if (engine()->type() != Engine::EngineType::GStreamer)
if (engine()->type() != EngineBase::Type::GStreamer)
#endif
ui_->combobox_device->addItem(IconLoader::Load("soundcard"), kOutputAutomaticallySelect, QVariant());
@ -436,7 +434,7 @@ void BackendSettingsPage::Save() {
if (!EngineInitialized()) return;
QVariant enginetype_v = ui_->combobox_engine->itemData(ui_->combobox_engine->currentIndex());
Engine::EngineType enginetype = enginetype_v.value<Engine::EngineType>();
EngineBase::Type enginetype = enginetype_v.value<EngineBase::Type>();
QString output_name;
QVariant device_value;
@ -455,7 +453,7 @@ void BackendSettingsPage::Save() {
QSettings s;
s.beginGroup(kSettingsGroup);
s.setValue("engine", EngineName(enginetype));
s.setValue("engine", EngineBase::Name(enginetype));
s.setValue("output", output_name);
s.setValue("device", device_value);
@ -512,11 +510,11 @@ void BackendSettingsPage::EngineChanged(const int index) {
if (!configloaded_ || !EngineInitialized()) return;
QVariant v = ui_->combobox_engine->itemData(index);
Engine::EngineType enginetype = v.value<Engine::EngineType>();
EngineBase::Type enginetype = v.value<EngineBase::Type>();
if (engine()->type() == enginetype) return;
if (engine()->state() != Engine::State::Empty) {
if (engine()->state() != EngineBase::State::Empty) {
errordialog_.ShowMessage("Can't switch engine while playing!");
ui_->combobox_engine->setCurrentIndex(ui_->combobox_engine->findData(static_cast<int>(engine()->type())));
return;
@ -797,7 +795,7 @@ void BackendSettingsPage::FadingOptionsChanged() {
if (!configloaded_ || !EngineInitialized()) return;
EngineBase::OutputDetails output = ui_->combobox_output->itemData(ui_->combobox_output->currentIndex()).value<EngineBase::OutputDetails>();
if (engine()->type() == Engine::EngineType::GStreamer &&
if (engine()->type() == EngineBase::Type::GStreamer &&
!(engine()->ALSADeviceSupport(output.name) && !ui_->lineedit_device->text().isEmpty() && (ui_->lineedit_device->text().contains(QRegularExpression("^hw:.*")) || ui_->lineedit_device->text().contains(QRegularExpression("^plughw:.*"))))) {
ui_->groupbox_fading->setEnabled(true);
}

View File

@ -26,13 +26,11 @@
#include <QVariant>
#include <QString>
#include "engine/enginetype.h"
#include "dialogs/errordialog.h"
#include "settingspage.h"
#include "core/application.h"
#include "core/player.h"
#include "engine/engine_fwd.h"
#include "engine/enginebase.h"
#include "dialogs/errordialog.h"
#include "settingspage.h"
class SettingsDialog;
class Ui_BackendSettingsPage;
@ -80,7 +78,7 @@ class BackendSettingsPage : public SettingsPage {
bool EngineInitialized();
void Load_Engine(Engine::EngineType enginetype);
void Load_Engine(const EngineBase::Type enginetype);
void Load_Output(QString output, QVariant device);
void Load_Device(const QString &output, const QVariant &device);
#ifdef HAVE_ALSA
@ -97,7 +95,7 @@ class BackendSettingsPage : public SettingsPage {
bool engineloaded_;
ErrorDialog errordialog_;
Engine::EngineType enginetype_current_;
EngineBase::Type enginetype_current_;
QString output_current_;
QVariant device_current_;

View File

@ -34,7 +34,7 @@
#include <QString>
#include <QSettings>
#include "engine/engine_fwd.h"
#include "engine/enginebase.h"
#include "osd/osdbase.h"
class QMainWindow;