More engine fixes
This commit is contained in:
parent
67df8f2243
commit
04f1d296ea
@ -19,6 +19,9 @@
|
||||
project(strawberry)
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
if(${CMAKE_VERSION} VERSION_GREATER "3.10.3")
|
||||
cmake_policy(SET CMP0072 NEW)
|
||||
endif()
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckIncludeFiles)
|
||||
|
17
dist/maketarball.sh.in
vendored
17
dist/maketarball.sh.in
vendored
@ -2,19 +2,26 @@
|
||||
|
||||
name=strawberry
|
||||
version="@STRAWBERRY_VERSION_PACKAGE@"
|
||||
gitrev="@INCLUDE_GIT_REVISION@"
|
||||
root=$(cd "${0%/*}/.." && echo $PWD/${0##*/})
|
||||
root=`dirname "$root"`
|
||||
rootnoslash=`echo $root | sed "s/^\///"`
|
||||
|
||||
if ! [ "$gitrev" = "ON" ]; then
|
||||
exclude_vcs="--exclude-vcs"
|
||||
fi
|
||||
|
||||
echo "Creating $name-$version.tar.xz..."
|
||||
|
||||
rm -f "$name-$version.tar.xz"
|
||||
tar -cJf $name-$version.tar.xz \
|
||||
--transform "s,^$rootnoslash,$name-$version," \
|
||||
--exclude-vcs \
|
||||
--exclude "$root/dist/*.tar" \
|
||||
--exclude "$root/dist/*.tar.*" \
|
||||
--transform "s,^$rootnoslash,$name-$version," $exclude_vcs \
|
||||
--exclude "*.tar" \
|
||||
--exclude "*.tar.*" \
|
||||
--exclude "*.bz" \
|
||||
--exclude "*.bz2" \
|
||||
--exclude "*.xz" \
|
||||
--exclude ".directory" \
|
||||
--exclude "$root/CMakeLists.txt.user" \
|
||||
--exclude "$root/build" \
|
||||
--exclude ".directory" \
|
||||
"$root"
|
||||
|
@ -81,8 +81,7 @@ Player::Player(Application *app, QObject *parent)
|
||||
volume_before_mute_(50),
|
||||
last_pressed_previous_(QDateTime::currentDateTime()),
|
||||
menu_previousmode_(PreviousBehaviour_DontRestart),
|
||||
seek_step_sec_(10)
|
||||
{
|
||||
seek_step_sec_(10) {
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(BackendSettingsPage::kSettingsGroup);
|
||||
@ -90,103 +89,86 @@ Player::Player(Application *app, QObject *parent)
|
||||
s.endGroup();
|
||||
|
||||
CreateEngine(enginetype);
|
||||
|
||||
settings_.beginGroup("Player");
|
||||
|
||||
SetVolume(settings_.value("volume", 100).toInt());
|
||||
|
||||
#if 0
|
||||
connect(engine_.get(), SIGNAL(Error(QString)), SIGNAL(Error(QString)));
|
||||
connect(engine_.get(), SIGNAL(ValidSongRequested(QUrl)), SLOT(ValidSongRequested(QUrl)));
|
||||
connect(engine_.get(), SIGNAL(InvalidSongRequested(QUrl)), SLOT(InvalidSongRequested(QUrl)));
|
||||
#endif
|
||||
int volume = settings_.value("volume", 50).toInt();
|
||||
SetVolume(volume);
|
||||
|
||||
}
|
||||
|
||||
Player::~Player() {}
|
||||
Player::~Player() {
|
||||
settings_.endGroup();
|
||||
}
|
||||
|
||||
EngineBase *Player::CreateEngine(Engine::EngineType enginetype) {
|
||||
|
||||
bool engine = false;
|
||||
EngineBase *enginebase = nullptr;
|
||||
void Player::CreateEngine(Engine::EngineType enginetype) {
|
||||
|
||||
for (int i = 1 ; !engine ; i++) {
|
||||
Engine::EngineType use_enginetype = Engine::None;
|
||||
|
||||
for (int i = 0 ; use_enginetype == Engine::None ; i++) {
|
||||
switch(enginetype) {
|
||||
case Engine::None:
|
||||
#ifdef HAVE_GSTREAMER
|
||||
case Engine::GStreamer:
|
||||
engine=true;
|
||||
enginetype=Engine::GStreamer;
|
||||
enginebase = new GstEngine(app_->task_manager());
|
||||
use_enginetype=Engine::GStreamer;
|
||||
engine_.reset(new GstEngine(app_->task_manager()));
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_XINE
|
||||
case Engine::Xine:
|
||||
engine=true;
|
||||
enginetype=Engine::Xine;
|
||||
enginebase = new XineEngine(app_->task_manager());
|
||||
use_enginetype=Engine::Xine;
|
||||
engine_.reset(new XineEngine(app_->task_manager()));
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_VLC
|
||||
case Engine::VLC:
|
||||
engine=true;
|
||||
enginetype=Engine::VLC;
|
||||
enginebase = new VLCEngine(app_->task_manager());
|
||||
use_enginetype=Engine::VLC;
|
||||
engine_.reset(new VLCEngine(app_->task_manager()));
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_PHONON
|
||||
case Engine::Phonon:
|
||||
engine=true;
|
||||
enginetype=Engine::Phonon;
|
||||
enginebase = new PhononEngine(app_->task_manager());
|
||||
use_enginetype=Engine::Phonon;
|
||||
engine_.reset(new PhononEngine(app_->task_manager()));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
if (i > 1) { qFatal("No engine available!"); return nullptr; }
|
||||
QSettings s;
|
||||
s.beginGroup(BackendSettingsPage::kSettingsGroup);
|
||||
s.setValue("engine", "");
|
||||
s.setValue("output", "");
|
||||
s.setValue("device", QVariant(""));
|
||||
s.endGroup();
|
||||
enginetype = Engine::None;
|
||||
break;
|
||||
if (i > 0) { qFatal("No engine available!"); }
|
||||
enginetype = Engine::None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(BackendSettingsPage::kSettingsGroup);
|
||||
s.setValue("engine", Engine::EngineName(enginetype));
|
||||
s.endGroup();
|
||||
|
||||
if (enginebase == nullptr) {
|
||||
qFatal("Failed to create engine!");
|
||||
return nullptr;
|
||||
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("output", engine_->DefaultOutput());
|
||||
s.setValue("device", QVariant(""));
|
||||
s.endGroup();
|
||||
}
|
||||
|
||||
engine_.reset(enginebase);
|
||||
|
||||
return enginebase;
|
||||
if (!engine_) {
|
||||
qFatal("Failed to create engine!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Player::Init() {
|
||||
|
||||
if (!engine_->Init()) { qFatal("Error initialising audio engine"); }
|
||||
|
||||
analyzer_->SetEngine(engine_.get());
|
||||
|
||||
connect(engine_.get(), SIGNAL(Error(QString)), SIGNAL(Error(QString)));
|
||||
connect(engine_.get(), SIGNAL(ValidSongRequested(QUrl)), SLOT(ValidSongRequested(QUrl)));
|
||||
connect(engine_.get(), SIGNAL(InvalidSongRequested(QUrl)), SLOT(InvalidSongRequested(QUrl)));
|
||||
|
||||
if (!engine_->Init()) qFatal("Error initialising audio engine");
|
||||
|
||||
connect(engine_.get(), SIGNAL(StateChanged(Engine::State)), SLOT(EngineStateChanged(Engine::State)));
|
||||
connect(engine_.get(), SIGNAL(TrackAboutToEnd()), SLOT(TrackAboutToEnd()));
|
||||
connect(engine_.get(), SIGNAL(TrackEnded()), SLOT(TrackEnded()));
|
||||
connect(engine_.get(), SIGNAL(MetaData(Engine::SimpleMetaBundle)), SLOT(EngineMetadataReceived(Engine::SimpleMetaBundle)));
|
||||
|
||||
engine_->SetVolume(settings_.value("volume", 50).toInt());
|
||||
|
||||
analyzer_->SetEngine(engine_.get());
|
||||
int volume = settings_.value("volume", 50).toInt();
|
||||
engine_->SetVolume(volume);
|
||||
|
||||
// Equalizer
|
||||
qLog(Debug) << "Creating equalizer";
|
||||
@ -195,7 +177,6 @@ void Player::Init() {
|
||||
connect(equalizer_, SIGNAL(StereoBalanceChanged(float)), app_->player()->engine(), SLOT(SetStereoBalance(float)));
|
||||
|
||||
engine_->SetEqualizerEnabled(equalizer_->is_enabled());
|
||||
|
||||
engine_->SetEqualizerParameters(equalizer_->preamp_value(), equalizer_->gain_values());
|
||||
engine_->SetStereoBalance(equalizer_->stereo_balance());
|
||||
|
||||
@ -203,15 +184,6 @@ void Player::Init() {
|
||||
|
||||
}
|
||||
|
||||
void Player::SetAnalyzer(AnalyzerContainer *analyzer) {
|
||||
|
||||
analyzer_ = analyzer;
|
||||
|
||||
}
|
||||
void Player::SetEqualizer(Equalizer *equalizer) {
|
||||
equalizer_ = equalizer;
|
||||
}
|
||||
|
||||
void Player::ReloadSettings() {
|
||||
|
||||
QSettings s;
|
||||
@ -224,7 +196,7 @@ void Player::ReloadSettings() {
|
||||
seek_step_sec_ = s.value("seek_step_sec", 10).toInt();
|
||||
s.endGroup();
|
||||
|
||||
if (engine_.get()) engine_->ReloadSettings();
|
||||
engine_->ReloadSettings();
|
||||
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,7 @@ class Player : public PlayerInterface {
|
||||
PreviousBehaviour_Restart = 2
|
||||
};
|
||||
|
||||
EngineBase *CreateEngine(Engine::EngineType enginetype);
|
||||
void CreateEngine(Engine::EngineType enginetype);
|
||||
void Init();
|
||||
|
||||
EngineBase *engine() const { return engine_.get(); }
|
||||
@ -145,9 +145,9 @@ class Player : public PlayerInterface {
|
||||
const UrlHandler *HandlerForUrl(const QUrl &url) const;
|
||||
|
||||
bool PreviousWouldRestartTrack() const;
|
||||
|
||||
void SetAnalyzer(AnalyzerContainer *analyzer);
|
||||
void SetEqualizer(Equalizer *equalizer);
|
||||
|
||||
void SetAnalyzer(AnalyzerContainer *analyzer) { analyzer_ = analyzer; }
|
||||
void SetEqualizer(Equalizer *equalizer) { equalizer_ = equalizer; }
|
||||
|
||||
public slots:
|
||||
void ReloadSettings();
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include "core/logging.h"
|
||||
|
||||
DirectSoundDeviceFinder::DirectSoundDeviceFinder()
|
||||
: DeviceFinder("directsound", { "directsound", "dsound", "directsoundsink" }) {
|
||||
: DeviceFinder("directsound", { "directsound", "dsound", "directsoundsink", "directx", "directx2" }) {
|
||||
}
|
||||
|
||||
QList<DeviceFinder::Device> DirectSoundDeviceFinder::ListDevices() {
|
||||
|
@ -84,7 +84,6 @@ bool Engine::Base::Play(const QUrl &url, TrackChangeFlags flags, bool force_stop
|
||||
void Engine::Base::SetVolume(uint value) {
|
||||
|
||||
volume_ = value;
|
||||
|
||||
SetVolumeSW(MakeVolumeLogarithmic(value));
|
||||
|
||||
}
|
||||
@ -132,3 +131,9 @@ void Engine::Base::EmitAboutToEnd() {
|
||||
about_to_end_emitted_ = true;
|
||||
emit TrackAboutToEnd();
|
||||
}
|
||||
|
||||
bool Engine::Base::ValidOutput(const QString &output) {
|
||||
|
||||
return (true);
|
||||
|
||||
}
|
||||
|
@ -89,8 +89,9 @@ public:
|
||||
}
|
||||
|
||||
virtual OutputDetailsList GetOutputsList() const = 0;
|
||||
virtual bool ValidOutput(const QString &output) = 0;
|
||||
virtual QString DefaultOutput() = 0;
|
||||
virtual bool CustomDeviceSupport(const QString &name) = 0;
|
||||
virtual bool CustomDeviceSupport(const QString &output) = 0;
|
||||
|
||||
// Plays a media stream represented with the URL 'u' from the given 'beginning' to the given 'end' (usually from 0 to a song's length).
|
||||
// Both markers should be passed in nanoseconds. 'end' can be negative, indicating that the real length of 'u' stream is unknown.
|
||||
|
@ -99,6 +99,7 @@ GstEngine::GstEngine(TaskManager *task_manager)
|
||||
scope_chunk_(0),
|
||||
have_new_buffer_(false) {
|
||||
|
||||
type_ = Engine::GStreamer;
|
||||
seek_timer_->setSingleShot(true);
|
||||
seek_timer_->setInterval(kSeekDelayNanosec / kNsecPerMsec);
|
||||
connect(seek_timer_, SIGNAL(timeout()), SLOT(SeekNow()));
|
||||
@ -129,7 +130,6 @@ bool GstEngine::Init() {
|
||||
|
||||
SetEnvironment();
|
||||
|
||||
type_ = Engine::GStreamer;
|
||||
initialising_ = QtConcurrent::run(this, &GstEngine::InitialiseGStreamer);
|
||||
return true;
|
||||
|
||||
@ -388,8 +388,19 @@ EngineBase::OutputDetailsList GstEngine::GetOutputsList() const {
|
||||
|
||||
}
|
||||
|
||||
bool GstEngine::CustomDeviceSupport(const QString &name) {
|
||||
return (name == kALSASink || name == kOpenALSASink || name == kOSSSink || name == kOSS4Sink || name == kPulseSink || name == kA2DPSink || name == kAVDTPSink);
|
||||
bool GstEngine::ValidOutput(const QString &output) {
|
||||
|
||||
PluginDetailsList plugins = GetPluginList("Sink/Audio");
|
||||
for (const PluginDetails &plugin : plugins) {
|
||||
if (plugin.name == output) return(true);
|
||||
}
|
||||
return(false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool GstEngine::CustomDeviceSupport(const QString &output) {
|
||||
return (output == kALSASink || output == kOpenALSASink || output == kOSSSink || output == kOSS4Sink || output == kPulseSink || output == kA2DPSink || output == kAVDTPSink);
|
||||
}
|
||||
|
||||
void GstEngine::ReloadSettings() {
|
||||
|
@ -84,8 +84,9 @@ class GstEngine : public Engine::Base, public GstBufferConsumer {
|
||||
const Engine::Scope &scope(int chunk_length);
|
||||
|
||||
OutputDetailsList GetOutputsList() const;
|
||||
bool ValidOutput(const QString &output);
|
||||
QString DefaultOutput() { return kAutoSink; }
|
||||
bool CustomDeviceSupport(const QString &name);
|
||||
bool CustomDeviceSupport(const QString &output);
|
||||
|
||||
void EnsureInitialised() { initialising_.waitForFinished(); }
|
||||
void InitialiseGStreamer();
|
||||
@ -132,7 +133,6 @@ class GstEngine : public Engine::Base, public GstBufferConsumer {
|
||||
void BufferingFinished();
|
||||
|
||||
private:
|
||||
|
||||
static const char *kAutoSink;
|
||||
static const char *kALSASink;
|
||||
static const char *kOpenALSASink;
|
||||
|
@ -32,11 +32,13 @@
|
||||
#include "core/logging.h"
|
||||
|
||||
PhononEngine::PhononEngine(TaskManager *task_manager)
|
||||
: media_object_(new Phonon::MediaObject(this)),
|
||||
: EngineBase(),
|
||||
media_object_(new Phonon::MediaObject(this)),
|
||||
audio_output_(new Phonon::AudioOutput(Phonon::MusicCategory, this)),
|
||||
state_timer_(new QTimer(this)),
|
||||
seek_offset_(-1)
|
||||
{
|
||||
seek_offset_(-1) {
|
||||
|
||||
type_ = Engine::Phonon;
|
||||
|
||||
Phonon::createPath(media_object_, audio_output_);
|
||||
|
||||
@ -54,8 +56,6 @@ PhononEngine::~PhononEngine() {
|
||||
}
|
||||
|
||||
bool PhononEngine::Init() {
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
type_ = Engine::Phonon;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -179,6 +179,13 @@ EngineBase::OutputDetailsList PhononEngine::GetOutputsList() const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool PhononEngine::CustomDeviceSupport(const QString &name) {
|
||||
bool PhononEngine::ValidOutput(const QString &output) {
|
||||
|
||||
return (output == "auto" || output == "" || output == DefaultOutput);
|
||||
return(false);
|
||||
|
||||
}
|
||||
|
||||
bool PhononEngine::CustomDeviceSupport(const QString &output) {
|
||||
return false;
|
||||
}
|
||||
|
@ -64,7 +64,8 @@ class PhononEngine : public Engine::Base {
|
||||
qint64 length_nanosec() const;
|
||||
|
||||
QString DefaultOutput() { return ""; }
|
||||
bool CustomDeviceSupport(const QString &name);
|
||||
bool ValidOutput(const QString &output);
|
||||
bool CustomDeviceSupport(const QString &output);
|
||||
|
||||
protected:
|
||||
void SetVolumeSW( uint percent );
|
||||
|
@ -40,13 +40,14 @@
|
||||
VLCEngine *VLCEngine::sInstance = nullptr;
|
||||
|
||||
VLCEngine::VLCEngine(TaskManager *task_manager)
|
||||
: instance_(nullptr),
|
||||
: EngineBase(),
|
||||
instance_(nullptr),
|
||||
player_(nullptr),
|
||||
state_(Engine::Empty),
|
||||
scope_data_(4096)
|
||||
{
|
||||
scope_data_(4096) {
|
||||
|
||||
Init();
|
||||
type_ = Engine::VLC;
|
||||
ReloadSettings();
|
||||
|
||||
}
|
||||
|
||||
@ -61,8 +62,6 @@ VLCEngine::~VLCEngine() {
|
||||
|
||||
bool VLCEngine::Init() {
|
||||
|
||||
type_ = Engine::VLC;
|
||||
|
||||
/* FIXME: Do we need this?
|
||||
static const char *const args[] = {
|
||||
"-I", "dummy", // Don't use any interface
|
||||
@ -113,8 +112,15 @@ bool VLCEngine::Init() {
|
||||
|
||||
}
|
||||
|
||||
bool VLCEngine::Load(const QUrl &url, Engine::TrackChangeFlags change, bool force_stop_at_end, quint64 beginning_nanosec, qint64 end_nanosec) {
|
||||
bool VLCEngine::Initialised() const {
|
||||
|
||||
if (instance_ && player_) return true;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
bool VLCEngine::Load(const QUrl &url, Engine::TrackChangeFlags change, bool force_stop_at_end, quint64 beginning_nanosec, qint64 end_nanosec) {
|
||||
if (!Initialised()) return false;
|
||||
// Create the media object
|
||||
VlcScopedRef<libvlc_media_t> media(libvlc_media_new_location(instance_, url.toEncoded().constData()));
|
||||
|
||||
@ -125,7 +131,7 @@ bool VLCEngine::Load(const QUrl &url, Engine::TrackChangeFlags change, bool forc
|
||||
}
|
||||
|
||||
bool VLCEngine::Play(quint64 offset_nanosec) {
|
||||
|
||||
if (!Initialised()) return false;
|
||||
// Set audio output
|
||||
if (!output_.isEmpty() || output_ != "auto") {
|
||||
int result = libvlc_audio_output_set(player_, output_.toUtf8().constData());
|
||||
@ -148,27 +154,29 @@ bool VLCEngine::Play(quint64 offset_nanosec) {
|
||||
}
|
||||
|
||||
void VLCEngine::Stop(bool stop_after) {
|
||||
|
||||
if (!Initialised()) return;
|
||||
libvlc_media_player_stop(player_);
|
||||
HandleErrors();
|
||||
|
||||
}
|
||||
|
||||
void VLCEngine::Pause() {
|
||||
|
||||
if (!Initialised()) return;
|
||||
libvlc_media_player_pause(player_);
|
||||
HandleErrors();
|
||||
|
||||
}
|
||||
|
||||
void VLCEngine::Unpause() {
|
||||
|
||||
if (!Initialised()) return;
|
||||
libvlc_media_player_play(player_);
|
||||
HandleErrors();
|
||||
|
||||
}
|
||||
|
||||
void VLCEngine::Seek(quint64 offset_nanosec) {
|
||||
|
||||
if (!Initialised()) return;
|
||||
|
||||
int offset = (offset_nanosec / kNsecPerMsec);
|
||||
|
||||
@ -183,7 +191,7 @@ void VLCEngine::Seek(quint64 offset_nanosec) {
|
||||
}
|
||||
|
||||
void VLCEngine::SetVolumeSW(uint percent) {
|
||||
|
||||
if (!Initialised()) return;
|
||||
libvlc_audio_set_volume(player_, percent);
|
||||
HandleErrors();
|
||||
}
|
||||
@ -248,12 +256,24 @@ EngineBase::OutputDetailsList VLCEngine::GetOutputsList() const {
|
||||
|
||||
}
|
||||
|
||||
bool VLCEngine::CustomDeviceSupport(const QString &name) {
|
||||
return (name == "auto" ? false : true);
|
||||
bool VLCEngine::ValidOutput(const QString &output) {
|
||||
|
||||
PluginDetailsList plugins = GetPluginList();
|
||||
for (const PluginDetails &plugin : plugins) {
|
||||
if (plugin.name == output) return(true);
|
||||
}
|
||||
return(false);
|
||||
|
||||
}
|
||||
|
||||
bool VLCEngine::CustomDeviceSupport(const QString &output) {
|
||||
return (output == "auto" ? false : true);
|
||||
}
|
||||
|
||||
uint VLCEngine::position() const {
|
||||
|
||||
if (!Initialised()) return (0);
|
||||
|
||||
bool is_playing = libvlc_media_player_is_playing(player_);
|
||||
HandleErrors();
|
||||
|
||||
@ -268,6 +288,8 @@ uint VLCEngine::position() const {
|
||||
|
||||
uint VLCEngine::length() const {
|
||||
|
||||
if (!Initialised()) return(0);
|
||||
|
||||
bool is_playing = libvlc_media_player_is_playing(player_);
|
||||
HandleErrors();
|
||||
|
||||
|
@ -63,8 +63,9 @@ class VLCEngine : public Engine::Base {
|
||||
const Engine::Scope& Scope();
|
||||
|
||||
OutputDetailsList GetOutputsList() const;
|
||||
bool ValidOutput(const QString &output);
|
||||
QString DefaultOutput() { return ""; }
|
||||
bool CustomDeviceSupport(const QString &name);
|
||||
bool CustomDeviceSupport(const QString &value);
|
||||
|
||||
private:
|
||||
libvlc_instance_t *instance_;
|
||||
@ -75,6 +76,7 @@ class VLCEngine : public Engine::Base {
|
||||
static VLCEngine *sInstance;
|
||||
QMutex scope_mutex_;
|
||||
|
||||
bool Initialised() const;
|
||||
uint position() const;
|
||||
uint length() const;
|
||||
bool CanDecode(const QUrl &url);
|
||||
|
@ -65,12 +65,8 @@ using std::shared_ptr;
|
||||
#define LLONG_MAX 9223372036854775807LL
|
||||
#endif
|
||||
|
||||
|
||||
//define this to use xine in a more standard way
|
||||
//#ifdef Q_OS_WIN32
|
||||
// Define this to use xine in a more standard way
|
||||
//#define XINE_SAFE_MODE
|
||||
//#endif
|
||||
|
||||
|
||||
const char *XineEngine::kAutoOutput = "auto";
|
||||
int XineEngine::last_error_ = XINE_MSG_NO_ERROR;
|
||||
@ -88,56 +84,28 @@ XineEngine::XineEngine(TaskManager *task_manager)
|
||||
fadeout_running_ (false),
|
||||
prune_(nullptr) {
|
||||
|
||||
type_ = Engine::Xine;
|
||||
ReloadSettings();
|
||||
|
||||
}
|
||||
|
||||
XineEngine::~XineEngine() {
|
||||
|
||||
// Wait until the fader thread is done
|
||||
if (s_fader_) {
|
||||
stop_fader_ = true;
|
||||
s_fader_->resume(); // safety call if the engine is in the pause state
|
||||
s_fader_->wait();
|
||||
}
|
||||
|
||||
// Wait until the prune scope thread is done
|
||||
if (prune_) {
|
||||
prune_->exit();
|
||||
prune_->wait();
|
||||
}
|
||||
|
||||
s_fader_.reset();
|
||||
s_outfader_.reset();
|
||||
prune_.reset();
|
||||
|
||||
if (fadeout_enabled_) {
|
||||
bool terminateFader = false;
|
||||
FadeOut(fadeout_duration_, &terminateFader, true); // true == exiting
|
||||
}
|
||||
|
||||
if (stream_) xine_close(stream_);
|
||||
if (eventqueue_) xine_event_dispose_queue(eventqueue_);
|
||||
if (stream_) xine_dispose(stream_);
|
||||
if (audioport_) xine_close_audio_driver(xine_, audioport_);
|
||||
if (post_) xine_post_dispose(xine_, post_);
|
||||
if (xine_) xine_exit(xine_);
|
||||
|
||||
//qLog(Debug) << "xine closed";
|
||||
//qLog(Debug) << "Scope statistics:";
|
||||
//qLog(Debug) << "Average list size: " << log_buffer_count_ / log_scope_call_count_;
|
||||
//qLog(Debug) << "Buffer failure: " << double(log_no_suitable_buffer_*100) / log_scope_call_count_ << "%";
|
||||
Cleanup();
|
||||
|
||||
}
|
||||
|
||||
bool XineEngine::Init() {
|
||||
|
||||
type_ = Engine::Xine;
|
||||
|
||||
Cleanup();
|
||||
SetEnvironment();
|
||||
|
||||
QMutexLocker l(&init_mutex_);
|
||||
|
||||
xine_ = xine_new();
|
||||
if (!xine_) {
|
||||
emit Error("Could not initialize xine.");
|
||||
@ -147,17 +115,76 @@ bool XineEngine::Init() {
|
||||
#ifdef XINE_SAFE_MODE
|
||||
xine_engine_set_param(xine_, XINE_ENGINE_PARAM_VERBOSITY, 99);
|
||||
#endif
|
||||
|
||||
xine_init(xine_);
|
||||
|
||||
MakeNewStream();
|
||||
xine_init(xine_);
|
||||
|
||||
#ifndef XINE_SAFE_MODE
|
||||
prune_.reset(new PruneScopeThread(this));
|
||||
prune_->start();
|
||||
#endif
|
||||
|
||||
SetDevice();
|
||||
|
||||
if (!ValidOutput(output_)) {
|
||||
qLog(Error) << "Invalid output detected:" << output_ << " - Resetting to default.";
|
||||
output_ = DefaultOutput();
|
||||
}
|
||||
audioport_ = xine_open_audio_driver(xine_, (output_.isEmpty() || output_ == kAutoOutput ? nullptr : output_.toUtf8().constData()), nullptr);
|
||||
if (!audioport_) {
|
||||
emit Error("Xine was unable to initialize any audio drivers.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void XineEngine::Cleanup() {
|
||||
|
||||
// Wait until the prune scope thread is done
|
||||
if (prune_) {
|
||||
prune_->exit();
|
||||
prune_->wait();
|
||||
}
|
||||
prune_.reset();
|
||||
|
||||
// Wait until the fader thread is done
|
||||
if (s_fader_) {
|
||||
stop_fader_ = true;
|
||||
s_fader_->resume(); // safety call if the engine is in the pause state
|
||||
s_fader_->wait();
|
||||
}
|
||||
|
||||
s_fader_.reset();
|
||||
s_outfader_.reset();
|
||||
|
||||
if (stream_)
|
||||
xine_close(stream_);
|
||||
if (eventqueue_) {
|
||||
xine_event_dispose_queue(eventqueue_);
|
||||
eventqueue_ = nullptr;
|
||||
}
|
||||
if (stream_) {
|
||||
xine_dispose(stream_);
|
||||
stream_ = nullptr;
|
||||
}
|
||||
if (audioport_) {
|
||||
xine_close_audio_driver(xine_, audioport_);
|
||||
audioport_ = nullptr;
|
||||
}
|
||||
if (post_) {
|
||||
xine_post_dispose(xine_, post_);
|
||||
post_ = nullptr;
|
||||
}
|
||||
|
||||
if (xine_) xine_exit(xine_);
|
||||
xine_ = nullptr;
|
||||
|
||||
//qLog(Debug) << "xine closed";
|
||||
//qLog(Debug) << "Scope statistics:";
|
||||
//qLog(Debug) << "Average list size: " << log_buffer_count_ / log_scope_call_count_;
|
||||
//qLog(Debug) << "Buffer failure: " << double(log_no_suitable_buffer_*100) / log_scope_call_count_ << "%";
|
||||
|
||||
}
|
||||
|
||||
Engine::State XineEngine::state() const {
|
||||
@ -183,7 +210,7 @@ bool XineEngine::Load(const QUrl &url, Engine::TrackChangeFlags change, bool for
|
||||
|
||||
if (s_outfader_) {
|
||||
s_outfader_->finish();
|
||||
if (s_outfader_) s_outfader_.reset();
|
||||
s_outfader_.reset();
|
||||
}
|
||||
|
||||
if (fade_length_ > 0 && xine_get_status(stream_) == XINE_STATUS_PLAY && url.scheme().toLower() == "file" && xine_get_param(stream_, XINE_PARAM_SPEED) != XINE_SPEED_PAUSE && (fade_next_track_ || crossfade_enabled_)) {
|
||||
@ -370,14 +397,22 @@ EngineBase::OutputDetailsList XineEngine::GetOutputsList() const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool XineEngine::CustomDeviceSupport(const QString &name) {
|
||||
return (name == "alsa" || name == "oss" || name == "jack" || name == "pulseaudio");
|
||||
bool XineEngine::ValidOutput(const QString &output) {
|
||||
|
||||
PluginDetailsList plugins = GetPluginList();
|
||||
for (const PluginDetails &plugin : plugins) {
|
||||
if (plugin.name == output) return(true);
|
||||
}
|
||||
return(false);
|
||||
|
||||
}
|
||||
|
||||
bool XineEngine::CustomDeviceSupport(const QString &output) {
|
||||
return (output == "alsa" || output == "oss" || output == "jack" || output == "pulseaudio");
|
||||
}
|
||||
|
||||
void XineEngine::ReloadSettings() {
|
||||
|
||||
QSettings s;
|
||||
|
||||
Engine::Base::ReloadSettings();
|
||||
|
||||
if (output_ == "") output_ = DefaultOutput();
|
||||
@ -386,13 +421,13 @@ void XineEngine::ReloadSettings() {
|
||||
|
||||
void XineEngine::SetEnvironment() {
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
putenv(QString("XINE_PLUGIN_PATH=" + QCoreApplication::applicationDirPath() + "/xine/plugins").toLatin1().constData());
|
||||
#endif // Q_OS_WIN32
|
||||
#ifdef Q_OS_WIN
|
||||
putenv(QString("XINE_PLUGIN_PATH=" + QCoreApplication::applicationDirPath() + "/xine-plugins").toLatin1().constData());
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
setenv("XINE_PLUGIN_PATH", QString(QCoreApplication::applicationDirPath() + "/../PlugIns/xine").toLatin1().constData(), 1);
|
||||
#endif // Q_OS_DARWIN
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@ -868,7 +903,7 @@ Engine::SimpleMetaBundle XineEngine::fetchMetaData() const {
|
||||
|
||||
}
|
||||
|
||||
bool XineEngine::MakeNewStream() {
|
||||
void XineEngine::SetDevice() {
|
||||
|
||||
if (device_.isValid()) {
|
||||
bool valid(false);
|
||||
@ -892,12 +927,11 @@ bool XineEngine::MakeNewStream() {
|
||||
xine_config_update_entry(xine_, &entry);
|
||||
}
|
||||
}
|
||||
current_device_ = device_;
|
||||
|
||||
audioport_ = xine_open_audio_driver(xine_, (output_.isEmpty() || output_ == kAutoOutput ? nullptr : output_.toUtf8().constData()), nullptr);
|
||||
if (!audioport_) {
|
||||
emit Error("Xine was unable to initialize any audio drivers.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool XineEngine::CreateStream() {
|
||||
|
||||
stream_ = xine_stream_new(xine_, audioport_, nullptr);
|
||||
if (!stream_) {
|
||||
@ -908,7 +942,6 @@ bool XineEngine::MakeNewStream() {
|
||||
}
|
||||
|
||||
if (eventqueue_) xine_event_dispose_queue(eventqueue_);
|
||||
|
||||
eventqueue_ = xine_event_new_queue(stream_);
|
||||
xine_event_create_listener_thread(eventqueue_, &XineEngine::XineEventListener, (void*)this);
|
||||
|
||||
@ -923,7 +956,7 @@ bool XineEngine::MakeNewStream() {
|
||||
if (xine_check_version(1, 1, 1) && !(fade_length_ > 0)) {
|
||||
// Enable gapless playback
|
||||
qLog(Debug) << "gapless playback enabled.";
|
||||
// xine_set_param(stream_, XINE_PARAM_EARLY_FINISHED_EVENT, 1);
|
||||
xine_set_param(stream_, XINE_PARAM_EARLY_FINISHED_EVENT, 1);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
@ -931,7 +964,7 @@ bool XineEngine::MakeNewStream() {
|
||||
|
||||
bool XineEngine::EnsureStream() {
|
||||
|
||||
if (!stream_) return MakeNewStream();
|
||||
if (!stream_) return CreateStream();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
@ -65,9 +65,8 @@ private:
|
||||
|
||||
class XineEngine : public Engine::Base {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
XineEngine(TaskManager *task_manager);
|
||||
~XineEngine();
|
||||
|
||||
@ -86,38 +85,21 @@ public:
|
||||
|
||||
const Engine::Scope& scope(int chunk_length);
|
||||
|
||||
QString DefaultOutput() { return "auto"; }
|
||||
OutputDetailsList GetOutputsList() const;
|
||||
bool CustomDeviceSupport(const QString &name);
|
||||
bool ValidOutput(const QString &output);
|
||||
QString DefaultOutput() { return "auto"; }
|
||||
bool CustomDeviceSupport(const QString &output);
|
||||
|
||||
void ReloadSettings();
|
||||
|
||||
void SetEnvironment();
|
||||
|
||||
uint length() const;
|
||||
uint position() const;
|
||||
|
||||
bool CanDecode(const QUrl &);
|
||||
|
||||
bool MetaDataForUrl(const QUrl &url, Engine::SimpleMetaBundle &b);
|
||||
bool GetAudioCDContents(const QString &device, QList<QUrl> &urls);
|
||||
bool FlushBuffer();
|
||||
bool CreateStream();
|
||||
|
||||
void SetEqualizerEnabled(bool enabled);
|
||||
void SetEqualizerParameters(int preamp, const QList<int>&);
|
||||
|
||||
|
||||
void FadeOut(uint fadeLength, bool* terminate, bool exiting = false);
|
||||
|
||||
static void XineEventListener(void*, const xine_event_t*);
|
||||
bool event(QEvent*);
|
||||
|
||||
Engine::SimpleMetaBundle fetchMetaData() const;
|
||||
|
||||
bool MakeNewStream();
|
||||
bool EnsureStream();
|
||||
|
||||
void DetermineAndShowErrorMessage(); //call after failure to load/play
|
||||
|
||||
// Simple accessors
|
||||
|
||||
xine_stream_t *stream() { return stream_; }
|
||||
@ -125,10 +107,12 @@ public:
|
||||
bool stop_fader() { return stop_fader_; }
|
||||
void set_stop_fader(bool stop_fader) { stop_fader_ = stop_fader; }
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
static const char *kAutoOutput;
|
||||
|
||||
QString current_output_;
|
||||
QVariant current_device_;
|
||||
|
||||
xine_t *xine_;
|
||||
xine_stream_t *stream_;
|
||||
xine_audio_port_t *audioport_;
|
||||
@ -160,6 +144,26 @@ private:
|
||||
|
||||
mutable Engine::SimpleMetaBundle current_bundle_;
|
||||
|
||||
void SetEnvironment();
|
||||
|
||||
void Cleanup();
|
||||
bool EnsureStream();
|
||||
void SetDevice();
|
||||
|
||||
uint length() const;
|
||||
uint position() const;
|
||||
|
||||
bool MetaDataForUrl(const QUrl &url, Engine::SimpleMetaBundle &b);
|
||||
bool GetAudioCDContents(const QString &device, QList<QUrl> &urls);
|
||||
bool FlushBuffer();
|
||||
|
||||
static void XineEventListener(void*, const xine_event_t*);
|
||||
bool event(QEvent*);
|
||||
|
||||
Engine::SimpleMetaBundle fetchMetaData() const;
|
||||
|
||||
void DetermineAndShowErrorMessage(); //call after failure to load/play
|
||||
|
||||
PluginDetailsList GetPluginList() const;
|
||||
|
||||
private slots:
|
||||
|
@ -38,7 +38,7 @@ XineFader::XineFader(XineEngine *engine, xine_t *xine, xine_stream_t *stream, xi
|
||||
paused_(false),
|
||||
terminated_(false) {
|
||||
|
||||
if (engine->MakeNewStream()) {
|
||||
if (engine->CreateStream()) {
|
||||
increase_ = stream_;
|
||||
xine_set_param(increase_, XINE_PARAM_AUDIO_AMP_LEVEL, 0);
|
||||
}
|
||||
|
@ -43,6 +43,10 @@
|
||||
#include "core/logging.h"
|
||||
#include "core/signalchecker.h"
|
||||
|
||||
#ifndef u_int32_t
|
||||
typedef unsigned int u_int32_t;
|
||||
#endif
|
||||
|
||||
static const int kDecodeRate = 11025;
|
||||
static const int kDecodeChannels = 1;
|
||||
static const int kPlayLengthSecs = 30;
|
||||
|
@ -79,7 +79,8 @@ void BackendSettingsPage::Load() {
|
||||
engineloaded_ = false;
|
||||
xinewarning_ = false;
|
||||
|
||||
Engine::EngineType enginetype = Engine::EngineTypeFromName(s_.value("engine", EngineDescription(Engine::GStreamer)).toString());
|
||||
Engine::EngineType enginetype = Engine::EngineTypeFromName(s_.value("engine", EngineName(Engine::None)).toString());
|
||||
if (enginetype == Engine::None && engine()) enginetype = engine()->type();
|
||||
|
||||
ui_->combobox_engine->clear();
|
||||
#ifdef HAVE_GSTREAMER
|
||||
@ -95,7 +96,9 @@ void BackendSettingsPage::Load() {
|
||||
ui_->combobox_engine->addItem(IconLoader::Load("speaker"), EngineDescription(Engine::Phonon), Engine::Phonon);
|
||||
#endif
|
||||
|
||||
enginereset_ = false;
|
||||
enginetype_current_ = enginetype;
|
||||
output_current_ = s_.value("output", "").toString();
|
||||
device_current_ = s_.value("device", QVariant());
|
||||
|
||||
ui_->combobox_engine->setCurrentIndex(ui_->combobox_engine->findData(enginetype));
|
||||
if (EngineInitialised()) Load_Engine(enginetype);
|
||||
@ -152,8 +155,8 @@ void BackendSettingsPage::Load_Engine(Engine::EngineType enginetype) {
|
||||
|
||||
if (!EngineInitialised()) return;
|
||||
|
||||
QString output = s_.value("output", "").toString();
|
||||
QVariant device = s_.value("device", QVariant());
|
||||
QString output = output_current_;
|
||||
QVariant device = device_current_;
|
||||
|
||||
ui_->combobox_output->clear();
|
||||
ui_->combobox_device->clear();
|
||||
@ -163,13 +166,15 @@ void BackendSettingsPage::Load_Engine(Engine::EngineType enginetype) {
|
||||
|
||||
ui_->lineedit_device->setEnabled(false);
|
||||
ui_->lineedit_device->setText("");
|
||||
|
||||
|
||||
ui_->groupbox_replaygain->setEnabled(false);
|
||||
|
||||
if (engine()->type() != enginetype) {
|
||||
qLog(Debug) << "Switching engine.";
|
||||
dialog()->app()->player()->CreateEngine(enginetype);
|
||||
dialog()->app()->player()->ReloadSettings();
|
||||
dialog()->app()->player()->Init();
|
||||
dialog()->set_output_changed(false);
|
||||
}
|
||||
|
||||
engineloaded_ = true;
|
||||
@ -203,6 +208,7 @@ void BackendSettingsPage::Load_Output(QString output, QVariant device) {
|
||||
}
|
||||
if (!found) { // Output is invalid for this engine, reset to default output.
|
||||
output = engine()->DefaultOutput();
|
||||
device = (engine()->CustomDeviceSupport(output) == true ? QVariant("") : QVariant());
|
||||
for (int i = 0; i < ui_->combobox_output->count(); ++i) {
|
||||
EngineBase::OutputDetails o = ui_->combobox_output->itemData(i).value<EngineBase::OutputDetails>();
|
||||
if (o.name == output) {
|
||||
@ -212,8 +218,16 @@ void BackendSettingsPage::Load_Output(QString output, QVariant device) {
|
||||
}
|
||||
}
|
||||
|
||||
if (engine()->type() == Engine::GStreamer) ui_->groupbox_replaygain->setEnabled(true);
|
||||
else ui_->groupbox_replaygain->setEnabled(false);
|
||||
if (engine()->type() == Engine::GStreamer) {
|
||||
ui_->groupbox_buffer->setEnabled(true);
|
||||
ui_->groupbox_replaygain->setEnabled(true);
|
||||
ui_->checkbox_monoplayback->setEnabled(true);
|
||||
}
|
||||
else {
|
||||
ui_->groupbox_buffer->setEnabled(false);
|
||||
ui_->groupbox_replaygain->setEnabled(false);
|
||||
ui_->checkbox_monoplayback->setEnabled(false);
|
||||
}
|
||||
|
||||
if (ui_->combobox_output->count() < 1) {
|
||||
ShowWarning("Engine may take some time to initialize. Close settings and reopen to set output and devices.");
|
||||
@ -315,23 +329,35 @@ void BackendSettingsPage::Save() {
|
||||
s_.setValue("rgpreamp", float(ui_->stickslider_replaygainpreamp->value()) / 10 - 15);
|
||||
s_.setValue("rgcompression", ui_->checkbox_replaygaincompression->isChecked());
|
||||
|
||||
// If engine has not been changed, but output or device has been changed,
|
||||
// then set_output_changed(true) to reinitialize engine when dialog closes.
|
||||
if (enginetype == enginetype_current_ && (output_name != output_current_ || device_value != device_current_)) dialog()->set_output_changed(true);
|
||||
|
||||
}
|
||||
|
||||
void BackendSettingsPage::Cancel() {
|
||||
if (engine() && engine()->type() != enginetype_current_) { // Reset engine back to the original because user cancelled.
|
||||
dialog()->app()->player()->CreateEngine(enginetype_current_);
|
||||
dialog()->app()->player()->ReloadSettings();
|
||||
dialog()->app()->player()->Init();
|
||||
}
|
||||
}
|
||||
|
||||
void BackendSettingsPage::EngineChanged(int index) {
|
||||
|
||||
if (!configloaded_ || !EngineInitialised()) return;
|
||||
|
||||
if (engine()->state() != Engine::Empty) {
|
||||
if (enginereset_ == true) { enginereset_ = false; return; }
|
||||
errordialog_.ShowMessage("Can't switch engine while playing!");
|
||||
enginereset_ = true;
|
||||
ui_->combobox_engine->setCurrentIndex(ui_->combobox_engine->findData(engineloaded_));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
QVariant v = ui_->combobox_engine->itemData(index);
|
||||
Engine::EngineType enginetype = v.value<Engine::EngineType>();
|
||||
|
||||
if (engine()->type() == enginetype) return;
|
||||
|
||||
if (engine()->state() != Engine::Empty) {
|
||||
errordialog_.ShowMessage("Can't switch engine while playing!");
|
||||
ui_->combobox_engine->setCurrentIndex(ui_->combobox_engine->findData(engine()->type()));
|
||||
return;
|
||||
}
|
||||
|
||||
engineloaded_ = false;
|
||||
xinewarning_ = false;
|
||||
ResetWarning();
|
||||
@ -346,7 +372,7 @@ void BackendSettingsPage::OutputChanged(int index) {
|
||||
EngineBase::OutputDetails output = ui_->combobox_output->itemData(index).value<EngineBase::OutputDetails>();
|
||||
Load_Device(output.name, QVariant());
|
||||
|
||||
if (engine()->type() == Engine::Xine) XineWarning();
|
||||
if (engine()->type() == Engine::Xine && engine()->state() != Engine::Empty) XineWarning();
|
||||
|
||||
}
|
||||
|
||||
@ -371,7 +397,7 @@ void BackendSettingsPage::DeviceSelectionChanged(int index) {
|
||||
if (!ui_->lineedit_device->text().isEmpty()) ui_->lineedit_device->setText("");
|
||||
}
|
||||
|
||||
if (engine()->type() == Engine::Xine) XineWarning();
|
||||
if (engine()->type() == Engine::Xine && engine()->state() != Engine::Empty) XineWarning();
|
||||
|
||||
}
|
||||
|
||||
@ -467,8 +493,8 @@ void BackendSettingsPage::XineWarning() {
|
||||
|
||||
if (!engineloaded_) return;
|
||||
if (!configloaded_) return;
|
||||
|
||||
if (engine()->type() != Engine::Xine) return;
|
||||
if (engine()->state() == Engine::Empty) return;
|
||||
if (xinewarning_) return;
|
||||
|
||||
ShowWarning("You need to restart Strawberry for output/device changes to take affect for Xine.");
|
||||
|
@ -52,6 +52,7 @@ public:
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
void Cancel();
|
||||
|
||||
EngineBase *engine() const { return dialog()->app()->player()->engine(); }
|
||||
|
||||
@ -65,10 +66,10 @@ public:
|
||||
|
||||
private:
|
||||
Ui_BackendSettingsPage *ui_;
|
||||
|
||||
|
||||
void ConnectSignals();
|
||||
bool EngineInitialised();
|
||||
|
||||
|
||||
void EngineChanged(Engine::EngineType enginetype);
|
||||
|
||||
void Load_Engine(Engine::EngineType enginetype);
|
||||
@ -77,14 +78,17 @@ private:
|
||||
void ShowWarning(QString text);
|
||||
void ResetWarning();
|
||||
void XineWarning();
|
||||
|
||||
|
||||
QSettings s_;
|
||||
bool configloaded_;
|
||||
bool engineloaded_;
|
||||
ErrorDialog errordialog_;
|
||||
bool enginereset_;
|
||||
bool xinewarning_;
|
||||
|
||||
ErrorDialog errordialog_;
|
||||
|
||||
Engine::EngineType enginetype_current_;
|
||||
QString output_current_;
|
||||
QVariant device_current_;
|
||||
|
||||
};
|
||||
|
||||
#endif // BACKENDSETTINGSPAGE_H
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <QSpinBox>
|
||||
|
||||
#include "core/iconloader.h"
|
||||
#include "core/logging.h"
|
||||
#include "settingspage.h"
|
||||
#include "playbacksettingspage.h"
|
||||
#include "ui_playbacksettingspage.h"
|
||||
@ -50,9 +51,7 @@ PlaybackSettingsPage::PlaybackSettingsPage(SettingsDialog *dialog) : SettingsPag
|
||||
}
|
||||
|
||||
PlaybackSettingsPage::~PlaybackSettingsPage() {
|
||||
|
||||
delete ui_;
|
||||
|
||||
}
|
||||
|
||||
void PlaybackSettingsPage::Load() {
|
||||
|
@ -45,6 +45,7 @@
|
||||
|
||||
#include "core/application.h"
|
||||
#include "core/player.h"
|
||||
#include "core/logging.h"
|
||||
#include "engine/enginebase.h"
|
||||
#include "widgets/groupediconview.h"
|
||||
#include "collection/collectionmodel.h"
|
||||
@ -104,7 +105,8 @@ SettingsDialog::SettingsDialog(Application *app, QWidget *parent)
|
||||
model_(app_->collection_model()->directory_model()),
|
||||
appearance_(app_->appearance()),
|
||||
ui_(new Ui_SettingsDialog),
|
||||
loading_settings_(false) {
|
||||
loading_settings_(false),
|
||||
output_changed_(false) {
|
||||
|
||||
ui_->setupUi(this);
|
||||
ui_->list->setItemDelegate(new SettingsItemDelegate(this));
|
||||
@ -203,6 +205,11 @@ void SettingsDialog::Save() {
|
||||
|
||||
void SettingsDialog::accept() {
|
||||
Save();
|
||||
// Only Xine needs to reinitialize to switch output and device.
|
||||
if (output_changed_ && engine() && engine()->type() == Engine::Xine && engine()->state() == Engine::Empty) {
|
||||
engine()->ReloadSettings();
|
||||
engine()->Init();
|
||||
}
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <QScrollArea>
|
||||
#include <QTreeWidgetItem>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "widgets/osd.h"
|
||||
|
||||
class QModelIndex;
|
||||
@ -104,6 +105,8 @@ public:
|
||||
// QWidget
|
||||
void showEvent(QShowEvent *e);
|
||||
|
||||
void set_output_changed(bool output_changed) { output_changed_ = output_changed; }
|
||||
|
||||
signals:
|
||||
void NotificationPreview(OSD::Behaviour, QString, QString);
|
||||
|
||||
@ -135,6 +138,8 @@ private:
|
||||
bool loading_settings_;
|
||||
|
||||
QMap<Page, PageData> pages_;
|
||||
|
||||
bool output_changed_;
|
||||
};
|
||||
|
||||
#endif // SETTINGSDIALOG_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user