2
base class for the player plugin
3
Copyright (C) 1999 Martin Vogt
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU Library General Public License as published by
7
the Free Software Foundation.
9
For more information look at the file COPYRIGHT in this package
13
#include "decoderPlugin.h"
18
static void *playerThread(void *arg){
19
((DecoderPlugin*)arg)->idleThread();
23
static int instanceCnt=0;
25
DecoderPlugin::DecoderPlugin(){
28
commandPipe=new CommandPipe();
29
threadCommand=new Command(_COMMAND_NONE);
30
abs_thread_cond_init(&streamStateCond);
31
abs_thread_mutex_init(&streamStateMut);
32
abs_thread_mutex_init(&shutdownMut);
37
streamState=_STREAM_STATE_EOF;
40
// this default is necessary. if you have a blocking
41
// device and we start automatic the thread
42
// may block on it and all commands (including play)
44
// *you should not use autoplay*
47
pluginInfo=new PluginInfo();
52
abs_thread_create(&tr,playerThread,this);
54
// we send a ping. because this signal is synchron
55
// we block until the thread is started and
56
// has read the ping singnal
57
Command cmd(_COMMAND_PING);
58
insertSyncCommand(&cmd);
64
DecoderPlugin::~DecoderPlugin(){
67
Command cmd(_COMMAND_CLOSE);
68
insertAsyncCommand(&cmd);
70
abs_thread_join(tr,&ret);
72
abs_thread_cond_destroy(&streamStateCond);
73
abs_thread_mutex_destroy(&streamStateMut);
74
abs_thread_mutex_destroy(&shutdownMut);
82
void DecoderPlugin::close(){
83
// from here we can only walk to init or eof
84
// in both cases we sometimes catch out decoderMut :-)
85
Command cmd(_COMMAND_CLOSE);
86
insertAsyncCommand(&cmd);
92
insertSyncCommand(&cmd);
93
waitForStreamState(_STREAM_STATE_EOF);
98
void DecoderPlugin::pause() {
99
Command cmd(_COMMAND_PAUSE);
100
insertSyncCommand(&cmd);
106
int DecoderPlugin::play() {
107
Command cmd(_COMMAND_PLAY);
108
insertSyncCommand(&cmd);
113
int DecoderPlugin::seek(int second) {
114
Command cmd(_COMMAND_SEEK,second);
115
insertSyncCommand(&cmd);
120
void DecoderPlugin::insertAsyncCommand(Command* cmd) {
121
commandPipe->sendCommandNoWait(*cmd);
124
void DecoderPlugin::insertSyncCommand(Command* cmd) {
125
commandPipe->sendCommand(*cmd);
129
void DecoderPlugin::shutdownLock() {
130
abs_thread_mutex_lock(&shutdownMut);
134
void DecoderPlugin::shutdownUnlock() {
135
abs_thread_mutex_unlock(&shutdownMut);
138
int DecoderPlugin::getTime(int lCurrent) {
139
int secLen=getTotalLength();
141
if (lCurrent==false) {
148
pos=input->getBytePosition()+1;
149
byteLen=input->getByteLength()+1;
151
int back=(int)(((double)pos/(double)byteLen) * (double)secLen);
157
int DecoderPlugin::getTotalLength() {
158
cout << "plugin does not support total playtime reporting"<<endl;
162
int DecoderPlugin::seek_impl(int) {
163
cout << "plugin does not support seek"<<endl;
170
void DecoderPlugin::setOutputPlugin(OutputStream* output) {
175
int DecoderPlugin::setInputPlugin(InputStream* input) {
179
cout << "input is NULL"<<endl;
182
pluginInfo->setUrl(input->getUrl());
185
// the command is synchron we block until the
186
// thread has read it
187
Command cmd(_COMMAND_START);
188
insertSyncCommand(&cmd);
191
// now that we know he has read it, we send another
192
// command, this is only read if the thread is in the
193
// decode_loop, and we then know that the streamState
195
Command ping(_COMMAND_PING);
196
insertSyncCommand(&ping);
206
void DecoderPlugin::config(const char* key,const char* value,void* ){
207
if (strcmp(key,"-y")==0) {
208
if (strcmp(value,"on")==0) {
218
during shutdown the streamState is undefined until
219
the thread has left the decode_loop().
220
Make sure we wait for this.
222
int DecoderPlugin::getStreamState() {
224
int back=streamState;
230
int DecoderPlugin::waitForStreamState(int state) {
232
abs_thread_mutex_lock(&streamStateMut);
233
while ((streamState & state) == false) {
234
abs_thread_cond_wait(&streamStateCond,&streamStateMut);
237
abs_thread_mutex_unlock(&streamStateMut);
242
void DecoderPlugin::setStreamState(int streamState) {
243
abs_thread_mutex_lock(&streamStateMut);
244
this->streamState=streamState;
245
abs_thread_cond_signal(&streamStateCond);
246
abs_thread_mutex_unlock(&streamStateMut);
250
void DecoderPlugin::decoder_loop() {
251
cout << "direct call decoder loop->plugin not found ???"<<endl;
252
TimeWrapper::usleep(100000);
256
void* DecoderPlugin::idleThread() {
258
while(lCreatorLoop) {
260
commandPipe->waitForCommand();
261
commandPipe->hasCommand(threadCommand);
262
int id=threadCommand->getID();
271
threadCommand->print("ignoring non START command in idleThread");
277
setStreamState(_STREAM_STATE_FIRST_INIT);
278
linDecoderLoop=false;
279
decode_loopCounter++;
286
setStreamState(_STREAM_STATE_EOF);
294
PluginInfo* DecoderPlugin::getPluginInfo() {
299
int DecoderPlugin::runCheck() {
300
if (runCheck_Counter==0) {
304
while (lDecoderLoop && lCreatorLoop) {
306
// if we have an eof this always leads to
307
// a shutdown of the decode_loop thread
308
// it has more priority than the resyn request
310
setStreamState(_STREAM_STATE_WAIT_FOR_END);
313
// if we are in _STREAM_STATE_RESYNC_COMMIT
314
// we only leave it if command is _COMMAND_RESYNC_END
318
// check user commands
320
if (lDecode==false) {
321
commandPipe->waitForCommand();
322
commandPipe->hasCommand(threadCommand);
324
if (commandPipe->hasCommand(threadCommand)==false) {
325
// no commands and lDecode=true
330
// here we forward the command to a special
331
// method who can handle everything
332
// (the default method should work fine);
333
int nextCheck= processThreadCommand(threadCommand);
335
case _RUN_CHECK_CONTINUE:
337
case _RUN_CHECK_FALSE:
339
case _RUN_CHECK_TRUE:
342
cout << "unknown runCheck return command"<<endl;
353
int DecoderPlugin::processThreadCommand(Command* command) {
356
int id=command->getID();
360
// if we are in _STREAM_STATE_RESYNC_COMMIT
361
// we only leave it if command is _COMMAND_RESYNC_END
363
if (streamState==_STREAM_STATE_RESYNC_COMMIT) {
365
case _COMMAND_RESYNC_END:
366
setStreamState(_STREAM_STATE_INIT);
371
// we return false so that the plugin clears
372
// all its allocated classes
374
// in the next call we exit immediately
375
return _RUN_CHECK_FALSE;
379
command->print("ignore command in _STREAM_STATE_RESYNC_COMMIT");
382
return _RUN_CHECK_CONTINUE;
397
case _COMMAND_SEEK: {
398
if (streamState==_STREAM_STATE_FIRST_INIT) {
399
command->print("ignore command seek in _STREAM_STATE_FIRST_INIT");
401
intArg=command->getIntArg();
408
// we return false so that the plugin clears
409
// all its allocated classes
411
// in the next call we exit immediately
412
return _RUN_CHECK_FALSE;
413
case _COMMAND_RESYNC_START:
414
setStreamState(_STREAM_STATE_RESYNC_COMMIT);
419
cout << "unknown command id in Command::print"<<endl;
422
return _RUN_CHECK_CONTINUE;