2018-02-27 18:06:05 +01:00
|
|
|
/***************************************************************************
|
2018-06-28 01:15:32 +02:00
|
|
|
* Copyright (C) 2017-2018 Jonas Kvinge <jonas@jkvinge.net> *
|
|
|
|
* Copyright (C) 2005 Christophe Thommeret <hftom@free.fr> *
|
|
|
|
* (C) 2005 Ian Monroe <ian@monroe.nu> *
|
|
|
|
* (C) 2005-2006 Mark Kretschmann <markey@web.de> *
|
|
|
|
* (C) 2004-2005 Max Howell <max.howell@methylblue.com> *
|
|
|
|
* (C) 2003-2004 J. Kofler <kaffeine@gmx.net> *
|
2018-02-27 18:06:05 +01:00
|
|
|
* *
|
|
|
|
* 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. *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
#ifndef XINEENGINE_H
|
|
|
|
#define XINEENGINE_H
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
#include <memory>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <xine.h>
|
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QtGlobal>
|
|
|
|
#include <QObject>
|
|
|
|
#include <QMutex>
|
2018-02-27 18:06:05 +01:00
|
|
|
#include <QThread>
|
|
|
|
#include <QEvent>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QList>
|
|
|
|
#include <QString>
|
|
|
|
#include <QUrl>
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
#include "engine_fwd.h"
|
|
|
|
#include "enginebase.h"
|
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
using std::shared_ptr;
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
class TaskManager;
|
2018-06-28 01:15:32 +02:00
|
|
|
class PruneScopeThread;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
class XineEvent : public QEvent {
|
|
|
|
public:
|
|
|
|
enum EventType {
|
2018-06-28 01:15:32 +02:00
|
|
|
PlaybackFinished,
|
2018-02-27 18:06:05 +01:00
|
|
|
InfoMessage,
|
|
|
|
StatusMessage,
|
|
|
|
MetaInfoChanged,
|
|
|
|
Redirecting,
|
|
|
|
LastFMTrackChanged,
|
|
|
|
};
|
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
XineEvent(EventType type, void* data = nullptr) : QEvent(QEvent::Type(type)), data_(data) {}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
void setData(void *data) { data_ = data; }
|
|
|
|
void *data() const { return data_; }
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
private:
|
2018-06-28 01:15:32 +02:00
|
|
|
void *data_;
|
2018-02-27 18:06:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class XineEngine : public Engine::Base {
|
|
|
|
Q_OBJECT
|
|
|
|
|
2018-07-01 01:29:52 +02:00
|
|
|
public:
|
2018-06-28 01:15:32 +02:00
|
|
|
XineEngine(TaskManager *task_manager);
|
|
|
|
~XineEngine();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
bool Init();
|
|
|
|
Engine::State state() const;
|
2018-09-22 23:13:56 +02:00
|
|
|
bool Load(const QUrl &media_url, const QUrl &original_url, Engine::TrackChangeFlags change, bool force_stop_at_end, quint64 beginning_nanosec, qint64 end_nanosec);
|
2018-06-28 01:15:32 +02:00
|
|
|
bool Play(quint64 offset_nanosec);
|
|
|
|
void Stop(bool stop_after = false);
|
|
|
|
void Pause();
|
|
|
|
void Unpause();
|
|
|
|
void Seek(quint64 offset_nanosec);
|
|
|
|
void SetVolumeSW(uint );
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
qint64 position_nanosec() const;
|
|
|
|
qint64 length_nanosec() const;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
const Engine::Scope& scope(int chunk_length);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
OutputDetailsList GetOutputsList() const;
|
2018-07-01 01:29:52 +02:00
|
|
|
bool ValidOutput(const QString &output);
|
|
|
|
QString DefaultOutput() { return "auto"; }
|
|
|
|
bool CustomDeviceSupport(const QString &output);
|
2018-09-21 23:29:00 +02:00
|
|
|
bool ALSADeviceSupport(const QString &output);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
void ReloadSettings();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
bool CanDecode(const QUrl &);
|
2018-07-01 01:29:52 +02:00
|
|
|
bool CreateStream();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
void SetEqualizerEnabled(bool enabled);
|
|
|
|
void SetEqualizerParameters(int preamp, const QList<int>&);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
// Simple accessors
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
xine_stream_t *stream() { return stream_; }
|
|
|
|
float preamp() { return preamp_; }
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-07-01 01:29:52 +02:00
|
|
|
private:
|
2018-06-28 01:15:32 +02:00
|
|
|
static const char *kAutoOutput;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-07-01 01:29:52 +02:00
|
|
|
QString current_output_;
|
|
|
|
QVariant current_device_;
|
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
xine_t *xine_;
|
|
|
|
xine_stream_t *stream_;
|
|
|
|
xine_audio_port_t *audioport_;
|
|
|
|
xine_event_queue_t *eventqueue_;
|
|
|
|
xine_post_t *post_;
|
|
|
|
float preamp_;
|
|
|
|
std::unique_ptr<PruneScopeThread> prune_;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-09-22 23:13:56 +02:00
|
|
|
QUrl media_url_;
|
|
|
|
QUrl original_url_;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
static int last_error_;
|
|
|
|
static time_t last_error_time_;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
uint log_buffer_count_ = 0;
|
|
|
|
uint log_scope_call_count_ = 1; // Prevent divideByZero
|
|
|
|
uint log_no_suitable_buffer_ = 0;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
int int_preamp_;
|
|
|
|
QMutex init_mutex_;
|
|
|
|
int64_t current_vpts_;
|
|
|
|
QList<int> equalizer_gains_;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
mutable Engine::SimpleMetaBundle current_bundle_;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-07-01 01:29:52 +02:00
|
|
|
void SetEnvironment();
|
|
|
|
|
|
|
|
void Cleanup();
|
|
|
|
bool EnsureStream();
|
|
|
|
void SetDevice();
|
2018-10-02 00:38:52 +02:00
|
|
|
|
2018-07-01 01:29:52 +02:00
|
|
|
uint length() const;
|
|
|
|
uint position() const;
|
2018-10-02 00:38:52 +02:00
|
|
|
|
2018-07-01 01:29:52 +02:00
|
|
|
bool MetaDataForUrl(const QUrl &url, Engine::SimpleMetaBundle &b);
|
|
|
|
bool GetAudioCDContents(const QString &device, QList<QUrl> &urls);
|
|
|
|
bool FlushBuffer();
|
|
|
|
|
|
|
|
static void XineEventListener(void*, const xine_event_t*);
|
|
|
|
bool event(QEvent*);
|
|
|
|
|
|
|
|
Engine::SimpleMetaBundle fetchMetaData() const;
|
|
|
|
|
|
|
|
void DetermineAndShowErrorMessage(); //call after failure to load/play
|
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
PluginDetailsList GetPluginList() const;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
private slots:
|
|
|
|
void PruneScope();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
signals:
|
|
|
|
void InfoMessage(const QString&);
|
2018-02-27 18:06:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class PruneScopeThread : public QThread {
|
|
|
|
public:
|
|
|
|
PruneScopeThread(XineEngine *parent);
|
|
|
|
|
|
|
|
protected:
|
2018-06-28 01:15:32 +02:00
|
|
|
void run();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
private:
|
2018-06-28 01:15:32 +02:00
|
|
|
XineEngine *engine_;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|