diff --git a/.circleci/config.yml b/.circleci/config.yml
index e6bc9dc8b..099570330 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -80,7 +80,6 @@ commands:
libpulse-devel
gstreamer-devel
gstreamer-plugins-base-devel
- libxine-devel
vlc-devel
libQt5Core-devel
libQt5Gui-devel
diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml
index df19adbb1..507103c4a 100644
--- a/.github/workflows/ccpp.yml
+++ b/.github/workflows/ccpp.yml
@@ -38,7 +38,6 @@ jobs:
libpulse-devel
gstreamer-devel
gstreamer-plugins-base-devel
- libxine-devel
vlc-devel
libQt5Core-devel
libQt5Gui-devel
@@ -109,7 +108,6 @@ jobs:
libpulse-devel
gstreamer-devel
gstreamer-plugins-base-devel
- libxine-devel
vlc-devel
libQt5Core-devel
libQt5Gui-devel
@@ -188,7 +186,6 @@ jobs:
libpulse-devel
gstreamer-devel
gstreamer-plugins-base-devel
- libxine-devel
vlc-devel
libQt5Core-devel
libQt5Gui-devel
@@ -269,7 +266,6 @@ jobs:
libpulse-devel
gstreamer-devel
gstreamer-plugins-base-devel
- libxine-devel
vlc-devel
libQt5Core-devel
libQt5Gui-devel
@@ -1036,7 +1032,6 @@ jobs:
-DENABLE_LIBGPOD=OFF
-DENABLE_IMOBILEDEVICE=OFF
-DENABLE_LIBMTP=OFF
- -DENABLE_XINE=OFF
-DProtobuf_PROTOC_EXECUTABLE=/usr/src/strawberry-mxe/usr/x86_64-pc-linux-gnu/bin/protoc
- name: Run Make
@@ -1049,7 +1044,7 @@ jobs:
- name: Create directories
working-directory: build
- run: mkdir -p gio-modules platforms sqldrivers imageformats styles gstreamer-plugins xine-plugins nsisplugins
+ run: mkdir -p gio-modules platforms sqldrivers imageformats styles gstreamer-plugins nsisplugins
- name: Copy GIO modules
working-directory: build
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 15437f666..33a0b860c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -118,7 +118,6 @@ pkg_check_modules(GSTREAMER_AUDIO gstreamer-audio-1.0)
pkg_check_modules(GSTREAMER_APP gstreamer-app-1.0)
pkg_check_modules(GSTREAMER_TAG gstreamer-tag-1.0)
pkg_check_modules(GSTREAMER_PBUTILS gstreamer-pbutils-1.0)
-pkg_check_modules(LIBXINE libxine)
pkg_check_modules(LIBVLC libvlc)
pkg_check_modules(SQLITE REQUIRED sqlite3>=3.9)
pkg_check_modules(LIBPULSE libpulse)
@@ -258,10 +257,6 @@ optional_component(GSTREAMER ON "Engine: GStreamer backend"
DEPENDS "gstreamer-pbutils-1.0" GSTREAMER_PBUTILS_FOUND
)
-optional_component(XINE ON "Engine: Xine backend"
- DEPENDS "libxine" LIBXINE_FOUND
-)
-
optional_component(VLC ON "Engine: VLC backend"
DEPENDS "libvlc" LIBVLC_FOUND
)
@@ -401,8 +396,8 @@ add_custom_target(uninstall
# Show a summary of what we have enabled
summary_show()
-if(NOT HAVE_GSTREAMER AND NOT HAVE_XINE AND NOT HAVE_VLC)
- message(FATAL_ERROR "You need to have either GStreamer, Xine or VLC to compile!")
+if(NOT HAVE_GSTREAMER AND NOT HAVE_VLC)
+ message(FATAL_ERROR "You need to have either GStreamer or VLC to compile!")
elseif(NOT HAVE_GSTREAMER)
message(WARNING "GStreamer is the only engine that is fully implemented. Using other engines is possible but not recommended.")
endif()
diff --git a/README.md b/README.md
index f1197844c..b46a63639 100644
--- a/README.md
+++ b/README.md
@@ -70,7 +70,7 @@ To build Strawberry from source you need the following installed on your system
* [ALSA library (linux)](https://www.alsa-project.org/)
* [DBus (linux)](https://www.freedesktop.org/wiki/Software/dbus/)
* [PulseAudio (linux optional)](https://www.freedesktop.org/wiki/Software/PulseAudio/?)
-* [GStreamer](https://gstreamer.freedesktop.org/), [Xine](https://www.xine-project.org) or [VLC](https://www.videolan.org)
+* [GStreamer](https://gstreamer.freedesktop.org/) or [VLC](https://www.videolan.org)
* [GnuTLS](https://www.gnutls.org/)
Optional dependencies:
@@ -81,7 +81,7 @@ Optional dependencies:
* iPhone, iPod Touch, iPad and Apple TV devices: [libimobiledevice, libplist and libusbmuxd](https://www.libimobiledevice.org/)
* Moodbar: [fftw3](http://www.fftw.org/)
-Either GStreamer, Xine or VLC engine is required, but only GStreamer is fully implemented so far.
+Either GStreamer or VLC engine is required, but only GStreamer is fully implemented so far.
You should also install the gstreamer plugins base and good, and optionally bad and ugly.
### :wrench: Compiling from source
diff --git a/data/icons.qrc b/data/icons.qrc
index 89503e12e..66af2cfb5 100644
--- a/data/icons.qrc
+++ b/data/icons.qrc
@@ -81,7 +81,6 @@
icons/128x128/view-refresh.png
icons/128x128/library-music.png
icons/128x128/vlc.png
- icons/128x128/xine.png
icons/128x128/zoom-in.png
icons/128x128/zoom-out.png
icons/128x128/scrobble.png
@@ -172,7 +171,6 @@
icons/64x64/view-refresh.png
icons/64x64/library-music.png
icons/64x64/vlc.png
- icons/64x64/xine.png
icons/64x64/zoom-in.png
icons/64x64/zoom-out.png
icons/64x64/scrobble.png
@@ -267,7 +265,6 @@
icons/48x48/view-refresh.png
icons/48x48/library-music.png
icons/48x48/vlc.png
- icons/48x48/xine.png
icons/48x48/zoom-in.png
icons/48x48/zoom-out.png
icons/48x48/scrobble.png
@@ -362,7 +359,6 @@
icons/32x32/view-refresh.png
icons/32x32/library-music.png
icons/32x32/vlc.png
- icons/32x32/xine.png
icons/32x32/zoom-in.png
icons/32x32/zoom-out.png
icons/32x32/scrobble.png
@@ -457,7 +453,6 @@
icons/22x22/view-refresh.png
icons/22x22/library-music.png
icons/22x22/vlc.png
- icons/22x22/xine.png
icons/22x22/zoom-in.png
icons/22x22/zoom-out.png
icons/22x22/scrobble.png
diff --git a/data/icons/128x128/xine.png b/data/icons/128x128/xine.png
deleted file mode 100644
index 600a57e9f..000000000
Binary files a/data/icons/128x128/xine.png and /dev/null differ
diff --git a/data/icons/22x22/xine.png b/data/icons/22x22/xine.png
deleted file mode 100644
index 150c72c1e..000000000
Binary files a/data/icons/22x22/xine.png and /dev/null differ
diff --git a/data/icons/32x32/xine.png b/data/icons/32x32/xine.png
deleted file mode 100644
index 6339a2574..000000000
Binary files a/data/icons/32x32/xine.png and /dev/null differ
diff --git a/data/icons/48x48/xine.png b/data/icons/48x48/xine.png
deleted file mode 100644
index 58aa29716..000000000
Binary files a/data/icons/48x48/xine.png and /dev/null differ
diff --git a/data/icons/64x64/xine.png b/data/icons/64x64/xine.png
deleted file mode 100644
index 2d409d08f..000000000
Binary files a/data/icons/64x64/xine.png and /dev/null differ
diff --git a/data/icons/full/xine.png b/data/icons/full/xine.png
deleted file mode 100644
index 600a57e9f..000000000
Binary files a/data/icons/full/xine.png and /dev/null differ
diff --git a/debian/copyright b/debian/copyright
index b789bedf6..f055cdfe3 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -213,21 +213,6 @@ Copyright: 2017, 2018, Jonas Kvinge
2003-2005, Mark Kretschmann
License: GPL-2+
-Files: src/engine/xineengine.cpp
- src/engine/xineengine.h
-Copyright: 2017, 2018, Jonas Kvinge
- 2005, Ian Monroe
- 2005, Christophe Thommeret
- 2005, 2006, Mark Kretschmann
- 2004, 2005, Max Howell
- 2003, 2004, J. Kofler
-License: GPL-2+
-
-Files: src/engine/xinescope.c
- src/engine/xinescope.h
-Copyright: 2004, Max Howell
-License: GPL-2+
-
Files: src/widgets/fancytabwidget.cpp
src/widgets/fancytabwidget.h
Copyright: 2018, Vikram Ambrose
diff --git a/dist/macos/macdeploy.py b/dist/macos/macdeploy.py
index 20d29a98e..1dc34626b 100755
--- a/dist/macos/macdeploy.py
+++ b/dist/macos/macdeploy.py
@@ -154,12 +154,6 @@ class InstallNameToolError(Error):
class CouldNotFindGstreamerPluginError(Error):
pass
-class CouldNotFindXinePluginError(Error):
- pass
-
-class CouldNotFindVLCPluginError(Error):
- pass
-
if len(sys.argv) < 2:
print 'Usage: %s ' % sys.argv[0]
@@ -433,15 +427,6 @@ def FixFrameworkInstallPath(library_path, library):
FixInstallPath(library_path, library, new_path)
-def FindXinePlugin(name):
- for path in XINEPLUGIN_SEARCH_PATH:
- if os.path.exists(path):
- for dir, dirs, files in os.walk(path):
- if name in files:
- return os.path.join(dir, name)
- raise CouldNotFindXinePluginError(name)
-
-
def FindQtPlugin(name):
for path in QT_PLUGINS_SEARCH_PATH:
if os.path.exists(path):
diff --git a/dist/unix/PKGBUILD.in b/dist/unix/PKGBUILD.in
index 94f028be3..538428f6f 100644
--- a/dist/unix/PKGBUILD.in
+++ b/dist/unix/PKGBUILD.in
@@ -23,7 +23,6 @@ depends=(
gstreamer
gst-plugins-base
gst-plugins-good
- xine-lib
vlc
chromaprint
libgpod
diff --git a/dist/unix/strawberry.spec.in b/dist/unix/strawberry.spec.in
index 09a7ef698..02b1abbab 100644
--- a/dist/unix/strawberry.spec.in
+++ b/dist/unix/strawberry.spec.in
@@ -73,7 +73,6 @@ BuildRequires: pkgconfig(libmtp)
BuildRequires: pkgconfig(libnotify)
BuildRequires: pkgconfig(libudf)
%if 0%{?suse_version} || 0%{?fedora_version}
-BuildRequires: pkgconfig(libxine)
BuildRequires: pkgconfig(libvlc)
%endif
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index 89a41f168..05f4d4677 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -99,7 +99,6 @@ parts:
- libqt5x11extras5-dev
- libgstreamer1.0-dev
- libgstreamer-plugins-base1.0-dev
- - libxine2-dev
- libvlc-dev
- libcdio-dev
- libgpod-dev
@@ -135,7 +134,6 @@ parts:
- libimobiledevice6
- libplist3
- libusbmuxd4
- - libxine2
- libvlc5
- libvlccore9
- libtag1v5
@@ -144,7 +142,6 @@ parts:
- libx11-6
- libxcomposite1
- libxcursor1
- - libxinerama1
- libxrandr2
- libdb5.3
- libglu1
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index bb4444e12..ce886673d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -533,12 +533,6 @@ optional_source(HAVE_GSTREAMER
HEADERS engine/gststartup.h engine/gstengine.h engine/gstenginepipeline.h engine/gstelementdeleter.h
)
-# Xine
-optional_source(HAVE_XINE
- SOURCES engine/xineengine.cpp engine/xinescope.c
- HEADERS engine/xineengine.h
-)
-
# VLC
optional_source(HAVE_VLC
SOURCES engine/vlcengine.cpp
@@ -944,10 +938,6 @@ if(HAVE_GSTREAMER)
)
endif(HAVE_GSTREAMER)
-if(HAVE_XINE)
- link_directories(${LIBXINE_LIBRARY_DIRS})
-endif()
-
if(HAVE_VLC)
link_directories(${LIBVLC_LIBRARY_DIRS})
endif()
@@ -1067,11 +1057,6 @@ if(HAVE_MOODBAR)
target_link_libraries(strawberry_lib PRIVATE gstmoodbar)
endif()
-if(HAVE_XINE)
- target_include_directories(strawberry_lib SYSTEM PRIVATE ${LIBXINE_INCLUDE_DIRS})
- target_link_libraries(strawberry_lib PRIVATE ${LIBXINE_LIBRARIES})
-endif()
-
if(HAVE_VLC)
target_include_directories(strawberry_lib SYSTEM PRIVATE ${LIBVLC_INCLUDE_DIRS})
target_link_libraries(strawberry_lib PRIVATE ${LIBVLC_LIBRARIES})
diff --git a/src/analyzer/analyzercontainer.cpp b/src/analyzer/analyzercontainer.cpp
index 6355712bd..97f4479e3 100644
--- a/src/analyzer/analyzercontainer.cpp
+++ b/src/analyzer/analyzercontainer.cpp
@@ -99,7 +99,7 @@ AnalyzerContainer::AnalyzerContainer(QWidget *parent)
void AnalyzerContainer::mouseReleaseEvent(QMouseEvent *e) {
- if (engine_->type() != Engine::EngineType::GStreamer && engine_->type() != Engine::EngineType::Xine) return;
+ if (engine_->type() != Engine::EngineType::GStreamer) return;
if (e->button() == Qt::RightButton) {
context_menu_->popup(e->globalPos());
diff --git a/src/config.h.in b/src/config.h.in
index ff31cdb8b..c57b5ad41 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -43,7 +43,6 @@
#cmakedefine HAVE_GSTREAMER
#cmakedefine HAVE_VLC
-#cmakedefine HAVE_XINE
#cmakedefine HAVE_SUBSONIC
#cmakedefine HAVE_TIDAL
diff --git a/src/core/iconmapper.h b/src/core/iconmapper.h
index 91e37db02..54ef6ce82 100644
--- a/src/core/iconmapper.h
+++ b/src/core/iconmapper.h
@@ -129,7 +129,6 @@ static const QMap iconmapper_ = {
{ "view-refresh", { {}} },
{ "library-music", { {"vinyl"}} },
{ "vlc", { {}} },
- { "xine", { {}} },
{ "zoom-in", { {}} },
{ "zoom-out", { {}, 0, 0 } }
diff --git a/src/core/mainwindow.cpp b/src/core/mainwindow.cpp
index 2f26aad5f..ab54d3dc8 100644
--- a/src/core/mainwindow.cpp
+++ b/src/core/mainwindow.cpp
@@ -1058,7 +1058,7 @@ void MainWindow::ExitFinished() {
void MainWindow::EngineChanged(Engine::EngineType enginetype) {
- ui_->action_equalizer->setEnabled(enginetype == Engine::EngineType::GStreamer || enginetype == Engine::EngineType::Xine);
+ ui_->action_equalizer->setEnabled(enginetype == Engine::EngineType::GStreamer);
#ifdef Q_OS_WIN
ui_->action_open_cd->setEnabled(false);
ui_->action_open_cd->setVisible(false);
diff --git a/src/core/player.cpp b/src/core/player.cpp
index 258bbc8d0..d5083bf52 100644
--- a/src/core/player.cpp
+++ b/src/core/player.cpp
@@ -51,9 +51,6 @@
# include "engine/gstengine.h"
# include "engine/gststartup.h"
#endif
-#ifdef HAVE_XINE
-# include "engine/xineengine.h"
-#endif
#ifdef HAVE_VLC
# include "engine/vlcengine.h"
#endif
@@ -125,12 +122,6 @@ Engine::EngineType Player::CreateEngine(Engine::EngineType enginetype) {
break;
}
#endif
-#ifdef HAVE_XINE
- case Engine::Xine:
- use_enginetype=Engine::Xine;
- engine_.reset(new XineEngine(app_->task_manager()));
- break;
-#endif
#ifdef HAVE_VLC
case Engine::VLC:
use_enginetype=Engine::VLC;
diff --git a/src/engine/enginetype.cpp b/src/engine/enginetype.cpp
index 443c39c40..9d1c586ce 100644
--- a/src/engine/enginetype.cpp
+++ b/src/engine/enginetype.cpp
@@ -28,7 +28,6 @@ namespace Engine {
Engine::EngineType EngineTypeFromName(QString enginename) {
QString lower = enginename.toLower();
if (lower == "gstreamer") return Engine::GStreamer;
- else if (lower == "xine") return Engine::Xine;
else if (lower == "vlc") return Engine::VLC;
else return Engine::None;
}
@@ -36,7 +35,6 @@ Engine::EngineType EngineTypeFromName(QString enginename) {
QString EngineName(Engine::EngineType enginetype) {
switch (enginetype) {
case Engine::GStreamer: return QString("gstreamer");
- case Engine::Xine: return QString("xine");
case Engine::VLC: return QString("vlc");
case Engine::None:
default: return QString("None");
@@ -46,7 +44,6 @@ QString EngineName(Engine::EngineType enginetype) {
QString EngineDescription(Engine::EngineType enginetype) {
switch (enginetype) {
case Engine::GStreamer: return QString("GStreamer");
- case Engine::Xine: return QString("Xine");
case Engine::VLC: return QString("VLC");
case Engine::None:
default: return QString("None");
diff --git a/src/engine/xineengine.cpp b/src/engine/xineengine.cpp
deleted file mode 100644
index 1e842b9ef..000000000
--- a/src/engine/xineengine.cpp
+++ /dev/null
@@ -1,1014 +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
-#include
-#include
-
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "core/logging.h"
-#include
-#include "engine_fwd.h"
-#include "enginebase.h"
-#include "enginetype.h"
-#include "xineengine.h"
-#include "xinescope.h"
-
-#ifndef LLONG_MAX
-#define LLONG_MAX 9223372036854775807LL
-#endif
-
-// Define this to use xine in a more standard way
-//#define XINE_SAFE_MODE
-
-const char *XineEngine::kAutoOutput = "auto";
-
-XineEngine::XineEngine(TaskManager *task_manager)
- : EngineBase(),
- xine_(nullptr),
- audioport_(nullptr),
- stream_(nullptr),
- eventqueue_(nullptr),
- post_(nullptr),
- prune_(nullptr),
- preamp_(1.0),
- have_metadata_(false) {
-
- Q_UNUSED(task_manager);
-
- type_ = Engine::Xine;
- ReloadSettings();
-
-}
-
-XineEngine::~XineEngine() {
-
- Cleanup();
-
-}
-
-bool XineEngine::Init() {
-
- Cleanup();
- SetEnvironment();
-
- QMutexLocker locker(&init_mutex_);
- xine_ = xine_new();
- if (!xine_) {
- emit Error("Could not initialize xine.");
- return false;
- }
-
-#ifdef XINE_SAFE_MODE
- xine_engine_set_param(xine_, XINE_ENGINE_PARAM_VERBOSITY, 99);
-#endif
-
- xine_init(xine_);
-
-#if !defined(XINE_SAFE_MODE)
- prune_.reset(new PruneScopeThread(this));
- prune_->start();
-#endif
-
- return true;
-
-}
-
-void XineEngine::SetDevice() {
-
- if (device_.isValid()) {
- bool valid(false);
- xine_cfg_entry_t entry;
- switch (device_.type()) {
- case QVariant::String:
- if (device_.toString().isEmpty()) break;
- valid = true;
- xine_config_register_string(xine_, "audio.device.alsa_front_device", device_.toString().toUtf8().data(), "", "", 10, nullptr, nullptr);
- break;
- case QVariant::ByteArray:
- valid = true;
- xine_config_register_string(xine_, "audio.device.alsa_front_device", device_.toByteArray().data(), "", "", 10, nullptr, nullptr);
- break;
- default:
- qLog(Error) << "Unknown device type" << device_;
- break;
- }
- if (valid) {
- xine_config_lookup_entry(xine_, "audio.device.alsa_front_device", &entry);
- xine_config_update_entry(xine_, &entry);
- }
- }
- current_device_ = device_;
-
-}
-
-bool XineEngine::OpenAudioDriver() {
-
- 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 StateChanged(Engine::Error);
- emit FatalError();
- emit Error("Xine was unable to initialize any audio drivers.");
- return false;
- }
-
-#if !defined(XINE_SAFE_MODE)
- post_ = scope_plugin_new(xine_, audioport_);
- if (!post_) {
- xine_close_audio_driver(xine_, audioport_);
- audioport_ = nullptr;
- emit StateChanged(Engine::Error);
- emit FatalError();
- emit Error("Xine was unable to initialize any audio drivers.");
- return false;
- }
-#endif
-
- return true;
-
-}
-
-void XineEngine::CloseAudioDriver() {
-
- if (post_) {
- xine_post_dispose(xine_, post_);
- post_ = nullptr;
- }
-
- if (audioport_) {
- xine_close_audio_driver(xine_, audioport_);
- audioport_ = nullptr;
- }
-
-}
-
-bool XineEngine::CreateStream() {
-
- stream_ = xine_stream_new(xine_, audioport_, nullptr);
- if (!stream_) {
- CloseAudioDriver();
- emit Error("Could not create a new Xine stream.");
- return false;
- }
-
- if (eventqueue_) xine_event_dispose_queue(eventqueue_);
- eventqueue_ = xine_event_new_queue(stream_);
- xine_event_create_listener_thread(eventqueue_, &XineEngine::XineEventListener, reinterpret_cast(this));
-
-#ifndef XINE_SAFE_MODE
- xine_set_param(stream_, XINE_PARAM_METRONOM_PREBUFFER, 6000);
- xine_set_param(stream_, XINE_PARAM_IGNORE_VIDEO, 1);
-#endif
-
-#ifdef XINE_PARAM_EARLY_FINISHED_EVENT
- // Enable gapless playback
- xine_set_param(stream_, XINE_PARAM_EARLY_FINISHED_EVENT, 1);
- qLog(Debug) << "Gapless playback enabled.";
-#endif
-
- return true;
-
-}
-
-void XineEngine::CloseStream() {
-
- if (stream_)
- xine_close(stream_);
-
- if (eventqueue_) {
- xine_event_dispose_queue(eventqueue_);
- eventqueue_ = nullptr;
- }
-
- if (stream_) {
- xine_dispose(stream_);
- stream_ = nullptr;
- }
-
-}
-
-bool XineEngine::EnsureStream() {
-
- if (!audioport_) {
- bool result = OpenAudioDriver();
- if (!result) return false;
- }
- if (!stream_) return CreateStream();
- return true;
-
-}
-
-void XineEngine::Cleanup() {
-
- // Wait until the prune scope thread is done
- if (prune_) {
- prune_->exit();
- prune_->wait();
- }
- prune_.reset();
-
- CloseStream();
- CloseAudioDriver();
-
- 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 {
-
- if (!stream_) return Engine::Empty;
-
- switch(xine_get_status(stream_)) {
- case XINE_STATUS_PLAY:
- return xine_get_param(stream_, XINE_PARAM_SPEED) != XINE_SPEED_PAUSE ? Engine::Playing : Engine::Paused;
- case XINE_STATUS_IDLE:
- return Engine::Empty;
- case XINE_STATUS_STOP:
- default:
- return stream_url_.isEmpty() ? Engine::Empty : Engine::Idle;
- }
-
-}
-
-bool XineEngine::Load(const QUrl &stream_url, const QUrl &original_url, const Engine::TrackChangeFlags change, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec) {
-
- if (!EnsureStream()) return false;
-
- have_metadata_ = false;
-
- Engine::Base::Load(stream_url, original_url, change, force_stop_at_end, beginning_nanosec, end_nanosec);
-
- xine_close(stream_);
-
- int result = xine_open(stream_, stream_url.toString().toUtf8());
- if (result) {
-
-#if !defined(XINE_SAFE_MODE)
- xine_post_out_t *source = xine_get_audio_source(stream_);
- xine_post_in_t *target = (xine_post_in_t*)xine_post_input(post_, const_cast("audio in"));
- xine_post_wire(source, target);
-#endif
-
- return true;
- }
-
- DetermineAndShowErrorMessage();
- return false;
-
-}
-
-bool XineEngine::Play(const quint64 offset_nanosec) {
-
- if (!EnsureStream()) return false;
-
- int offset = (offset_nanosec / kNsecPerMsec);
- const bool has_audio = xine_get_stream_info(stream_, XINE_STREAM_INFO_HAS_AUDIO);
- const bool audio_handled = xine_get_stream_info(stream_, XINE_STREAM_INFO_AUDIO_HANDLED);
- if (!has_audio || !audio_handled) return false;
-
- int result = xine_play(stream_, 0, offset);
- if (result) {
- emit StateChanged(Engine::Playing);
- return true;
- }
- xine_close(stream_);
-
- DetermineAndShowErrorMessage();
- return false;
-
-}
-
-void XineEngine::Stop(const bool stop_after) {
-
- Q_UNUSED(stop_after);
-
- if (!stream_) return;
-
- xine_stop(stream_);
- xine_close(stream_);
- xine_set_param(stream_, XINE_PARAM_AUDIO_CLOSE_DEVICE, 1);
-
- CloseStream();
- CloseAudioDriver();
-
- emit StateChanged(Engine::Empty);
-
-}
-
-void XineEngine::Pause() {
-
- if (!stream_) return;
-
- int result = xine_get_param(stream_, XINE_PARAM_SPEED);
- if (result != XINE_SPEED_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);
- }
-
-}
-
-void XineEngine::Unpause() {
-
- if (!stream_) return;
-
- int result = xine_get_param(stream_, XINE_PARAM_SPEED);
- if (result == XINE_SPEED_PAUSE) {
- xine_set_param(stream_, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
- emit StateChanged(Engine::Playing);
- }
-
-}
-
-void XineEngine::Seek(const quint64 offset_nanosec) {
-
- if (!EnsureStream()) return;
-
- int offset = (offset_nanosec / kNsecPerMsec);
-
- int result = xine_get_param(stream_, XINE_PARAM_SPEED);
- if (result == XINE_SPEED_PAUSE) {
- xine_play(stream_, 0, offset);
- xine_set_param(stream_, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
- }
- else xine_play(stream_, 0, offset);
-
-}
-
-void XineEngine::SetVolumeSW(const uint vol) {
-
- if (!stream_) return;
- if (!volume_control_ && vol != 100) return;
- xine_set_param(stream_, XINE_PARAM_AUDIO_AMP_LEVEL, static_cast(vol * preamp_));
-
-}
-
-qint64 XineEngine::position_nanosec() const {
- if (state() == Engine::Empty) return 0;
- const qint64 result = (position() * kNsecPerMsec);
- return qint64(qMax(0ll, result));
-}
-
-qint64 XineEngine::length_nanosec() const {
- if (state() == Engine::Empty) return 0;
- const qint64 result = end_nanosec_ - beginning_nanosec_;
-
- if (result > 0) {
- return result;
- }
- else {
- // Get the length from the pipeline if we don't know.
- return (length() * kNsecPerMsec);
- }
-}
-
-EngineBase::OutputDetailsList XineEngine::GetOutputsList() const {
-
- OutputDetailsList ret;
-
- PluginDetailsList plugins = GetPluginList();
- for (const PluginDetails &plugin : plugins) {
- OutputDetails output;
- output.name = plugin.name;
- output.description = plugin.description;
- if (plugin.name == "auto") output.iconname = "soundcard";
- else if ((plugin.name == "alsa")||(plugin.name == "oss")) output.iconname = "alsa";
- else if (plugin.name== "jack") output.iconname = "jack";
- else if (plugin.name == "pulseaudio") output.iconname = "pulseaudio";
- else if (plugin.name == "bluetooth") output.iconname = "bluetooth";
- else if (plugin.name == "file") output.iconname = "document-new";
- else output.iconname = "soundcard";
- ret.append(output);
- }
-
- return ret;
-}
-
-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");
-}
-
-bool XineEngine::ALSADeviceSupport(const QString &output) {
- return (output == "alsa");
-}
-
-void XineEngine::ReloadSettings() {
-
- Engine::Base::ReloadSettings();
-
- if (output_.isEmpty()) output_ = DefaultOutput();
-
-}
-
-void XineEngine::SetEnvironment() {
-
-#ifdef Q_OS_WIN
- putenv(QString("XINE_PLUGIN_PATH=" + QCoreApplication::applicationDirPath() + "/xine-plugins").toLatin1().constData());
-#endif
-
-#ifdef Q_OS_MACOS
- setenv("XINE_PLUGIN_PATH", QString(QCoreApplication::applicationDirPath() + "/../PlugIns/xine").toLatin1().constData(), 1);
-#endif
-
-}
-
-uint XineEngine::length() const {
-
- if (!stream_) return 0;
-
- // Xine often delivers nonsense values for VBR files and such, so we only use the length for remote files
-
- if (stream_url_.isLocalFile()) return 0;
- else {
- int pos = 0, time = 0, length = 0;
-
- xine_get_pos_length(stream_, &pos, &time, &length);
- if (length < 0) length=0;
-
- return length;
- }
-
-}
-
-uint XineEngine::position() const {
-
- if (state() == Engine::Empty) return 0;
-
- int pos = 0, time = 0, length = 0;
-
- // Workaround for problems when you seek too quickly, see BUG 99808
- //int tmp = 0, i = 0;
- //while (++i < 4) {
- xine_get_pos_length(stream_, &pos, &time, &length);
- //if (time > tmp) break;
- //usleep(100000);
- //}
-
- if (state() != Engine::Idle && state() != Engine::Empty && !have_metadata_ && time > 0) {
- FetchMetaData();
- }
-
- return time;
-
-}
-
-bool XineEngine::CanDecode(const QUrl &url) {
-
- static QStringList list;
-
- if (list.isEmpty()) {
-
- QMutexLocker locker(&const_cast(this)->init_mutex_);
-
- if (list.isEmpty()) {
- char *exts = xine_get_file_extensions(xine_);
- list = QString(exts).split(' ');
- free(exts);
- exts = nullptr;
- // Images
- list.removeAll("png");
- list.removeAll("jpg");
- list.removeAll("jpeg");
- list.removeAll("gif");
- list.removeAll("ilbm");
- list.removeAll("iff");
- // Subtitles
- list.removeAll("asc");
- list.removeAll("txt");
- list.removeAll("sub");
- list.removeAll("srt");
- list.removeAll("smi");
- list.removeAll("ssa");
- // HACK: we also check for m4a because xine plays them but for some reason doesn't return the extension
- if (!list.contains("m4a"))
- list << "m4a";
- }
- }
-
- if (url.scheme() == "cdda") return true;
-
- QString path = url.path();
-
- // Partial downloads from Konqi and other browsers tend to have a .part extension
- if (path.endsWith(".part")) path = path.left(path.length() - 5);
-
- const QString ext = path.mid(path.lastIndexOf('.') + 1).toLower();
-
- return list.contains(ext);
-
-}
-
-void XineEngine::SetEqualizerEnabled(const bool enabled) {
-
- if (!stream_) return;
-
- equalizer_enabled_ = enabled;
-
- if (!enabled) {
- QList gains;
- for (uint x = 0; x < 10; x++)
- gains << -101; // sets eq gains to zero.
-
- SetEqualizerParameters(0, gains);
- }
-
-}
-
-/*
- Sets the eq params for xine engine - have to rescale eq params to fitting range (adapted from kaffeine and xfmedia)
-
- preamp:
- pre: (-100..100)
- post: (0.1..1.9) - this is not really a preamp but we use the xine preamp parameter for our normal volume. so we make a postamp.
-
- gains:
- pre: (-100..100)
- post: (1..200) - (1 = down, 100 = middle, 200 = up, 0 = off)
-*/
-void XineEngine::SetEqualizerParameters(const int preamp, const QList &gains) {
-
- if (!stream_) return;
-
- equalizer_gains_ = gains;
- int_preamp_ = preamp;
- QList::ConstIterator it = gains.begin();
-
- xine_set_param(stream_, XINE_PARAM_EQ_30HZ, int((*it)*0.995 + 100));
- xine_set_param(stream_, XINE_PARAM_EQ_60HZ, int((*++it)*0.995 + 100));
- xine_set_param(stream_, XINE_PARAM_EQ_125HZ, int((*++it)*0.995 + 100));
- xine_set_param(stream_, XINE_PARAM_EQ_250HZ, int((*++it)*0.995 + 100));
- xine_set_param(stream_, XINE_PARAM_EQ_500HZ, int((*++it)*0.995 + 100));
- xine_set_param(stream_, XINE_PARAM_EQ_1000HZ, int((*++it)*0.995 + 100));
- xine_set_param(stream_, XINE_PARAM_EQ_2000HZ, int((*++it)*0.995 + 100));
- xine_set_param(stream_, XINE_PARAM_EQ_4000HZ, int((*++it)*0.995 + 100));
- xine_set_param(stream_, XINE_PARAM_EQ_8000HZ, int((*++it)*0.995 + 100));
- xine_set_param(stream_, XINE_PARAM_EQ_16000HZ, int((*++it)*0.995 + 100));
-
- preamp_ = (preamp - 0.1 * preamp + 100) / 100.0;
- SetVolume(volume_);
-
-}
-
-void XineEngine::XineEventListener(void *p, const xine_event_t *event) {
-
- if (!p) return;
- XineEngine *engine = reinterpret_cast(p);
-
- switch(event->type) {
- case XINE_EVENT_UI_SET_TITLE:
- qLog(Debug) << "XINE_EVENT_UI_SET_TITLE";
- engine->FetchMetaData();
- break;
-
- case XINE_EVENT_UI_PLAYBACK_FINISHED:
- qLog(Debug) << "XINE_EVENT_UI_PLAYBACK_FINISHED";
- emit engine->TrackEnded();
- break;
-
- case XINE_EVENT_PROGRESS:
- {
- xine_progress_data_t *pd = reinterpret_cast(event->data);
- QString msg = QString("%1 %2%").arg(QString::fromUtf8(pd->description)).arg(QString::number(pd->percent) + QLocale::system().percent());
- //qLog(Debug) << "Xine:" << msg;
- }
- break;
-
- case XINE_EVENT_MRL_REFERENCE_EXT:
- {
- // Xine has read the stream and found it actually links to something else so we need to play that instead
- QString message = QString::fromUtf8(static_cast(event->data)->mrl);
- //emit StatusText(QString("Redirecting to: ").arg(*message));
- engine->Load(QUrl(message), engine->original_url_, Engine::Auto, false, 0, 0);
- engine->Play(0);
- }
- break;
-
- case XINE_EVENT_UI_MESSAGE:
- {
- qLog(Debug) << "XINE_EVENT_UI_MESSAGE";
-
- xine_ui_message_data_t *data = reinterpret_cast(event->data);
- QString message;
-
- switch (data->type) {
-
- case XINE_MSG_NO_ERROR:
- {
- // Series of \0 separated strings, terminated with a \0\0
- char str[2000];
- char *str_p = str;
- for (char *msg = data->messages; !(*msg == '\0' && *(msg+1) == '\0'); ++msg, ++str_p)
- *str_p = *msg == '\0' ? '\n' : *msg;
- *str_p = '\0';
- qLog(Debug) << "Xine:" << str;
- break;
- }
-
- case XINE_MSG_ENCRYPTED_SOURCE:
- message = "Source is encrypted.";
- if (data->explanation) {
- message += " : ";
- message += QString::fromUtf8(reinterpret_cast(data) + data->parameters);
- }
- emit engine->StateChanged(Engine::Error);
- emit engine->InvalidSongRequested(engine->stream_url_);
- break;
- case XINE_MSG_UNKNOWN_HOST:
- message = "The host is unknown.";
- if (data->explanation) {
- message += " : ";
- message += QString::fromUtf8(reinterpret_cast(data) + data->parameters);
- }
- emit engine->StateChanged(Engine::Error);
- emit engine->InvalidSongRequested(engine->stream_url_);
- break;
- case XINE_MSG_UNKNOWN_DEVICE:
- message = "The device name you specified seems invalid.";
- if (data->explanation) {
- message += " : ";
- message += QString::fromUtf8(reinterpret_cast(data) + data->parameters);
- }
- emit engine->StateChanged(Engine::Error);
- emit engine->InvalidSongRequested(engine->stream_url_);
- break;
- case XINE_MSG_NETWORK_UNREACHABLE:
- message = "The network appears unreachable.";
- if (data->explanation) {
- message += " : ";
- message += QString::fromUtf8(reinterpret_cast(data) + data->parameters);
- }
- emit engine->StateChanged(Engine::Error);
- emit engine->InvalidSongRequested(engine->stream_url_);
- break;
- case XINE_MSG_AUDIO_OUT_UNAVAILABLE:
- message = "Audio output unavailable; the device is busy.";
- if (data->explanation) {
- message += " : ";
- message += QString::fromUtf8(reinterpret_cast(data) + data->parameters);
- }
- emit engine->StateChanged(Engine::Error);
- emit engine->FatalError();
- break;
- case XINE_MSG_CONNECTION_REFUSED:
- message = "Connection refused.";
- if (data->explanation) {
- message += " : ";
- message += QString::fromUtf8(reinterpret_cast(data) + data->parameters);
- }
- emit engine->StateChanged(Engine::Error);
- emit engine->InvalidSongRequested(engine->stream_url_);
- break;
- case XINE_MSG_FILE_NOT_FOUND:
- message = "File not found.";
- if (data->explanation) {
- message += " : ";
- message += QString::fromUtf8(reinterpret_cast(data) + data->parameters);
- }
- emit engine->StateChanged(Engine::Error);
- emit engine->InvalidSongRequested(engine->stream_url_);
- break;
- case XINE_MSG_PERMISSION_ERROR:
- message = "Access denied.";
- if (data->explanation) {
- message += " : ";
- message += QString::fromUtf8(reinterpret_cast(data) + data->parameters);
- }
- emit engine->StateChanged(Engine::Error);
- emit engine->InvalidSongRequested(engine->stream_url_);
- break;
- case XINE_MSG_READ_ERROR:
- message = "Read error.";
- if (data->explanation) {
- message += " : ";
- message += QString::fromUtf8(reinterpret_cast(data) + data->parameters);
- }
- emit engine->StateChanged(Engine::Error);
- emit engine->InvalidSongRequested(engine->stream_url_);
- break;
- case XINE_MSG_LIBRARY_LOAD_ERROR:
- message = "A problem occurred while loading a library or decoder.";
- if (data->explanation) {
- message += " : ";
- message += QString::fromUtf8(reinterpret_cast(data) + data->parameters);
- }
- emit engine->StateChanged(Engine::Error);
- emit engine->FatalError();
- break;
- case XINE_MSG_GENERAL_WARNING:
- message = "General Warning";
- if (data->explanation) {
- message += ": ";
- message += QString::fromUtf8(reinterpret_cast(data) + data->explanation);
- }
- else message += ".";
- break;
- case XINE_MSG_SECURITY:
- message = "Security Warning";
- if (data->explanation) {
- message += ": ";
- message += QString::fromUtf8(reinterpret_cast(data) + data->explanation);
- }
- else message += ".";
- break;
- default:
- message = "Unknown Error";
- if (data->explanation) {
- message += ": ";
- message += QString::fromUtf8(reinterpret_cast(data) + data->explanation);
- }
- else message += ".";
- break;
- }
- emit engine->Error(message);
- }
- }
-
-}
-
-Engine::SimpleMetaBundle XineEngine::FetchMetaData() const {
-
- Engine::SimpleMetaBundle bundle;
- bundle.url = original_url_;
- bundle.title = QString::fromUtf8(xine_get_meta_info(stream_, XINE_META_INFO_TITLE));
- bundle.artist = QString::fromUtf8(xine_get_meta_info(stream_, XINE_META_INFO_ARTIST));
- bundle.album = QString::fromUtf8(xine_get_meta_info(stream_, XINE_META_INFO_ALBUM));
- bundle.comment = QString::fromUtf8(xine_get_meta_info(stream_, XINE_META_INFO_COMMENT));
- bundle.genre = QString::fromUtf8(xine_get_meta_info(stream_, XINE_META_INFO_GENRE));
- bundle.length = 0;
-
- bundle.year = QString::fromUtf8(xine_get_meta_info(stream_, XINE_META_INFO_YEAR)).toInt();
- bundle.track = QString::fromUtf8(xine_get_meta_info(stream_, XINE_META_INFO_TRACK_NUMBER)).toInt();
-
- bundle.samplerate = xine_get_stream_info(stream_, XINE_STREAM_INFO_AUDIO_SAMPLERATE);
- bundle.bitdepth = xine_get_stream_info(stream_, XINE_STREAM_INFO_AUDIO_BITS);
- bundle.bitrate = xine_get_stream_info(stream_, XINE_STREAM_INFO_AUDIO_BITRATE) / 1000;
-
- qLog(Debug) << "Metadata received" << bundle.title
- << bundle.artist
- << bundle.album
- << bundle.comment
- << bundle.genre
- << bundle.length
- << bundle.year
- << bundle.track
- << bundle.samplerate
- << bundle.bitdepth
- << bundle.bitrate;
-
- current_bundle_ = bundle;
- XineEngine *engine = const_cast(this);
- engine->have_metadata_ = true;
- emit engine->MetaData(bundle);
-
- return bundle;
-
-}
-
-void XineEngine::DetermineAndShowErrorMessage() {
-
- int errno;
- QString message;
-
- errno = xine_get_error(stream_);
- switch (errno) {
-
- case XINE_ERROR_NO_INPUT_PLUGIN:
- message = "No suitable input plugin. This often means that the url's protocol is not supported. Network failures are other possible causes.";
- break;
-
- case XINE_ERROR_NO_DEMUX_PLUGIN:
- message = "No suitable demux plugin. This often means that the file format is not supported.";
- break;
-
- case XINE_ERROR_DEMUX_FAILED:
- message = "Demuxing failed.";
- break;
-
- case XINE_ERROR_INPUT_FAILED:
- message = "Could not open file.";
- break;
-
- case XINE_ERROR_MALFORMED_MRL:
- message = "The location is malformed.";
- break;
-
- case XINE_ERROR_NONE:
- // Xine is thick. Xine doesn't think there is an error but there may be! We check for other errors below.
- default:
- emit FatalError();
- int result = xine_get_stream_info(stream_, XINE_STREAM_INFO_AUDIO_HANDLED);
- if (!result) {
- // xine can read the plugin but it didn't find any codec
- // THUS xine=daft for telling us it could handle the format in canDecode!
- message = "There is no available decoder.";
- QString const ext = QFileInfo(stream_url_.path()).completeSuffix();
- break;
- }
- result = xine_get_stream_info(stream_, XINE_STREAM_INFO_HAS_AUDIO);
- if (!result) {
- message = "There is no audio channel!";
- break;
- }
- break;
- }
-
- emit Error(message);
-
-}
-
-const Engine::Scope &XineEngine::scope(const int chunk_length) {
-
- Q_UNUSED(chunk_length);
-
- if (!post_ || !stream_ || xine_get_status(stream_) != XINE_STATUS_PLAY)
- return scope_;
-
- MyNode *const myList = scope_plugin_list(post_);
- const int myChannels = scope_plugin_channels(post_);
- int scopeidx = 0;
-
- if (myChannels > 2) return scope_;
-
- for (int n, frame = 0; frame < 512;) {
-
- MyNode *best_node = 0;
-
- for (MyNode *node = myList->next; node != myList; node = node->next, log_buffer_count_++)
- if (node->vpts <= current_vpts_ && (!best_node || node->vpts > best_node->vpts))
- best_node = node;
-
- if (!best_node || best_node->vpts_end < current_vpts_) {
- log_no_suitable_buffer_++;
- break;
- }
-
- int64_t diff = current_vpts_;
- diff -= best_node->vpts;
- diff *= 1<<16;
- diff /= 32768;
-
- const int16_t *data16 = best_node->mem;
- data16 += diff;
-
- diff += diff % myChannels; // Important correction to ensure we don't overflow the buffer
- diff /= myChannels; // Use units of frames, not samples
-
- // Calculate the number of available samples in this buffer
- n = best_node->num_frames;
- n -= diff;
- n += frame; //clipping for # of frames we need
-
- if (n > 512)
- n = 512; // We don't want more than 512 frames
-
- for (int c; frame < n; ++frame, data16 += myChannels) {
- for (c = 0; c < myChannels; ++c) {
- // We now give interleaved pcm to the scope
- scope_[scopeidx++] = data16[c];
- if (myChannels == 1) // Duplicate mono samples
- scope_[scopeidx++] = data16[c];
- }
- }
-
- current_vpts_ = best_node->vpts_end;
- current_vpts_++; // FIXME: Needs to be done for some reason, or you get situations where it uses same buffer again and again
- }
-
- log_scope_call_count_++;
-
- return scope_;
-
-}
-
-void XineEngine::PruneScope() {
-
- if (!stream_) return;
-
- // Here we prune the buffer list regularly
-
- MyNode *myList = scope_plugin_list(post_);
-
- if (!myList) return;
-
- // We operate on a subset of the list for thread-safety
- MyNode * const first_node = myList->next;
- MyNode const * const list_end = myList;
-
- current_vpts_ = (xine_get_status(stream_) == XINE_STATUS_PLAY) ? xine_get_current_vpts(stream_)
- : LLONG_MAX; //if state is not playing OR paused, empty the list
- //: std::numeric_limits::max(); //TODO Don't support crappy gcc 2.95
-
- for (MyNode *prev = first_node, *node = first_node->next; node != list_end; node = node->next) {
- //we never delete first_node this maintains thread-safety
- if (node->vpts_end < current_vpts_) {
- prev->next = node->next;
-
- free(node->mem);
- free(node);
-
- node = prev;
- }
-
- prev = node;
- }
-}
-
-PruneScopeThread::PruneScopeThread(XineEngine *parent) : engine_(parent) {}
-
-void PruneScopeThread::run() {
-
- QTimer timer;
- connect(&timer, SIGNAL(timeout()), engine_, SLOT(PruneScope()), Qt::DirectConnection);
- timer.start(1000);
-
- exec();
-
-}
-
-EngineBase::PluginDetailsList XineEngine::GetPluginList() const {
-
- PluginDetailsList ret;
- const char *const *plugins = xine_list_audio_output_plugins(xine_);
-
- {
- PluginDetails details;
- details.name = "auto";
- details.description = "Automatically detected";
- ret << details;
- }
-
- for (int i =0 ; plugins[i] ; ++i) {
- PluginDetails details;
- details.name = QString::fromUtf8(plugins[i]);
- if (details.name == "alsa") details.description = "ALSA audio output";
- else if (details.name == "oss") details.description = "OSS audio output";
- else if (details.name == "pulseaudio") details.description = "PulseAudio audio output";
- else if (details.name == "file") details.description = "File audio output";
- else if (details.name == "none") details.description = "None";
- else details.description = QString::fromUtf8(plugins[i]);
- ret << details;
- }
-
- return ret;
-
-}
-
-
diff --git a/src/engine/xineengine.h b/src/engine/xineengine.h
deleted file mode 100644
index 75cb7a8c9..000000000
--- a/src/engine/xineengine.h
+++ /dev/null
@@ -1,154 +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 XINEENGINE_H
-#define XINEENGINE_H
-
-#include "config.h"
-
-#ifndef XINE_ENGINE_INTERNAL
-# define XINE_ENGINE_INTERNAL
-#endif
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "engine_fwd.h"
-#include "enginebase.h"
-
-class TaskManager;
-class PruneScopeThread;
-
-class XineEngine : public Engine::Base {
- Q_OBJECT
-
- public:
- explicit XineEngine(TaskManager *task_manager);
- ~XineEngine() override;
-
- bool Init() override;
- Engine::State state() const override;
- bool Load(const QUrl &stream_url, const QUrl &original_url, Engine::TrackChangeFlags change, bool force_stop_at_end, quint64 beginning_nanosec, qint64 end_nanosec) override;
- bool Play(quint64 offset_nanosec) override;
- void Stop(bool stop_after = false) override;
- void Pause() override;
- void Unpause() override;
- void Seek(quint64 offset_nanosec) override;
- void SetVolumeSW(uint) override;
-
- qint64 position_nanosec() const override;
- qint64 length_nanosec() const override;
-
- const Engine::Scope& scope(int chunk_length);
-
- OutputDetailsList GetOutputsList() const override;
- bool ValidOutput(const QString &output) override;
- QString DefaultOutput() override { return "auto"; }
- bool CustomDeviceSupport(const QString &output) override;
- bool ALSADeviceSupport(const QString &output) override;
-
- void ReloadSettings() override;
-
- bool CanDecode(const QUrl &);
-
- void SetEqualizerEnabled(bool enabled) override;
- void SetEqualizerParameters(int preamp, const QList&) override;
-
- // Simple accessors
-
- xine_stream_t *stream() { return stream_; }
- float preamp() { return preamp_; }
-
- private:
- static const char *kAutoOutput;
-
- QString current_output_;
- QVariant current_device_;
-
- xine_t *xine_;
- xine_audio_port_t *audioport_;
- xine_stream_t *stream_;
- xine_event_queue_t *eventqueue_;
- xine_post_t *post_;
- std::unique_ptr prune_;
-
- float preamp_;
-
- QUrl stream_url_;
- QUrl original_url_;
- bool have_metadata_;
-
- uint log_buffer_count_ = 0;
- uint log_scope_call_count_ = 1; // Prevent divideByZero
- uint log_no_suitable_buffer_ = 0;
-
- int int_preamp_;
- QMutex init_mutex_;
- int64_t current_vpts_;
- QList equalizer_gains_;
-
- mutable Engine::SimpleMetaBundle current_bundle_;
-
- void SetEnvironment();
-
- void Cleanup();
- void SetDevice();
- bool OpenAudioDriver();
- void CloseAudioDriver();
- bool CreateStream();
- void CloseStream();
- bool EnsureStream();
-
- uint length() const;
- uint position() const;
-
- static void XineEventListener(void*, const xine_event_t*);
-
- void DetermineAndShowErrorMessage();
- Engine::SimpleMetaBundle FetchMetaData() const;
-
- PluginDetailsList GetPluginList() const;
-
- private slots:
- void PruneScope();
-
- signals:
- void InfoMessage(const QString&);
-};
-
-class PruneScopeThread : public QThread {
- public:
- PruneScopeThread(XineEngine *parent);
-
- protected:
- void run();
-
- private:
- XineEngine *engine_;
-
-};
-
-#endif
diff --git a/src/engine/xinescope.c b/src/engine/xinescope.c
deleted file mode 100644
index 307c64ddc..000000000
--- a/src/engine/xinescope.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* Author: Max Howell , (C) 2004
- Copyright: See COPYING file that comes with this distribution
-
- This has to be a c file or for some reason it won't link! (GCC 3.4.1)
-
-*/
-
-/* need access to port_ticket */
-#ifndef XINE_ENGINE_INTERNAL
-# define XINE_ENGINE_INTERNAL
-#endif
-
-#include "config.h"
-
-#include "xinescope.h"
-#include
-#include
-
-typedef struct scope_plugin_s scope_plugin_t;
-
-struct scope_plugin_s {
- post_plugin_t post;
-
- metronom_t metronom;
- int channels;
- MyNode *list;
-};
-
-/*************************
- * post plugin functions *
- *************************/
-
-static int scope_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, uint32_t bits, uint32_t rate, int mode) {
-
- #define port ((post_audio_port_t*)port_gen)
- #define this ((scope_plugin_t*)((post_audio_port_t*)port_gen)->post)
-
- _x_post_rewire((post_plugin_t*)port->post);
- _x_post_inc_usage(port);
-
- port->stream = stream;
- port->bits = bits;
- port->rate = rate;
- port->mode = mode;
-
- this->channels = _x_ao_mode2channels(mode);
-
- return port->original_port->open(port->original_port, stream, bits, rate, mode);
-}
-
-static void scope_port_close(xine_audio_port_t *port_gen, xine_stream_t *stream) {
-
- MyNode *node;
-
- /* ensure the buffers are deleted during the next XineEngine::timerEvent() */
- for(node = this->list->next; node != this->list; node = node->next)
- node->vpts = node->vpts_end = -1;
-
- port->stream = NULL;
- port->original_port->close(port->original_port, stream);
-
- _x_post_dec_usage(port);
-}
-
-static void scope_port_put_buffer(xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream) {
-/* FIXME With 8-bit samples the scope won't work correctly. For a special 8-bit code path, the sample size could be checked like this: if(port->bits == 8) */
-
- const int num_samples = buf->num_frames * this->channels;
- metronom_t *myMetronom = &this->metronom;
- MyNode *new_node;
-
- /* I keep my own metronom because xine wouldn't for some reason */
- memcpy(&this->metronom, stream->metronom, sizeof(metronom_t));
-
- new_node = (MyNode *) malloc(sizeof(MyNode));
- new_node->vpts = myMetronom->got_audio_samples(myMetronom, buf->vpts, buf->num_frames);
- new_node->num_frames = buf->num_frames;
- new_node->mem = (int16_t *) malloc(num_samples * 2);
- memcpy(new_node->mem, buf->mem, num_samples * 2);
-
- {
- int64_t
- K = 32768; /*smpls = 1<<16 samples*/
- K *= num_samples;
- K /= (1<<16);
- K += new_node->vpts;
-
- new_node->vpts_end = K;
- }
-
- port->original_port->put_buffer(port->original_port, buf, stream);
-
- /* Finally we should append the current buffer to the list
- * This is thread-safe due to the way we handle the list in the GUI thread */
- new_node->next = this->list->next;
- this->list->next = new_node;
-
- #undef port
- #undef this
-}
-
-static void scope_dispose(post_plugin_t *post) {
-
- MyNode *list = ((scope_plugin_t*)post)->list;
- MyNode *prev;
- MyNode *node = list;
-
- /* Free all elements of the list (a ring buffer) */
- do {
- prev = node->next;
-
- free(node->mem);
- free(node);
-
- node = prev;
- }
- while(node != list);
-
-
- free(post);
-}
-
-
-/************************
- * plugin init function *
- ************************/
-
-xine_post_t *scope_plugin_new(xine_t *xine, xine_audio_port_t *audio_target) {
-
- scope_plugin_t *scope_plugin = (scope_plugin_t *) calloc(1, sizeof(scope_plugin_t));
- post_plugin_t *post_plugin = (post_plugin_t *)scope_plugin;
-
- {
- post_in_t *input;
- post_out_t *output;
- post_audio_port_t *port;
-
- _x_post_init(post_plugin, 1, 0);
-
- port = _x_post_intercept_audio_port(post_plugin, audio_target, &input, &output);
- port->new_port.open = scope_port_open;
- port->new_port.close = scope_port_close;
- port->new_port.put_buffer = scope_port_put_buffer;
-
- post_plugin->xine_post.audio_input[0] = &port->new_port;
- post_plugin->xine_post.type = PLUGIN_POST;
-
- post_plugin->dispose = scope_dispose;
- }
-
- // code is straight from xine_init_post() can't use that function as it only dlopens the plugins and our plugin is statically linked in
-
- post_plugin->running_ticket = xine->port_ticket;
- post_plugin->xine = xine;
-
- /* scope_plugin_t init */
- scope_plugin->list = (MyNode *) calloc(1, sizeof(MyNode));
- scope_plugin->list->next = scope_plugin->list;
-
- return &post_plugin->xine_post;
-}
-
-MyNode *scope_plugin_list(void *post) {
- return ((scope_plugin_t*)post)->list;
-}
-
-int scope_plugin_channels(void *post) {
- return ((scope_plugin_t*)post)->channels;
-}
-
-metronom_t* scope_plugin_metronom(void *post) {
- return &((scope_plugin_t*)post)->metronom;
-}
diff --git a/src/engine/xinescope.h b/src/engine/xinescope.h
deleted file mode 100644
index 2f57d1c6c..000000000
--- a/src/engine/xinescope.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Author: Max Howell , (C) 2004
- Copyright: See COPYING file that comes with this distribution
-
- This has to be a c file or for some reason it won't link! (GCC 3.4.1)
-*/
-
-#ifndef XINESCOPE_H
-#define XINESCOPE_H
-
-/* need access to some stuff for scope time stamping */
-#ifndef METRONOM_INTERNAL
-# define METRONOM_INTERNAL
-#endif
-
-#include "config.h"
-
-#include
-#include
-
-typedef struct my_node_s MyNode;
-
-struct my_node_s {
- MyNode *next;
- int16_t *mem;
- int num_frames;
- int64_t vpts;
- int64_t vpts_end;
-};
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
- xine_post_t *scope_plugin_new( xine_t*, xine_audio_port_t* );
-
- /* we sacrifice type-safety here because some GCCs appear broken and choke on redefining the xine_post_t typedef */
-
- MyNode *scope_plugin_list(void*);
- int scope_plugin_channels(void*);
- metronom_t *scope_plugin_metronom(void*);
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/settings/backendsettingspage.cpp b/src/settings/backendsettingspage.cpp
index 1ce06305e..d1c641d55 100644
--- a/src/settings/backendsettingspage.cpp
+++ b/src/settings/backendsettingspage.cpp
@@ -94,9 +94,6 @@ void BackendSettingsPage::Load() {
#ifdef HAVE_GSTREAMER
ui_->combobox_engine->addItem(IconLoader::Load("gstreamer"), EngineDescription(Engine::GStreamer), QVariant::fromValue(Engine::GStreamer));
#endif
-#ifdef HAVE_XINE
- ui_->combobox_engine->addItem(IconLoader::Load("xine"), EngineDescription(Engine::Xine), QVariant::fromValue(Engine::Xine));
-#endif
#ifdef HAVE_VLC
ui_->combobox_engine->addItem(IconLoader::Load("vlc"), EngineDescription(Engine::VLC), QVariant::fromValue(Engine::VLC));
#endif