Remove broken xine fader until it's properly fixed

This commit is contained in:
Jonas Kvinge 2018-08-12 15:05:34 +02:00
parent 099d098dc7
commit 41b0b1efd4
5 changed files with 13 additions and 351 deletions

View File

@ -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
)

View File

@ -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<uint>(vol * preamp_));
xine_set_param(stream_, XINE_PARAM_AUDIO_AMP_LEVEL, static_cast<uint>(vol * preamp_));
}
@ -658,46 +592,6 @@ void XineEngine::SetEqualizerParameters(int preamp, const QList<int> &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() {

View File

@ -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<int>&);
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<PruneScopeThread> 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<XineFader> s_fader_;
std::unique_ptr<XineOutFader> s_outfader_;
int int_preamp_;
QMutex init_mutex_;
int64_t current_vpts_;
QList<int> equalizer_gains_;
int fade_length_;
bool fade_next_track_;
mutable Engine::SimpleMetaBundle current_bundle_;

View File

@ -1,150 +0,0 @@
/***************************************************************************
* Copyright (C) 2017-2018 Jonas Kvinge <jonas@jkvinge.net> *
* Copyright (C) 2005 Christophe Thommeret <hftom@free.fr> *
* (C) 2005 Ian Monroe <ian@monroe.nu> *
* (C) 2005-2006 Mark Kretschmann <markey@web.de> *
* (C) 2004-2005 Max Howell <max.howell@methylblue.com> *
* (C) 2003-2004 J. Kofler <kaffeine@gmx.net> *
* *
* 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 <xine.h>
#include <QtGlobal>
#include <QThread>
#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;
}

View File

@ -1,69 +0,0 @@
/***************************************************************************
* Copyright (C) 2017-2018 Jonas Kvinge <jonas@jkvinge.net> *
* Copyright (C) 2005 Christophe Thommeret <hftom@free.fr> *
* (C) 2005 Ian Monroe <ian@monroe.nu> *
* (C) 2005-2006 Mark Kretschmann <markey@web.de> *
* (C) 2004-2005 Max Howell <max.howell@methylblue.com> *
* (C) 2003-2004 J. Kofler <kaffeine@gmx.net> *
* *
* 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 <QtGlobal>
#include <QThread>
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