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