00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "xinevideowidget.h"
00035 #include "lib.h"
00036
00037
00038 #include <opie2/odebug.h>
00039 #include <qpe/global.h>
00040
00041
00042 #include <qtextstream.h>
00043 #include <qdir.h>
00044 #include <qgfx_qws.h>
00045
00046
00047 #include <assert.h>
00048 #include <unistd.h>
00049
00050 typedef void (*display_xine_frame_t) (void *user_data, uint8_t* frame,
00051 int width, int height,int bytes );
00052 typedef void (*vo_scale_cb) (void*, int, int, double,
00053 int*, int*, int*, int*, double*, int*, int* );
00054 typedef void (*dest_size_cb) (void*, int, int, double, int*, int*, double*);
00055
00056
00057 extern "C" {
00058 xine_vo_driver_t* init_video_out_plugin( xine_t *xine, void* video, display_xine_frame_t, void *, vo_scale_cb, dest_size_cb );
00059 int null_is_showing_video( const xine_vo_driver_t* self );
00060 void null_set_show_video( const xine_vo_driver_t* self, int show );
00061 void null_set_mode( const xine_vo_driver_t* self, int depth, int rgb );
00062 void null_display_handler( const xine_vo_driver_t* self, display_xine_frame_t t, void* user_data );
00063 }
00064
00065 using namespace XINE;
00066
00067 Lib::Lib( InitializationMode initMode, XineVideoWidget* widget )
00068 {
00069 m_initialized = false;
00070 m_duringInitialization = false;
00071 m_video = false;
00072 m_wid = widget;
00073 printf("Lib");
00074 QString configPath = QDir::homeDirPath() + "/Settings/opiexine.cf";
00075
00076
00077
00078 if ( !QFile::exists(configPath) ) {
00079 QFile f(configPath);
00080 f.open(IO_WriteOnly);
00081 QTextStream ts( &f );
00082 ts << "misc.memcpy_method:glibc\n";
00083 ts << "# uncomment if you experience double speed audio \n #audio.oss_sync_method:softsync\n";
00084 ts << "codec.ffmpeg_pp_quality:3\n";
00085 ts << "audio.num_buffers:50\n";
00086 ts << "audio.size_buffers:4096\n";
00087 ts << "video.num_buffers:20\n";
00088 ts << "video.size_buffers:4096\n";
00089 ts << "audio.out_num_audio_buf:16\n";
00090 ts << "audio.out_size_audio_buf:8096\n";
00091 ts << "audio.out_size_zero_buf:1024\n";
00092 ts << "audio.passthrough_offset:0\n";
00093 f.close();
00094 }
00095
00096 if ( initMode == InitializeImmediately ) {
00097 initialize();
00098 m_initialized = true;
00099 }
00100 else
00101 start();
00102 }
00103
00104 void Lib::run()
00105 {
00106 odebug << "Lib::run() started" << oendl;
00107 initialize();
00108 m_initialized = true;
00109 odebug << "Lib::run() finished" << oendl;
00110 }
00111
00112 void Lib::initialize()
00113 {
00114 m_duringInitialization = true;
00115 m_xine = xine_new( );
00116
00117 QString configPath = QDir::homeDirPath() + "/Settings/opiexine.cf";
00118 xine_config_load( m_xine, QFile::encodeName( configPath ) );
00119
00120 xine_init( m_xine );
00121
00122
00123
00124 m_audioOutput = xine_open_audio_driver( m_xine, "oss", NULL );
00125 m_videoOutput = ::init_video_out_plugin( m_xine, NULL,
00126 xine_display_frame, this,
00127 xine_vo_scale_cb,
00128 xine_dest_cb );
00129
00130 m_stream = xine_stream_new (m_xine, m_audioOutput, m_videoOutput );
00131 xine_set_param( m_stream, XINE_PARAM_AUDIO_CLOSE_DEVICE, 1);
00132
00133 if (m_wid != 0 )
00134 setWidget( m_wid );
00135
00136
00137 m_queue = xine_event_new_queue (m_stream);
00138 xine_event_create_listener_thread (m_queue, xine_event_handler, this);
00139
00140 m_duringInitialization = false;
00141 }
00142
00143 Lib::~Lib() {
00144 assert( isRunning() == false );
00145 assert( m_initialized );
00146
00147
00148
00149 xine_close( m_stream );
00150 xine_event_dispose_queue( m_queue );
00151 xine_dispose( m_stream );
00152 xine_close_audio_driver(m_xine,m_audioOutput);
00153 xine_close_video_driver(m_xine,m_videoOutput);
00154 xine_exit( m_xine );
00155
00156
00157
00158
00159 }
00160
00161 void Lib::resize ( const QSize &s ) {
00162 assert( m_initialized || m_duringInitialization );
00163
00164 if ( s. width ( ) && s. height ( ) )
00165 m_videoSize = s;
00166 }
00167
00168 int Lib::majorVersion() {
00169 int major, minor, sub;
00170 xine_get_version ( &major, &minor, &sub );
00171 return major;
00172 }
00173
00174 int Lib::minorVersion() {
00175 int major, minor, sub;
00176 xine_get_version ( &major, &minor, &sub );
00177 return minor;
00178 }
00179
00180 int Lib::subVersion() {
00181 int major, minor, sub;
00182 xine_get_version ( &major, &minor, &sub );
00183 return sub;
00184 }
00185
00186 int Lib::setfile(const QString& fileName)
00187 {
00188 QString str = fileName.stripWhiteSpace();
00189
00190
00191 if ( !xine_open( m_stream, str.utf8().data() ) ) {
00192 return 0;
00193 }
00194 return 1;
00195 }
00196
00197 int Lib::play( const QString& fileName, int startPos, int start_time ) {
00198 assert( m_initialized );
00199
00200 QString str = fileName.stripWhiteSpace();
00201
00202
00203 if ( !xine_open( m_stream, str.utf8().data() ) ) {
00204 return 0;
00205 }
00206 return xine_play( m_stream, startPos, start_time);
00207 }
00208
00209 void Lib::stop() {
00210 assert( m_initialized );
00211 xine_stop( m_stream );
00212 xine_set_param( m_stream, XINE_PARAM_AUDIO_CLOSE_DEVICE, 1);
00213 }
00214
00215 void Lib::pause( bool toggle ) {
00216 assert( m_initialized );
00217
00218 if ( toggle ) {
00219 xine_set_param( m_stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE );
00220 xine_set_param( m_stream, XINE_PARAM_AUDIO_CLOSE_DEVICE, 1);
00221 }
00222
00223 else {
00224 xine_set_param( m_stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL );
00225 }
00226 }
00227
00228 int Lib::speed() const {
00229 assert( m_initialized );
00230
00231 return xine_get_param ( m_stream, XINE_PARAM_SPEED );
00232 }
00233
00234 void Lib::setSpeed( int speed ) {
00235 assert( m_initialized );
00236
00237 xine_set_param ( m_stream, XINE_PARAM_SPEED, speed );
00238 }
00239
00240 int Lib::status() const {
00241 assert( m_initialized );
00242
00243 return xine_get_status( m_stream );
00244 }
00245
00246 int Lib::currentPosition() const {
00247 assert( m_initialized );
00248
00249 int pos, time, length;
00250 xine_get_pos_length( m_stream, &pos, &time, &length );
00251 return pos;
00252 }
00253
00254 int Lib::currentTime() const {
00255 assert( m_initialized );
00256
00257 int pos, time, length;
00258 pos = time = length = 0;
00259
00260 if ( xine_get_pos_length( m_stream, &pos, &time, &length ) )
00261 return time/1000;
00262 else
00263 return 0;
00264 }
00265
00266 int Lib::length() const {
00267 assert( m_initialized );
00268
00269 int pos, time, length;
00270
00271 int iRetVal=0, iTestLoop=0;
00272
00273 do
00274 {
00275 iRetVal = xine_get_pos_length( m_stream, &pos, &time, &length );
00276 if (iRetVal)
00277 {
00278 return length/1000;
00279 }
00280
00281 usleep(100000);
00282 iTestLoop++;
00283 }
00284 while ( iTestLoop < 10 );
00285
00286
00287
00288 return -1;
00289 }
00290
00291
00292 QSize Lib::videoSize()const
00293 {
00294 if (!m_initialized||!hasVideo()) return QSize(0,0);
00295 int width = xine_get_stream_info(m_stream,XINE_STREAM_INFO_VIDEO_WIDTH);
00296 int height = xine_get_stream_info(m_stream,XINE_STREAM_INFO_VIDEO_HEIGHT);
00297 return QSize(width,height);
00298 }
00299
00300
00301 bool Lib::isSeekable() const {
00302 assert( m_initialized );
00303
00304 return xine_get_stream_info( m_stream, XINE_STREAM_INFO_SEEKABLE );
00305 }
00306
00307 bool Lib::hasVideo() const {
00308 assert( m_initialized );
00309
00310 return xine_get_stream_info( m_stream, XINE_STREAM_INFO_HAS_VIDEO);
00311 }
00312
00313 int Lib::audioBitrate()const
00314 {
00315 if (!m_initialized) return 0;
00316 return xine_get_stream_info( m_stream, XINE_STREAM_INFO_AUDIO_BITRATE);
00317 }
00318 int Lib::videoBitrate()const
00319 {
00320 if (!m_initialized||!hasVideo()) return 0;
00321 return xine_get_stream_info( m_stream, XINE_STREAM_INFO_VIDEO_BITRATE);
00322 }
00323
00324
00325 void Lib::seekTo( int time ) {
00326 assert( m_initialized );
00327
00328 odebug << "Seeking to second " << time << oendl;
00329
00330 if ( xine_get_param( m_stream, XINE_PARAM_SPEED ) ) {
00331 xine_play( m_stream, 0, time*1000 );
00332 }
00333
00334 else {
00335 xine_play( m_stream, 0, time*1000 );
00336 xine_set_param( m_stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE );
00337 }
00338
00339 }
00340
00341
00342 QString Lib::metaInfo( int number) const {
00343 assert( m_initialized );
00344
00345 return xine_get_meta_info( m_stream, number );
00346 }
00347
00348 int Lib::error() const {
00349 assert( m_initialized );
00350
00351 return xine_get_error( m_stream );
00352 };
00353
00354 void Lib::ensureInitialized()
00355 {
00356 if ( m_initialized )
00357 return;
00358
00359 odebug << "waiting for initialization thread to finish" << oendl;
00360 wait();
00361 odebug << "initialization thread finished!" << oendl;
00362 }
00363
00364 void Lib::setWidget( XineVideoWidget *widget )
00365 {
00366 m_wid = widget;
00367 if (m_wid) {
00368 resize ( m_wid-> size ( ) );
00369 ::null_set_mode( m_videoOutput, qt_screen->depth(), qt_screen->pixelType() );
00370 }
00371 }
00372
00373 void Lib::receiveMessage( ThreadUtil::ChannelMessage *msg, SendType sendType )
00374 {
00375 assert( sendType == ThreadUtil::Channel::OneWay );
00376 handleXineEvent( msg->type(), msg->data(), msg->msg() );
00377 delete msg;
00378 }
00379
00380 void Lib::handleXineEvent( const xine_event_t* t ) {
00381 int prog = -1; const char* name = 0;
00382 if ( t->type == XINE_EVENT_PROGRESS ) {
00383 xine_progress_data_t *pt = static_cast<xine_progress_data_t*>( t->data );
00384 prog = pt->percent;
00385 name = pt->description;
00386 }
00387
00388 send( new ThreadUtil::ChannelMessage( t->type, prog, name ), OneWay );
00389 }
00390
00391 void Lib::handleXineEvent( int type, int data, const char* name ) {
00392 assert( m_initialized );
00393
00394 if ( type == XINE_EVENT_UI_PLAYBACK_FINISHED ) {
00395 emit stopped();
00396 }else if ( type == XINE_EVENT_PROGRESS ) {
00397 QString str = name == 0 ? QString::null : QString::fromUtf8( name );
00398 Global::statusMessage( tr( "Progress: %1 %2" ).arg( name, data ) );;
00399 }
00400 }
00401
00402
00403 void Lib::setShowVideo( bool video ) {
00404 assert( m_initialized );
00405
00406 m_video = video;
00407 ::null_set_show_video( m_videoOutput, video );
00408 }
00409
00410 bool Lib::isShowingVideo() const {
00411 assert( m_initialized );
00412
00413 return ::null_is_showing_video( m_videoOutput );
00414 }
00415
00416 void Lib::showVideoFullScreen( bool fullScreen ) {
00417 assert( m_initialized );
00418
00419 #warning use xine
00420 }
00421
00422 bool Lib::isVideoFullScreen() const {
00423 assert( m_initialized );
00424
00425 #warning use xine
00426 return false;
00427 }
00428
00429 void Lib::setScaling( bool scale ) {
00430 assert( m_initialized );
00431
00432 xine_set_param( m_stream, XINE_PARAM_VO_ASPECT_RATIO,
00433 scale ? XINE_VO_ASPECT_AUTO : XINE_VO_ASPECT_SQUARE );
00434 }
00435
00436 void Lib::setGamma( int value ) {
00437 assert( m_initialized );
00438 xine_set_param( m_stream, XINE_PARAM_VO_BRIGHTNESS, value );
00439 }
00440
00441 bool Lib::isScaling() const {
00442 assert( m_initialized );
00443
00444 int aratio = xine_get_param( m_stream, XINE_PARAM_VO_ASPECT_RATIO );
00445 return aratio == XINE_VO_ASPECT_AUTO;
00446 }
00447
00448 void Lib::xine_event_handler( void* user_data, const xine_event_t* t ) {
00449 ( (Lib*)user_data)->handleXineEvent( t );
00450 }
00451
00452 void Lib::xine_display_frame( void* user_data, uint8_t *frame,
00453 int width, int height, int bytes ) {
00454 ( (Lib*)user_data)->drawFrame( frame, width, height, bytes );
00455 }
00456
00457 void Lib::xine_vo_scale_cb( void *user_data, int video_with, int video_height,
00458 double video_pixel_aspect,
00459 int *dest_x, int *dest_y, int *dest_width,
00460 int *dest_height, double *dest_pixel_aspect,
00461 int *win_x, int *win_y ) {
00462 QSize size = ((Lib*)user_data)->m_videoSize;
00463 if (!size.isValid())
00464 return;
00465
00466 *dest_x = 0;
00467 *dest_y = 0;
00468 *dest_width = size.width();
00469 *dest_height = size.height();
00470 *win_x = 0;
00471 *win_y = 0;
00472 }
00473
00474 void Lib::xine_dest_cb( void* user_data, int, int, double,
00475 int *dest_width, int* dest_height, double* ) {
00476 QSize size = ((Lib*)user_data)->m_videoSize;
00477 if ( !size.isValid() )
00478 return;
00479
00480 *dest_width = size.width();
00481 *dest_height = size.height();
00482 }
00483
00484 void Lib::drawFrame( uint8_t* frame, int width, int height, int bytes ) {
00485 assert( m_initialized );
00486
00487 if ( !m_video )
00488 return;
00489
00490 if (m_wid) m_wid-> setVideoFrame ( frame, width, height, bytes );
00491 }