Fixes to xine engine

This commit is contained in:
Jonas Kvinge 2018-06-28 23:12:39 +02:00
parent 505c1feb42
commit fc66e2e2c7
7 changed files with 108 additions and 116 deletions

View File

@ -42,7 +42,7 @@ Engine::Base::Base()
end_nanosec_(0), end_nanosec_(0),
scope_(kScopeSize), scope_(kScopeSize),
output_(""), output_(""),
device_(QVariant("")), device_(QVariant()),
rg_enabled_(false), rg_enabled_(false),
rg_mode_(0), rg_mode_(0),
rg_preamp_(0), rg_preamp_(0),

View File

@ -63,7 +63,7 @@ GstEnginePipeline::GstEnginePipeline(GstEngine *engine)
id_(sId++), id_(sId++),
valid_(false), valid_(false),
output_(""), output_(""),
device_(""), device_(QVariant()),
eq_enabled_(false), eq_enabled_(false),
eq_preamp_(0), eq_preamp_(0),
stereo_balance_(0.0f), stereo_balance_(0.0f),

View File

@ -357,6 +357,7 @@ EngineBase::PluginDetailsList VLCEngine::GetPluginList() const {
details.name = QString::fromUtf8(audio_output->psz_name); details.name = QString::fromUtf8(audio_output->psz_name);
details.description = QString::fromUtf8(audio_output->psz_description); details.description = QString::fromUtf8(audio_output->psz_description);
ret << details; ret << details;
//GetDevicesList(audio_output->psz_name);
} }
libvlc_audio_output_list_release(audio_output_list); libvlc_audio_output_list_release(audio_output_list);

View File

