diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e5efec282..d1cd748d3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -528,7 +528,7 @@ optional_source(HAVE_GSTREAMER # Xine optional_source(HAVE_XINE - SOURCES engine/xineengine.cpp engine/xinescope.c engine/xinefader.cpp + SOURCES engine/xineengine.cpp engine/xinescope.c HEADERS engine/xineengine.h ) diff --git a/src/engine/xineengine.cpp b/src/engine/xineengine.cpp index 2bc0b1b9e..a9f57a92b 100644 --- a/src/engine/xineengine.cpp +++ b/src/engine/xineengine.cpp @@ -55,7 +55,6 @@ #include "enginetype.h" #include "xineengine.h" #include "xinescope.h" -#include "xinefader.h" #include "settings/backendsettingspage.h" @@ -80,8 +79,6 @@ XineEngine::XineEngine(TaskManager *task_manager) eventqueue_(nullptr), post_(nullptr), preamp_(1.0), - stop_fader_(false), - fadeout_running_ (false), prune_(nullptr) { type_ = Engine::Xine; @@ -91,11 +88,6 @@ XineEngine::XineEngine(TaskManager *task_manager) XineEngine::~XineEngine() { - if (fadeout_enabled_) { - bool terminateFader = false; - FadeOut(fadeout_duration_, &terminateFader, true); // true == exiting - } - Cleanup(); } @@ -122,7 +114,7 @@ bool XineEngine::Init() { prune_.reset(new PruneScopeThread(this)); prune_->start(); #endif - + SetDevice(); if (!ValidOutput(output_)) { @@ -148,16 +140,6 @@ void XineEngine::Cleanup() { } 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_) { @@ -189,7 +171,7 @@ void XineEngine::Cleanup() { Engine::State XineEngine::state() const { - if (!stream_ || fadeout_running_) return Engine::Empty; + if (!stream_) return Engine::Empty; switch(xine_get_status(stream_)) { case XINE_STATUS_PLAY: @@ -208,24 +190,6 @@ bool XineEngine::Load(const QUrl &url, Engine::TrackChangeFlags change, bool for Engine::Base::Load(url, change, force_stop_at_end, beginning_nanosec, end_nanosec); - if (s_outfader_) { - s_outfader_->finish(); - 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_)) { - - fade_next_track_ = false; // Set by engine controller when switching tracks automatically - - // Stop a probably running fader - if (s_fader_) { - stop_fader_ = true; - s_fader_->finish(); // Makes the fader stop abruptly - } - s_fader_.reset(new XineFader(this, xine_, stream_, audioport_, post_, fade_length_)); - SetEqualizerParameters(int_preamp_, equalizer_gains_); - } - xine_close(stream_); //int result = xine_open(stream_, url.path().toUtf8()); @@ -244,8 +208,6 @@ bool XineEngine::Load(const QUrl &url, Engine::TrackChangeFlags change, bool for qLog(Error) << "Failed to play"; } - // FAILURE to load! - // s_fader_ will delete itself DetermineAndShowErrorMessage(); return false; @@ -260,16 +222,9 @@ bool XineEngine::Play(quint64 offset_nanosec) { const bool audio_handled = xine_get_stream_info(stream_, XINE_STREAM_INFO_AUDIO_HANDLED); if (has_audio && audio_handled && xine_play(stream_, 0, offset)) { - if (s_fader_) s_fader_->start(QThread::LowestPriority); - emit StateChanged(Engine::Playing); - return true; } - - // We need to stop the track that is prepped for crossfade - if (s_fader_) s_fader_.reset(); - emit StateChanged(Engine::Empty); DetermineAndShowErrorMessage(); @@ -281,26 +236,14 @@ bool XineEngine::Play(quint64 offset_nanosec) { void XineEngine::Stop(bool stop_after) { - if (s_fader_ && s_fader_->isRunning()) - s_fader_->resume(); // Safety call if the engine is in the pause state - if (!stream_) return; - if ((fadeout_enabled_ && !fadeout_running_) || state() == Engine::Paused) { - s_outfader_.reset(new XineOutFader(this, fadeout_duration_)); - s_outfader_->start(); - ::usleep(100); // To be sure engine state won't be changed before it is checked in FadeOut() - url_ = QUrl(); // To ensure we return Empty from state() - - std::fill(scope_.begin(), scope_.end(), 0); - } - else if (!fadeout_running_) { - xine_stop(stream_); - xine_close(stream_); - xine_set_param(stream_, XINE_PARAM_AUDIO_CLOSE_DEVICE, 1); - } + xine_stop(stream_); + xine_close(stream_); + xine_set_param(stream_, XINE_PARAM_AUDIO_CLOSE_DEVICE, 1); emit StateChanged(Engine::Empty); + } void XineEngine::Pause() { @@ -308,13 +251,9 @@ void XineEngine::Pause() { if (!stream_) return; if (xine_get_param(stream_, XINE_PARAM_SPEED) != XINE_SPEED_PAUSE) { - - if (s_fader_ && s_fader_->isRunning()) s_fader_->pause(); - xine_set_param(stream_, XINE_PARAM_SPEED, XINE_SPEED_PAUSE); xine_set_param(stream_, XINE_PARAM_AUDIO_CLOSE_DEVICE, 1); emit StateChanged(Engine::Paused); - } } @@ -324,12 +263,8 @@ void XineEngine::Unpause() { if (!stream_) return; if (xine_get_param(stream_, XINE_PARAM_SPEED) == XINE_SPEED_PAUSE) { - - if (s_fader_ && s_fader_->isRunning()) s_fader_->resume(); - xine_set_param(stream_, XINE_PARAM_SPEED, XINE_SPEED_NORMAL); emit StateChanged(Engine::Playing); - } } @@ -351,8 +286,7 @@ void XineEngine::Seek(quint64 offset_nanosec) { void XineEngine::SetVolumeSW(uint vol) { if (!stream_) return; - if (!s_fader_) - xine_set_param(stream_, XINE_PARAM_AUDIO_AMP_LEVEL, static_cast(vol * preamp_)); + xine_set_param(stream_, XINE_PARAM_AUDIO_AMP_LEVEL, static_cast(vol * preamp_)); } @@ -658,46 +592,6 @@ void XineEngine::SetEqualizerParameters(int preamp, const QList &gains) { } -void XineEngine::FadeOut(uint fadeLength, bool *terminate, bool exiting) { - - if (fadeout_running_) return; // Don't start another fadeout - - fadeout_running_ = !fadeout_running_; - const bool isPlaying = stream_ && (xine_get_status(stream_) == XINE_STATUS_PLAY); - const float originalVol = Engine::Base::MakeVolumeLogarithmic(volume_) * preamp_; - - // On shutdown, limit fadeout to 3 secs max, so that we don't risk getting killed - const int length = exiting ? qMin(fadeLength, 3000u) : fadeLength; - - if (length > 0 && isPlaying) { - // fader-class doesn't work in this spot as is, so some parts need to be copied here... (ugly) - uint stepsCount = length < 1000 ? length / 10 : 100; - uint stepSizeUs = (int)(1000.0 * (float)length / (float)stepsCount); - - ::usleep(stepSizeUs); - QTime t; - t.start(); - float mix = 0.0; - while (mix < 1.0) { - if (*terminate) break; - - ::usleep(stepSizeUs); - float vol = Engine::Base::MakeVolumeLogarithmic(volume_) * preamp_; - float mix = (float)t.elapsed() / (float)length; - if (mix > 1.0) break; - if (stream_) { - float v = 4.0 * (1.0 - mix) / 3.0; - xine_set_param(stream_, XINE_PARAM_AUDIO_AMP_LEVEL, (uint)(v < 1.0 ? vol * v : vol)); - } - } - } - if (fadeout_running_ && stream_) - xine_set_param(stream_, XINE_PARAM_AUDIO_AMP_LEVEL, (uint) originalVol); - - fadeout_running_ = !fadeout_running_; - -} - void XineEngine::XineEventListener(void *p, const xine_event_t *xineEvent) { time_t current; @@ -953,13 +847,13 @@ bool XineEngine::CreateStream() { #endif #ifdef XINE_PARAM_EARLY_FINISHED_EVENT - 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); - } + // Enable gapless playback + qLog(Debug) << "gapless playback enabled."; + xine_set_param(stream_, XINE_PARAM_EARLY_FINISHED_EVENT, 1); #endif + return true; + } bool XineEngine::EnsureStream() { diff --git a/src/engine/xineengine.h b/src/engine/xineengine.h index 032854a35..1d707e716 100644 --- a/src/engine/xineengine.h +++ b/src/engine/xineengine.h @@ -40,8 +40,6 @@ using std::shared_ptr; class TaskManager; class PruneScopeThread; -class XineFader; -class XineOutFader; class XineEvent : public QEvent { public: @@ -97,15 +95,11 @@ class XineEngine : public Engine::Base { void SetEqualizerEnabled(bool enabled); void SetEqualizerParameters(int preamp, const QList&); - - void FadeOut(uint fadeLength, bool* terminate, bool exiting = false); // Simple accessors xine_stream_t *stream() { return stream_; } float preamp() { return preamp_; } - bool stop_fader() { return stop_fader_; } - void set_stop_fader(bool stop_fader) { stop_fader_ = stop_fader; } private: static const char *kAutoOutput; @@ -119,8 +113,6 @@ class XineEngine : public Engine::Base { xine_event_queue_t *eventqueue_; xine_post_t *post_; float preamp_; - bool stop_fader_; - bool fadeout_running_; std::unique_ptr prune_; QUrl url_; @@ -132,15 +124,10 @@ class XineEngine : public Engine::Base { uint log_scope_call_count_ = 1; // Prevent divideByZero uint log_no_suitable_buffer_ = 0; - std::unique_ptr s_fader_; - std::unique_ptr s_outfader_; - int int_preamp_; QMutex init_mutex_; int64_t current_vpts_; QList equalizer_gains_; - int fade_length_; - bool fade_next_track_; mutable Engine::SimpleMetaBundle current_bundle_; diff --git a/src/engine/xinefader.cpp b/src/engine/xinefader.cpp deleted file mode 100644 index 8a7691a82..000000000 --- a/src/engine/xinefader.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2017-2018 Jonas Kvinge * - * Copyright (C) 2005 Christophe Thommeret * - * (C) 2005 Ian Monroe * - * (C) 2005-2006 Mark Kretschmann * - * (C) 2004-2005 Max Howell * - * (C) 2003-2004 J. Kofler * - * * - * This program 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 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#include "config.h" - -#include - -#include -#include - -#include "core/logging.h" - -#include "xineengine.h" -#include "xinefader.h" - -XineFader::XineFader(XineEngine *engine, xine_t *xine, xine_stream_t *stream, xine_audio_port_t *audioport, xine_post_t *post, uint fade_length) - : QThread(engine), - engine_(engine), - xine_(xine), - stream_(stream), - decrease_(stream), - increase_(nullptr), - port_(audioport), - post_(post), - fade_length_(fade_length), - paused_(false), - terminated_(false) { - - if (engine->CreateStream()) { - increase_ = stream_; - xine_set_param(increase_, XINE_PARAM_AUDIO_AMP_LEVEL, 0); - } - else { - terminated_ = true; - } - -} - -XineFader::~XineFader() { - - wait(); - - xine_close(decrease_); - xine_dispose(decrease_); - xine_close_audio_driver(xine_, port_); - if (post_) xine_post_dispose(xine_, post_); - - if (!engine_->stop_fader()) - engine_->SetVolume(engine_->volume()); - - engine_->set_stop_fader(false); - -} - -void XineFader::run() { - - // Do a volume change in 100 steps (or every 10ms) - uint stepsCount = fade_length_ < 1000 ? fade_length_ / 10 : 100; - uint stepSizeUs = (int)(1000.0 * (float)fade_length_ / (float)stepsCount); - - float mix = 0.0; - float elapsedUs = 0.0; - while (mix < 1.0) { - if (terminated_) break; - // Sleep a constant amount of time - QThread::usleep(stepSizeUs); - - if (paused_) - continue; - - elapsedUs += stepSizeUs; - - // Get volume (amarok main * equalizer preamp) - float vol = Engine::Base::MakeVolumeLogarithmic(engine_->volume()) * engine_->preamp(); - - // Compute the mix factor as the percentage of time spent since fade begun - float mix = (elapsedUs / 1000.0) / (float)fade_length_; - if (mix > 1.0) { - if (increase_) xine_set_param(increase_, XINE_PARAM_AUDIO_AMP_LEVEL, (uint)vol); - break; - } - - // Change volume of streams (using dj-like cross-fade profile) - if (decrease_) { - //xine_set_param(decrease_, XINE_PARAM_AUDIO_AMP_LEVEL, (uint)(vol * (1.0 - mix))); // linear - float v = 4.0 * (1.0 - mix) / 3.0; - xine_set_param(decrease_, XINE_PARAM_AUDIO_AMP_LEVEL, (uint)(v < 1.0 ? vol * v : vol)); - } - if (increase_) { - // xine_set_param(increase_, XINE_PARAM_AUDIO_AMP_LEVEL, (uint)(vol * mix)); //linear - float v = 4.0 * mix / 3.0; - xine_set_param(increase_, XINE_PARAM_AUDIO_AMP_LEVEL, (uint)(v < 1.0 ? vol * v : vol)); - } - } - - // Stop using cpu! - xine_stop(decrease_); - -} - -void XineFader::pause() { - paused_ = true; -} - -void XineFader::resume() { - paused_ = false; -} - -void XineFader::finish() { - terminated_ = true; -} - -XineOutFader::XineOutFader(XineEngine *engine, uint fadeLength) - : QThread(engine), - engine_(engine), - terminated_(false), - fade_length_(fadeLength) -{ -} - -XineOutFader::~XineOutFader() { - wait(); -} - -void XineOutFader::run() { - - engine_->FadeOut(fade_length_, &terminated_); - - xine_stop(engine_->stream()); - xine_close(engine_->stream()); - xine_set_param(engine_->stream(), XINE_PARAM_AUDIO_CLOSE_DEVICE, 1); - -} - -void XineOutFader::finish() { - terminated_ = true; -} - diff --git a/src/engine/xinefader.h b/src/engine/xinefader.h deleted file mode 100644 index 047024ebf..000000000 --- a/src/engine/xinefader.h +++ /dev/null @@ -1,69 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2017-2018 Jonas Kvinge * - * Copyright (C) 2005 Christophe Thommeret * - * (C) 2005 Ian Monroe * - * (C) 2005-2006 Mark Kretschmann * - * (C) 2004-2005 Max Howell * - * (C) 2003-2004 J. Kofler * - * * - * This program 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 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#ifndef XINEFADER_H -#define XINEFADER_H - -#include "config.h" - -#include -#include - -class XineFader : public QThread { - -private: - - XineEngine *engine_; - xine_t *xine_; - xine_stream_t *stream_; - xine_stream_t *decrease_; - xine_stream_t *increase_; - xine_audio_port_t *port_; - xine_post_t *post_; - uint fade_length_; - bool paused_; - bool terminated_; - - void run(); - -public: - - XineFader(XineEngine *engine, xine_t *xine, xine_stream_t *stream, xine_audio_port_t *audioport, xine_post_t *post, uint fadeMs); - ~XineFader(); - - void pause(); - void resume(); - void finish(); - -}; - -class XineOutFader : public QThread { - -private: - - XineEngine *engine_; - bool terminated_; - uint fade_length_; - - void run(); - -public: - XineOutFader(XineEngine *, uint fadeLengthMs ); - ~XineOutFader(); - - void finish(); -}; - -#endif