Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

lib.cpp

Go to the documentation of this file.
00001 /*
00002                     This file is part of the Opie Project
00003 
00004                       Copyright (c)  2002 Max Reiss <harlekin@handhelds.org>
00005                              Copyright (c)  2002 LJP <>
00006                              Copyright (c)  2002 Holger Freyther <zecke@handhelds.org>
00007               =.
00008             .=l.
00009      .>+-=
00010 _;:,   .>  :=|.         This program is free software; you can
00011 .> <`_,  > .  <=          redistribute it and/or  modify it under
00012 :`=1 )Y*s>-.--  :           the terms of the GNU General Public
00013 .="- .-=="i,   .._         License as published by the Free Software
00014 - .  .-<_>   .<>         Foundation; either version 2 of the License,
00015   ._= =}    :          or (at your option) any later version.
00016   .%`+i>    _;_.
00017   .i_,=:_.   -<s.       This program is distributed in the hope that
00018   + . -:.    =       it will be useful,  but WITHOUT ANY WARRANTY;
00019   : ..  .:,   . . .    without even the implied warranty of
00020   =_    +   =;=|`    MERCHANTABILITY or FITNESS FOR A
00021  _.=:.    :  :=>`:     PARTICULAR PURPOSE. See the GNU
00022 ..}^=.=    =    ;      Library General Public License for more
00023 ++=  -.   .`   .:       details.
00024 :   = ...= . :.=-
00025 -.  .:....=;==+<;          You should have received a copy of the GNU
00026  -_. . .  )=. =           Library General Public License along with
00027   --    :-=`           this library; see the file COPYING.LIB.
00028                              If not, write to the Free Software Foundation,
00029                              Inc., 59 Temple Place - Suite 330,
00030                              Boston, MA 02111-1307, USA.
00031 
00032 */
00033 
00034 #include "xinevideowidget.h"
00035 #include "lib.h"
00036 
00037 /* OPIE */
00038 #include <opie2/odebug.h>
00039 #include <qpe/global.h>
00040 
00041 /* QT */
00042 #include <qtextstream.h>
00043 #include <qdir.h>
00044 #include <qgfx_qws.h>
00045 
00046 /* STD */
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     // get the configuration
00076 
00077     // not really OO, should be an extra class, later
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     // allocate oss for sound
00123     // and fb for framebuffer
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 //    free( m_config );
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     /* FIXME either free or delete but valgrind bitches against both */
00157     //free( m_videoOutput );
00158     //delete m_audioOutput;
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 /* dilb: patch to solve the wrong stream length reported to the GUI*/
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        {/* if the function didn't return 0, then pos, time and length are valid.*/
00278        return length/1000;
00279        }
00280     /*don't poll too much*/
00281     usleep(100000);
00282     iTestLoop++;
00283     }
00284       while ( iTestLoop < 10 ); /* if after 1s, we still don't have any
00285 valid stream, then return -1 (this value could be used to make the stream
00286 unseekable, but it should never occur!! Mr. Murphy ? :) ) */
00287 
00288       return -1;
00289 }
00290 
00291 /* info about current stream */
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 /* end info block */
00324 
00325 void Lib::seekTo( int time ) {
00326     assert( m_initialized );
00327 
00328     odebug << "Seeking to second " << time << oendl;
00329     //Keep it paused if it was in that state
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 }

Generated on Sat Nov 5 16:17:31 2005 for OPIE by  doxygen 1.4.2