@ -201,7 +201,8 @@ bool XineEngine::Load(const QUrl &url, Engine::TrackChangeFlags change, bool for
xine_close(stream_); xine_close(stream_);
int result = xine_open(stream_, url.path().toUtf8()); //int result = xine_open(stream_, url.path().toUtf8());
int result = xine_open(stream_, url.toString().toUtf8());
if (result) { if (result) {
#ifndef XINE_SAFE_MODE #ifndef XINE_SAFE_MODE
@ -370,7 +371,7 @@ EngineBase::OutputDetailsList XineEngine::GetOutputsList() const {
} }
bool XineEngine::CustomDeviceSupport(const QString &name) { bool XineEngine::CustomDeviceSupport(const QString &name) {
return (name == DefaultOutput() ? false : true); return (name == "alsa" || name == "oss" || name == "jack" || name == "pulseaudio");
} }
void XineEngine::ReloadSettings() { void XineEngine::ReloadSettings() {

View File

@ -2,17 +2,14 @@
Copyright: See COPYING file that comes with this distribution 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) This has to be a c file or for some reason it won't link! (GCC 3.4.1)
*/ */
/* gcc doesn't like inline for me */
#define inline
/* need access to port_ticket */ /* need access to port_ticket */
#define XINE_ENGINE_INTERNAL #define XINE_ENGINE_INTERNAL
#include "config.h" #include "config.h"
#include <time.h>
#include "xinescope.h" #include "xinescope.h"
#include <xine/post.h> #include <xine/post.h>
#include <xine/xine_internal.h> #include <xine/xine_internal.h>
@ -20,11 +17,11 @@
typedef struct scope_plugin_s scope_plugin_t; typedef struct scope_plugin_s scope_plugin_t;
struct scope_plugin_s { struct scope_plugin_s {
post_plugin_t post; post_plugin_t post;
metronom_t metronom; metronom_t metronom;
int channels; int channels;
MyNode *list; MyNode *list;
}; };
/************************* /*************************
@ -33,91 +30,92 @@ struct scope_plugin_s {
static int scope_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, uint32_t bits, uint32_t rate, int mode) { 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 port ((post_audio_port_t*)port_gen)
#define this ((scope_plugin_t*)((post_audio_port_t*)port_gen)->post) #define this ((scope_plugin_t*)((post_audio_port_t*)port_gen)->post)
_x_post_rewire((post_plugin_t*)port->post); _x_post_rewire((post_plugin_t*)port->post);
_x_post_inc_usage(port); _x_post_inc_usage(port);
port->stream = stream; port->stream = stream;
port->bits = bits; port->bits = bits;
port->rate = rate; port->rate = rate;
port->mode = mode; port->mode = mode;
this->channels = _x_ao_mode2channels(mode); this->channels = _x_ao_mode2channels(mode);
return port->original_port->open(port->original_port, stream, bits, rate, 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) { static void scope_port_close(xine_audio_port_t *port_gen, xine_stream_t *stream) {
MyNode *node; MyNode *node;
/* ensure the buffers are deleted during the next XineEngine::timerEvent() */ /* ensure the buffers are deleted during the next XineEngine::timerEvent() */
for(node = this->list->next; node != this->list; node = node->next) for(node = this->list->next; node != this->list; node = node->next)
node->vpts = node->vpts_end = -1; node->vpts = node->vpts_end = -1;
port->stream = NULL; port->stream = NULL;
port->original_port->close(port->original_port, stream); port->original_port->close(port->original_port, stream);
_x_post_dec_usage(port); _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) { 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) */ /* 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; const int num_samples = buf->num_frames * this->channels;
metronom_t *myMetronom = &this->metronom; metronom_t *myMetronom = &this->metronom;
MyNode *new_node; MyNode *new_node;
/* I keep my own metronom because xine wouldn't for some reason */ /* I keep my own metronom because xine wouldn't for some reason */
memcpy(&this->metronom, stream->metronom, sizeof(metronom_t)); memcpy(&this->metronom, stream->metronom, sizeof(metronom_t));
new_node = malloc(sizeof(MyNode)); new_node = (MyNode *) malloc(sizeof(MyNode));
new_node->vpts = myMetronom->got_audio_samples(myMetronom, buf->vpts, buf->num_frames); new_node->vpts = myMetronom->got_audio_samples(myMetronom, buf->vpts, buf->num_frames);
new_node->num_frames = buf->num_frames; new_node->num_frames = buf->num_frames;
new_node->mem = malloc(num_samples * 2); new_node->mem = (int16_t *) malloc(num_samples * 2);
memcpy(new_node->mem, buf->mem, num_samples * 2); memcpy(new_node->mem, buf->mem, num_samples * 2);
{ {
int64_t int64_t
K = myMetronom->pts_per_smpls; /*smpls = 1<<16 samples*/ K = myMetronom->pts_per_smpls; /*smpls = 1<<16 samples*/
K *= num_samples; K *= num_samples;
K /= (1<<16); K /= (1<<16);
K += new_node->vpts; K += new_node->vpts;
new_node->vpts_end = K; new_node->vpts_end = K;
} }
port->original_port->put_buffer(port->original_port, buf, stream); port->original_port->put_buffer(port->original_port, buf, stream);
/* finally we should append the current buffer to the list /* 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 */ * This is thread-safe due to the way we handle the list in the GUI thread */
new_node->next = this->list->next; new_node->next = this->list->next;
this->list->next = new_node; this->list->next = new_node;
#undef port #undef port
#undef this #undef this
} }
static void scope_dispose(post_plugin_t *this) { static void scope_dispose(post_plugin_t *post) {
MyNode *list = ((scope_plugin_t*)this)->list;
MyNode *prev;
MyNode *node = list;
/* Free all elements of the list (a ring buffer) */ MyNode *list = ((scope_plugin_t*)post)->list;
do { MyNode *prev;
prev = node->next; MyNode *node = list;
free(node->mem); /* Free all elements of the list (a ring buffer) */
free(node); do {
prev = node->next;
node = prev; free(node->mem);
} free(node);
while(node != list);
node = prev;
}
while(node != list);
free(this); free(post);
} }
@ -125,49 +123,49 @@ static void scope_dispose(post_plugin_t *this) {
* plugin init function * * plugin init function *
************************/ ************************/
xine_post_t* scope_plugin_new(xine_t *xine, xine_audio_port_t *audio_target) { xine_post_t *scope_plugin_new(xine_t *xine, xine_audio_port_t *audio_target) {
scope_plugin_t *scope_plugin = calloc(1, sizeof(scope_plugin_t)); 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_plugin_t *post_plugin = (post_plugin_t *)scope_plugin;
{ {
post_in_t *input; post_in_t *input;
post_out_t *output; post_out_t *output;
post_audio_port_t *port; post_audio_port_t *port;
_x_post_init(post_plugin, 1, 0); _x_post_init(post_plugin, 1, 0);
port = _x_post_intercept_audio_port(post_plugin, audio_target, &input, &output); port = _x_post_intercept_audio_port(post_plugin, audio_target, &input, &output);
port->new_port.open = scope_port_open; port->new_port.open = scope_port_open;
port->new_port.close = scope_port_close; port->new_port.close = scope_port_close;
port->new_port.put_buffer = scope_port_put_buffer; port->new_port.put_buffer = scope_port_put_buffer;
post_plugin->xine_post.audio_input[0] = &port->new_port; post_plugin->xine_post.audio_input[0] = &port->new_port;
post_plugin->xine_post.type = PLUGIN_POST; post_plugin->xine_post.type = PLUGIN_POST;
post_plugin->dispose = scope_dispose; 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 // 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->running_ticket = xine->port_ticket;
post_plugin->xine = xine; post_plugin->xine = xine;
/* scope_plugin_t init */ /* scope_plugin_t init */
scope_plugin->list = calloc(1, sizeof(MyNode)); scope_plugin->list = (MyNode *) calloc(1, sizeof(MyNode));
scope_plugin->list->next = scope_plugin->list; scope_plugin->list->next = scope_plugin->list;
return &post_plugin->xine_post; return &post_plugin->xine_post;
} }
MyNode* scope_plugin_list(void *post) { MyNode *scope_plugin_list(void *post) {
return ((scope_plugin_t*)post)->list; return ((scope_plugin_t*)post)->list;
} }
int scope_plugin_channels(void *post) { int scope_plugin_channels(void *post) {
return ((scope_plugin_t*)post)->channels; return ((scope_plugin_t*)post)->channels;
} }
metronom_t* scope_plugin_metronom(void *post) { metronom_t* scope_plugin_metronom(void *post) {
return &((scope_plugin_t*)post)->metronom; return &((scope_plugin_t*)post)->metronom;
} }

View File

@ -17,34 +17,25 @@
typedef struct my_node_s MyNode; typedef struct my_node_s MyNode;
struct my_node_s struct my_node_s {
{ MyNode *next;
MyNode *next; int16_t *mem;
int16_t *mem; int num_frames;
int num_frames; int64_t vpts;
int64_t vpts; int64_t vpts_end;
int64_t vpts_end;
}; };
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
#endif #endif
xine_post_t* xine_post_t *scope_plugin_new( xine_t*, xine_audio_port_t* );
scope_plugin_new( xine_t*, xine_audio_port_t* );
/* we sacrifice type-safety here because some GCCs appear broken /* we sacrifice type-safety here because some GCCs appear broken and choke on redefining the xine_post_t typedef */
* and choke on redefining the xine_post_t typedef
*/
MyNode* MyNode *scope_plugin_list(void*);
scope_plugin_list( void* ); int scope_plugin_channels(void*);
metronom_t *scope_plugin_metronom(void*);
int
scope_plugin_channels( void* );
metronom_t*
scope_plugin_metronom( void* );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -233,9 +233,10 @@ void BackendSettingsPage::Load_Device(QString output, QVariant device) {
ui_->combobox_device->setEnabled(false); ui_->combobox_device->setEnabled(false);
ui_->lineedit_device->setText(""); ui_->lineedit_device->setText("");
#ifndef Q_OS_WIN32 #ifdef Q_OS_WIN
ui_->combobox_device->addItem(IconLoader::Load("soundcard"), "Automatically select", QVariant("")); if (engine()->type() != Engine::GStreamer)
#endif #endif
ui_->combobox_device->addItem(IconLoader::Load("soundcard"), "Automatically select", QVariant(""));
for (DeviceFinder *f : dialog()->app()->enginedevice()->device_finders_) { for (DeviceFinder *f : dialog()->app()->enginedevice()->device_finders_) {
if (!f->outputs().contains(output)) continue; if (!f->outputs().contains(output)) continue;