Main Page | Class List | File List | Class Members | File Members

qxinewidget.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                            videowindow.cpp 
00003                            -------------------
00004     begin                : Fre Apr 18 2003
00005     revision             : $Revision: 1.56 $
00006     last modified        : $Date: 2004/03/24 11:45:05 $ by $Author: juergenk $
00007     copyright            : (C) 2003-2004 by J. Kofler
00008     email                : kaffeine@gm---.net
00009  ***************************************************************************/
00010 
00011 /***************************************************************************
00012  *                                                                         *
00013  *   This program is free software; you can redistribute it and/or modify  *
00014  *   it under the terms of the GNU General Public License as published by  *
00015  *   the Free Software Foundation; either version 2 of the License, or     *
00016  *   (at your option) any later version.                                   *
00017  *                                                                         *
00018  ***************************************************************************/
00019 
00020 
00021 #define USE_QT_ONLY 1
00022 
00023 #ifndef USE_QT_ONLY
00024 
00025 #include <klocale.h>
00026 #include <kurl.h>
00027 #include <kstandarddirs.h>
00028 #include <kdebug.h>
00029 #include <kmessagebox.h>
00030 #include <kapplication.h>
00031 
00032 #else
00033 
00034 #include <qmessagebox.h>
00035 #include <qapplication.h>
00036 
00037 #endif
00038 
00039 #include <qdir.h>
00040 #include <qcursor.h>
00041 #include <qimage.h>
00042 
00043 #include <string.h>
00044 #include <stdlib.h>
00045 #include <xine/xineutils.h>
00046 
00047 #include "convert.h"
00048 #include "qxinewidget.h"
00049 
00050 #ifndef USE_QT_ONLY
00051 #include "qxinewidget.moc"
00052 #endif
00053 
00054 #include <X11/keysym.h>
00055 #ifdef HAVE_XTEST
00056 #include <X11/extensions/XTest.h>
00057 #endif
00058 
00059 
00060 #define TIMER_EVENT_PLAYBACK_FINISHED 100
00061 #define TIMER_EVENT_NEW_CHANNELS      101
00062 #define TIMER_EVENT_NEW_TITLE         102
00063 #define TIMER_EVENT_NEW_INFO          103
00064 #define TIMER_EVENT_NEW_PROGRESS_INFO 104
00065 #define TIMER_EVENT_CHANGE_CURSOR     105
00066 #define TIMER_EVENT_GRAB_KEYBOARD     106
00067 #define TIMER_EVENT_NEW_MRL_REFERENCE 107
00068 #define TIMER_EVENT_NEW_XINE_MESSAGE  108
00069 #define TIMER_EVENT_RESTART_PLAYBACK  200
00070 #define TIMER_EVENT_RESIZE_PARENT     300
00071 
00072 
00073 QXineWidget::QXineWidget(QWidget *parent, const char *name, const QString& prefAudio, const QString& prefVideo, bool verbose, bool startManual)
00074              : QWidget(parent,name), QThread()
00075 {
00076   xineEngine = NULL; xineStream = NULL; audioDriver = NULL; videoDriver = NULL;
00077   eventQueue = NULL; xinePost = NULL;  xineRunning = false;
00078   xineDisplay = NULL; eventThread = 0; currentZoom = 100;
00079   startXineManual = startManual;
00080   visualPluginName = QString::null;
00081   devicePath = QString::null;
00082   xineVerbose = verbose;
00083   autoresizeEnabled = false; videoFrameWidth = 0; videoFrameHeight = 0;
00084   
00085   preferedAudio = prefAudio;
00086   preferedVideo = prefVideo;
00087 
00088   setPaletteBackgroundColor(QColor(0,0,0));
00089 
00090   playMode = NORMAL_PLAY;
00091 
00092   connect(&posTimer, SIGNAL(timeout()), this, SLOT(slotGetPosition()));
00093   connect(&lengthInfoTimer, SIGNAL(timeout()), this, SLOT(slotEmitLengthInfo()));
00094   connect(&screensaverTimer, SIGNAL(timeout()), this, SLOT(slotFakeKeyEvent()));
00095   connect(&mouseHideTimer, SIGNAL(timeout()), this, SLOT(slotHideMouse()));
00096 
00097   setMouseTracking( true );
00098   setUpdatesEnabled( false ); //prevent qt overwrites videowin black
00099 }
00100 
00101 QXineWidget::~QXineWidget()
00102 {
00103   /* "careful" shutdown, maybe xine initialization was not successful */
00104 
00105   xineRunning = false;
00106 
00107   /* stop all timers */
00108   posTimer.stop();
00109   screensaverTimer.stop();
00110   mouseHideTimer.stop();
00111 
00112   if (xineStream)
00113   {
00114     xine_close(xineStream);
00115   }
00116 
00117   if (running())
00118   {
00119 
00120     XEvent ev;
00121     ev.type = Expose;
00122     ev.xexpose.display = xineDisplay;
00123     ev.xexpose.window = winId();
00124     ev.xexpose.x = x();
00125     ev.xexpose.y = y();
00126     ev.xexpose.width = width();
00127     ev.xexpose.height = height();
00128     ev.xexpose.count = 0;
00129 
00130     XSendEvent( x11Display(), winId(), False, ExposureMask, &ev );  /* send a fake expose event */
00131     XFlush( x11Display() );
00132 
00133     if( !wait(1000) )  /* wait a second for thread exiting */
00134     {
00135        warningOut("XEvent thread don't exit. Terminating it...");
00136        terminate();
00137     }
00138   }
00139 
00140   debugOut("Shut down xine engine\n");
00141 
00142   if (xineDisplay)
00143      XLockDisplay( xineDisplay );
00144 
00145   if (xinePost)
00146   {
00147     debugOut(QString("Dispose visual plugin: %1").arg(visualPluginName));
00148     postAudioSource = xine_get_audio_source (xineStream);
00149     xine_post_wire_audio_port (postAudioSource, audioDriver);
00150     xine_post_dispose (xineEngine, xinePost);
00151   }  
00152   if (eventQueue)
00153      xine_event_dispose_queue(eventQueue);
00154   if (xineStream)   
00155      xine_dispose(xineStream);
00156   if (audioDriver)   
00157      xine_close_audio_driver(xineEngine, audioDriver);
00158   if (videoDriver)   
00159      xine_close_video_driver(xineEngine, videoDriver);
00160   if (xineEngine)
00161      xine_exit(xineEngine);
00162   xineEngine = NULL;
00163 
00164   if (xineDisplay)
00165     XUnlockDisplay( xineDisplay ); 
00166 
00167  /*
00168   * FIXME
00169   * Removing XCloseDisplay() seems to be a workaround for the crash after closing on some systems...
00170   * We're looking for a better solution...
00171   */   
00172  /* if (xineDisplay)
00173     XCloseDisplay(xineDisplay); */  /* close xine display */
00174   xineDisplay = NULL;
00175 
00176   debugOut("xine closed\n");
00177 }
00178 
00179 /* Helper functions ... */
00180 QString QXineWidget::i18n(const char *text)
00181 {
00182 #ifdef USE_QT_ONLY
00183         return tr (text);
00184 #else
00185         return ::i18n(text);
00186 #endif
00187 }
00188 
00189 void QXineWidget::debugOut (QString qsDebug)
00190 {
00191 #ifdef USE_QT_ONLY
00192         QString qsDebugging = QString ("Debug: ") + qsDebug;
00193         printf ((const char *)qsDebugging);
00194 #else
00195         kdDebug(555) << (const char *)qsDebug << "\n";
00196 #endif
00197 }
00198 void QXineWidget::errorOut (QString qsError)
00199 {
00200 #ifdef USE_QT_ONLY
00201         QString qsErroring = QString ("Error: ") + qsError;
00202         printf ((const char *)qsErroring);
00203 #else
00204         kdError(555) << (const char *)qsError << "\n";
00205 #endif
00206 }
00207 void QXineWidget::warningOut (QString qsWarning)
00208 {
00209 #ifdef USE_QT_ONLY
00210         QString qsWarninging = QString ("Warning: ") + qsWarning;
00211         printf ((const char *)qsWarninging);
00212 #else
00213         kdWarning(555) << (const char *)qsWarning << "\n";
00214 #endif
00215 }
00216 
00217 void QXineWidget::postEvent(QObject *pObject,QEvent *pEvent)
00218 {
00219 #ifdef USE_QT_ONLY
00220         QApplication::postEvent (pObject, pEvent);
00221 #else
00222         KApplication::kApplication()->postEvent(pObject, pEvent);
00223 #endif
00224 }
00225 
00226 void QXineWidget::messageBoxError(QWidget *pWidget, QString qsMessage)
00227 {
00228 #ifdef USE_QT_ONLY
00229     QMessageBox::about(pWidget, qsMessage, qsMessage);
00230 #else
00231     KMessageBox::error(pWidget, qsMessage);
00232 #endif
00233 }
00234 
00235 
00236 void QXineWidget::SaveXineConfig()
00237 {
00238   if (!devicePath.isNull())
00239   {
00240     debugOut("Set CD/VCD/DVD path back");
00241     xine_cfg_entry_t config;
00242 
00243     xine_config_lookup_entry (xineEngine, "input.cdda_device", &config);
00244     if ( devicePath == config.str_value )
00245     {
00246       config.str_value = (char*)cachedCDPath.latin1();
00247       xine_config_update_entry (xineEngine, &config);
00248     }  
00249 
00250     xine_config_lookup_entry (xineEngine, "input.vcd_device", &config);
00251     if ( devicePath == config.str_value )
00252     {
00253       config.str_value = (char*)cachedVCDPath.latin1();
00254       xine_config_update_entry (xineEngine, &config);
00255     }  
00256 
00257     xine_config_lookup_entry (xineEngine, "input.dvd_device", &config);
00258     if ( devicePath == config.str_value )
00259     {
00260       config.str_value = (char*)cachedDVDPath.latin1();
00261       xine_config_update_entry (xineEngine, &config);
00262     }  
00263   }  
00264     
00265   debugOut(QString("Save %1\n").arg(configFile));
00266   xine_config_save(xineEngine, configFile);
00267 }  
00268 
00269 
00270 /***************************************************
00271  *         CALLBACKS
00272  ***************************************************/
00273 
00274 void QXineWidget::DestSizeCallback(void* p, int /*video_width*/, int /*video_height*/, double /*video_aspect*/,
00275                        int* dest_width, int* dest_height, double* dest_aspect)
00276 
00277 {
00278   if (p == NULL) return;
00279   QXineWidget* vw = (QXineWidget*) p;
00280 
00281   *dest_width = vw->width();
00282   *dest_height = vw->height();
00283   *dest_aspect = vw->displayRatio;
00284 }
00285 
00286 void QXineWidget::FrameOutputCallback(void* p, int video_width, int video_height, double video_aspect,
00287                           int* dest_x, int* dest_y, int* dest_width, int* dest_height,
00288                           double* dest_aspect, int* win_x, int* win_y)
00289 
00290 {
00291   if (p == NULL) return;
00292   QXineWidget* vw = (QXineWidget*) p;
00293 
00294   *dest_x = 0;
00295   *dest_y = 0 ;
00296   *dest_width = vw->width();
00297   *dest_height = vw->height();
00298   *win_x = vw->globX;
00299   *win_y = vw->globY;
00300   *dest_aspect = vw->displayRatio;
00301 
00302  /* correct size with video aspect */
00303   if (video_aspect >= vw->displayRatio)
00304     video_width  = (int) ( (double) (video_width * video_aspect / vw->displayRatio + 0.5) );
00305    else
00306     video_height = (int) ( (double) (video_height * vw->displayRatio / video_aspect) + 0.5);
00307 
00308  /*** set the size of main window (KMP) to fit the size of video stream ***/
00309   if (vw->autoresizeEnabled)
00310   {
00311     if ( (video_width != vw->videoFrameWidth) || (video_height != vw->videoFrameHeight) )
00312     {
00313       if ( (vw->parentWidget()) && (!vw->parentWidget()->isFullScreen()) && (vw->posTimer.isActive()) && (video_width > 0) && (video_height > 0) )
00314       {
00315         vw->videoFrameWidth = video_width;
00316         vw->videoFrameHeight = video_height;
00317 
00318         vw->newParentSize = vw->parentWidget()->size() - QSize((vw->width() - video_width), vw->height() - video_height);
00319         debugOut (QString("Resize video window to: %1x%2 ...").arg(vw->newParentSize.width()).arg(vw->newParentSize.height()));
00320         debugOut(QString("...with video frame: %1x%2, video aspect ratio: %3").arg(video_width).arg(video_height).arg(video_aspect));
00321 
00322         /* we should not do a resize() inside a xine thread,
00323            but post an event to the main thread */
00324         vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_RESIZE_PARENT ) );
00325       }
00326     }
00327   }
00328 }
00329 
00330 
00331 /*
00332  * XINE EVENT THREAD
00333  * only the QT event thread should do GUI operations,
00334  * we use QApplication::postEvent() and a reimplementation of QObject::timerEvent() to
00335  * make sure all critical jobs are done within the QT main thread context
00336  *
00337  * for more information see http://doc.trolltech.com/3.1/threads.html
00338  */
00339 
00340 void QXineWidget::XineEventListener(void *p, const xine_event_t* xineEvent)
00341 {
00342 
00343   if (p == NULL) return;
00344   QXineWidget* vw = (QXineWidget*) p;
00345 
00346  // KApplication::kApplication()->lock(); /* lock QT event thread */
00347   
00348   switch (xineEvent->type)
00349   {
00350     case XINE_EVENT_UI_PLAYBACK_FINISHED:
00351        {
00352          debugOut("xine event: playback finished");
00353          vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_PLAYBACK_FINISHED ) );
00354          break; 
00355        }
00356     case XINE_EVENT_UI_CHANNELS_CHANGED:  /* new channel informations */
00357       {
00358         debugOut("xine event: channels changed");
00359         int i,j,channels;
00360         char* lang = new char[128];     /* more than enough */
00361         QString num;
00362 
00363         vw->audioCh.clear();
00364         vw->subCh.clear();
00365 
00366         /*** get audio channels  ***/
00367         channels = QMAX(6, xine_get_stream_info(vw->xineStream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL));
00368         for(i = 0; i < channels; i++)
00369         {
00370           if (xine_get_audio_lang(vw->xineStream, i, lang))
00371             vw->audioCh << lang;
00372            else
00373             vw->audioCh << vw->i18n("Ch ") + num.setNum(i+1);
00374         }     
00375 
00376         /*** get subtitle channels ***/
00377     
00378         channels = QMAX(6, xine_get_stream_info(vw->xineStream, XINE_STREAM_INFO_MAX_SPU_CHANNEL));
00379         for(j = 0; j < channels; j++)
00380         {
00381           if (xine_get_spu_lang(vw->xineStream, j, lang))
00382             vw->subCh << lang;
00383            else
00384             vw->subCh << vw->i18n("Ch ") + num.setNum(j+1);
00385         }    
00386 
00387         delete lang;  /* or not? */
00388 
00389         vw->currentAudio = xine_get_param(vw->xineStream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
00390         vw->currentSub = xine_get_param(vw->xineStream, XINE_PARAM_SPU_CHANNEL);
00391  
00392         if (vw->currentAudio > (i-1))
00393         {
00394           vw->slotSetAudioChannel(0);
00395           vw->currentAudio = -1;
00396         }
00397           
00398         if (vw->currentSub > (j-1))
00399         {
00400           vw->slotSetSubtitleChannel(0);
00401           vw->currentSub = -1;
00402          }
00403 
00404          vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_NEW_CHANNELS ) );
00405          break;
00406       }
00407     case XINE_EVENT_UI_SET_TITLE:  /* set new title */
00408        {
00409         debugOut("xine event: ui set title");
00410         xine_ui_data_t* xd = (xine_ui_data_t*)xineEvent->data;
00411         vw->currentTitle = QString::fromLocal8Bit( (char*)xd->str );
00412         vw->trackInfoRow = vw->currentTitle + " ** " + vw->GetStreamInfo() + vw->extraInfo;
00413 
00414         vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_NEW_TITLE ) );
00415         vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_NEW_INFO ) );
00416         break;
00417        }
00418      case XINE_EVENT_PROGRESS:
00419        {
00420         debugOut("xine event: progress info");
00421         xine_progress_data_t* pd = (xine_progress_data_t*)xineEvent->data;
00422 
00423         QString perc;
00424         perc.setNum(pd->percent);
00425         perc.append(" %");
00426         
00427         vw->currentProgress = pd->description;
00428         vw->currentProgress.append("  ");
00429         vw->currentProgress.append(perc);
00430         
00431         if (pd->percent != 100)
00432           vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_NEW_PROGRESS_INFO ) );
00433          else
00434           vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_NEW_INFO ) );
00435 
00436         break;
00437         }
00438      case XINE_EVENT_DROPPED_FRAMES:
00439       {
00440         debugOut("xine event: dropped frames");
00441         xine_dropped_frames_t* dropped = (xine_dropped_frames_t*)xineEvent->data;
00442         
00443         warningOut(QString("skipped frames: %1% discarded frames: %2%").arg( dropped->skipped_frames/10).arg(dropped->discarded_frames/10));
00444 
00445         break;
00446        }  
00447      case XINE_EVENT_SPU_BUTTON:
00448        {
00449          debugOut("xine event: spu button");
00450          xine_spu_button_t* button = (xine_spu_button_t*)xineEvent->data;
00451 
00452          if (button->direction == 1) /* enter a button */
00453          {          
00454            debugOut("DVD Menu: Mouse entered button");
00455            vw->DVDButtonEntered = true;
00456          }  
00457          else
00458          {
00459            debugOut("DVD Menu: Mouse leaved button");
00460            vw->DVDButtonEntered = false;
00461          }  
00462 
00463          vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_CHANGE_CURSOR ) );
00464          break;
00465        }  
00466      case XINE_EVENT_UI_NUM_BUTTONS:
00467        {
00468          debugOut("xine event: ui num buttons");
00469          xine_ui_data_t *buttons = (xine_ui_data_t *)xineEvent->data;
00470          if(buttons->num_buttons >= 1)
00471            vw->DVDMenuEntered = true; 
00472           else
00473            vw->DVDMenuEntered = false;
00474     
00475          debugOut(QString("DVD Menu: Num buttons=%1").arg(buttons->num_buttons));
00476          vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_GRAB_KEYBOARD ) );
00477          break;
00478        }
00479      case XINE_EVENT_MRL_REFERENCE:
00480        {
00481          debugOut("xine event: mrl reference");
00482          xine_mrl_reference_data_t* mrldata = (xine_mrl_reference_data_t*)xineEvent->data;
00483          vw->newMrlReference = mrldata->mrl;
00484 
00485          vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_NEW_MRL_REFERENCE ) );
00486          break;
00487        }
00488      case XINE_EVENT_UI_MESSAGE:
00489        {
00490          debugOut("xine event: xine message");
00491          
00492          xine_ui_message_data_t *data = (xine_ui_message_data_t *)xineEvent->data;
00493          QString message;
00494 
00495          /* some code take from the xine-ui - Copyright (C) 2000-2003 the xine project */
00496          switch(data->type)
00497          {
00498            case XINE_MSG_NO_ERROR:
00499              {               
00500               /* copy strings, and replace '\0' separators by '\n' */
00501                char* s = data->messages;
00502                char* d = new char[2000];
00503      
00504                while(s && (*s != '\0') && ((*s + 1) != '\0'))
00505                {
00506                   switch(*s)
00507                   {
00508                     case '\0':
00509                       {
00510                          *d = '\n';
00511                          break;
00512                       }
00513                     default:
00514                       {
00515                          *d = *s;
00516                           break;
00517                       }
00518                   }   
00519                   s++;
00520                   d++;
00521                }
00522                *++d = '\0';
00523 
00524                message = d;
00525                delete d;
00526                break;
00527              }
00528            case XINE_MSG_GENERAL_WARNING:
00529             {
00530               message = vw->i18n("General Warning: \n");
00531 
00532               if(data->explanation)
00533                 message = message + ((char *) data + data->explanation) + " " + ((char *) data + data->parameters);
00534               else
00535                 message = message + vw->i18n("No Informations available.");
00536 
00537               break;
00538             }  
00539           case XINE_MSG_UNKNOWN_HOST:
00540             {
00541               message = vw->i18n("The host you're trying to connect is unknown.\nCheck the validity of the specified hostname. ");
00542                 if(data->explanation)
00543                   message = message + "(" + ((char *) data + data->parameters) + ")";
00544               break;
00545             }
00546           case XINE_MSG_UNKNOWN_DEVICE:
00547             {
00548               message = vw->i18n("The device name you specified seems invalid. ");
00549               if(data->explanation)
00550                 message = message + "(" + ((char *) data + data->parameters) + ")";
00551               break;
00552             }
00553           case XINE_MSG_NETWORK_UNREACHABLE:
00554             {
00555               message = vw->i18n("The network looks unreachable.\nCheck your network setup and the server name. ");
00556               if(data->explanation)
00557                 message = message + "(" + ((char *) data + data->parameters) + ")";
00558               break;
00559             }
00560           case XINE_MSG_CONNECTION_REFUSED:
00561             {
00562               message = vw->i18n("The connection was refused.\nCheck the host name. ");
00563               if(data->explanation)
00564                 message = message + "(" + ((char *) data + data->parameters) + ")";
00565               break;
00566             }
00567           case XINE_MSG_FILE_NOT_FOUND:
00568             {
00569               message = vw->i18n("The specified file or url was not found. Please check it. ");
00570               if(data->explanation)
00571                 message = message + "(" + ((char *) data + data->parameters) + ")";
00572               break;
00573             }  
00574           case XINE_MSG_READ_ERROR:
00575             {
00576               message = vw->i18n("The source can't be read.\nMaybe you don't have enough rights for this, or source doesn't contain data (e.g: no disc in drive). ");
00577               if(data->explanation)
00578                 message = message + "(" + ((char *) data + data->parameters) + ")";
00579               break;
00580             }  
00581           case XINE_MSG_LIBRARY_LOAD_ERROR:
00582             {
00583               message = vw->i18n("A problem occur while loading a library or a decoder: ");
00584               if(data->explanation)
00585                 message = message + ((char *) data + data->parameters);
00586               break;
00587             }  
00588           case XINE_MSG_ENCRYPTED_SOURCE:
00589             {
00590               message = vw->i18n("The source seems encrypted, and can't be read. ");
00591               if (vw->currentMRL.contains("dvd:/"))
00592                 message = message + vw->i18n("\nYour DVD is probably crypted. According to your country laws, you can or can't use libdvdcss to be able to read this disc. ");
00593               if(data->explanation)
00594                 message = message + "(" + ((char *) data + data->parameters) + ")";
00595               break;
00596             }
00597           default:
00598             {
00599               message = vw->i18n("Unkown error: \n");
00600               if(data->explanation)
00601                 message = message + ((char *) data + data->explanation) + " " + ((char *) data + data->parameters);
00602               break;
00603             }
00604           }
00605 
00606          vw->xineMessage = message;
00607          vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_NEW_XINE_MESSAGE ) );
00608          break;
00609        }
00610      default:
00611        {
00612         // debugOut("xine event: unhandled type %1").arg(xineEvent->type);
00613          break;
00614        }    
00615    }
00616 
00617  //  KApplication::kApplication()->unlock();
00618 }
00619 
00620 
00621 void QXineWidget::timerEvent( QTimerEvent* tevent )
00622 {
00623   switch ( tevent->timerId() )
00624   {
00625     case TIMER_EVENT_PLAYBACK_FINISHED:
00626     {
00627       emit signalPlaybackFinished();
00628       break;
00629     }
00630     case TIMER_EVENT_NEW_CHANNELS:
00631     {
00632       emit signalNewChannels( audioCh, subCh, currentAudio, currentSub);
00633       break;
00634     }
00635     case TIMER_EVENT_NEW_TITLE:
00636     {
00637        emit signalNewTitle( currentTitle );
00638        break;
00639     }
00640     case TIMER_EVENT_NEW_INFO:
00641     {
00642        emit signalNewInfo( trackInfoRow );
00643        break;
00644     }
00645     case TIMER_EVENT_NEW_PROGRESS_INFO:
00646     {
00647        emit signalNewInfo( currentProgress );
00648        break;
00649     }
00650     case TIMER_EVENT_CHANGE_CURSOR:
00651     {
00652       if (DVDButtonEntered)
00653         setCursor(QCursor(Qt::PointingHandCursor));
00654        else
00655         setCursor(QCursor(Qt::ArrowCursor));
00656       break;
00657     }      
00658     case TIMER_EVENT_GRAB_KEYBOARD:
00659     {
00660       if (DVDMenuEntered)
00661         grabKeyboard();
00662        else
00663         releaseKeyboard();
00664       break;  
00665     }      
00666     case TIMER_EVENT_NEW_MRL_REFERENCE:
00667     {
00668        emit signalNewMrlReference( newMrlReference );
00669        break;
00670     }
00671     case TIMER_EVENT_NEW_XINE_MESSAGE:
00672     {
00673        emit signalNewXineMessage();
00674        break;
00675     }
00676     case TIMER_EVENT_RESTART_PLAYBACK:
00677     {
00678       PlayMRL( currentMRL, currentTitle, false );
00679       slotChangePosition( savedPos );
00680       break;
00681     }
00682     case TIMER_EVENT_RESIZE_PARENT:
00683     {
00684       parentWidget()->resize( newParentSize );
00685       break;
00686     }    
00687     default: break;
00688   }
00689 }      
00690 
00691 
00692 /******************* new video driver *********************/
00693 
00694 void QXineWidget::VideoDriverChangedCallback(void* p, xine_cfg_entry_t* entry)
00695 {
00696   if (p == NULL) return;
00697   QXineWidget* vw = (QXineWidget*) p;
00698 
00699   int pos, time, length;
00700   
00701   debugOut(QString("New video driver: %1").arg(entry->enum_values[entry->num_value]));
00702 
00703   bool playing = false;
00704   if (xine_get_status(vw->xineStream) == XINE_STATUS_PLAY)
00705   {
00706     playing = true;
00707     vw->savedPos = 0;
00708     if ( xine_get_pos_length(vw->xineStream, &pos, &time, &length) )
00709      vw->savedPos = pos;
00710   }   
00711 
00712   xine_close(vw->xineStream);
00713 
00714   if (vw->xinePost)
00715   {
00716      debugOut(QString("Dispose visual plugin: %1").arg(vw->visualPluginName));
00717      vw->postAudioSource = xine_get_audio_source (vw->xineStream);
00718      xine_post_wire_audio_port (vw->postAudioSource, vw->audioDriver);
00719      xine_post_dispose (vw->xineEngine, vw->xinePost);
00720      vw->xinePost = NULL;
00721   }
00722   
00723   xine_event_dispose_queue(vw->eventQueue);
00724   xine_dispose(vw->xineStream);
00725   xine_close_video_driver(vw->xineEngine, vw->videoDriver);
00726   vw->videoDriver = NULL;
00727 
00728   vw->videoDriver = xine_open_video_driver(vw->xineEngine,
00729                            entry->enum_values[entry->num_value], XINE_VISUAL_TYPE_X11,
00730                            (void *) &(vw->visual));
00731 
00732 
00733   if (!vw->videoDriver)
00734   {
00735      QApplication::beep();
00736      vw->trackInfoRow = vw->i18n("Error: Can't init new Video Driver %1 - using %2!").arg(entry->enum_values[entry->num_value]).arg(vw->videoDriverName);
00737      vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_NEW_INFO ) );
00738      playing = false;
00739      vw->videoDriver = xine_open_video_driver(vw->xineEngine,
00740                            vw->videoDriverName, XINE_VISUAL_TYPE_X11,
00741                            (void *) &(vw->visual));
00742   }
00743   else
00744   {
00745      vw->videoDriverName = entry->enum_values[entry->num_value];
00746      vw->trackInfoRow = vw->i18n("Using Video Driver: ") + vw->videoDriverName;
00747      vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_NEW_INFO ) );
00748   }
00749 
00750   vw->xineStream = xine_stream_new(vw->xineEngine, vw->audioDriver, vw->videoDriver);
00751   vw->eventQueue = xine_event_new_queue (vw->xineStream);
00752   xine_event_create_listener_thread(vw->eventQueue, &QXineWidget::XineEventListener, p);
00753 
00754   if (playing)
00755     vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_RESTART_PLAYBACK ) );
00756 }
00757 
00758 
00759 /*********************** new audio driver *************************/
00760 
00761 void QXineWidget::AudioDriverChangedCallback(void* p, xine_cfg_entry_t* entry)
00762 {
00763   if (p == NULL) return;
00764   QXineWidget* vw = (QXineWidget*) p;
00765 
00766   int pos, time, length;
00767 
00768   debugOut(QString("New audio driver: %1").arg(entry->enum_values[entry->num_value]));
00769 
00770   bool playing = false;
00771   if (xine_get_status(vw->xineStream) == XINE_STATUS_PLAY)
00772   {
00773     playing = true;
00774     vw->savedPos = 0;
00775     if ( xine_get_pos_length(vw->xineStream, &pos, &time, &length) )
00776      vw->savedPos = pos;
00777   }
00778 
00779   xine_close(vw->xineStream);
00780 
00781   if (vw->xinePost)
00782   {
00783      debugOut(QString("Dispose visual plugin: %1").arg(vw->visualPluginName));
00784      vw->postAudioSource = xine_get_audio_source (vw->xineStream);
00785      xine_post_wire_audio_port (vw->postAudioSource, vw->audioDriver);
00786      xine_post_dispose (vw->xineEngine, vw->xinePost);
00787      vw->xinePost = NULL;
00788   }
00789 
00790   xine_event_dispose_queue(vw->eventQueue);
00791   xine_dispose(vw->xineStream);
00792   xine_close_audio_driver(vw->xineEngine, vw->audioDriver);
00793   vw->audioDriver = NULL;
00794 
00795   vw->audioDriver = xine_open_audio_driver(vw->xineEngine, entry->enum_values[entry->num_value], NULL);
00796 
00797   if (!vw->audioDriver)
00798   {
00799      QApplication::beep();
00800      vw->trackInfoRow = vw->i18n("Error: Can't init new Audio Driver %1 - using %2!").arg(entry->enum_values[entry->num_value]).arg(vw->audioDriverName);
00801      vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_NEW_INFO ) );
00802      playing = false;
00803      vw->audioDriver = xine_open_audio_driver(vw->xineEngine, vw->audioDriverName, NULL);
00804   }
00805   else
00806   {
00807      vw->audioDriverName = entry->enum_values[entry->num_value];
00808      vw->trackInfoRow = vw->i18n("Using Audio Driver: ") + vw->audioDriverName;
00809      vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_NEW_INFO ) );
00810   }
00811 
00812   vw->xineStream = xine_stream_new(vw->xineEngine, vw->audioDriver, vw->videoDriver);
00813   vw->eventQueue = xine_event_new_queue (vw->xineStream);
00814   xine_event_create_listener_thread(vw->eventQueue, &QXineWidget::XineEventListener, p);
00815 
00816   if (playing)
00817     vw->postEvent( vw, new QTimerEvent( TIMER_EVENT_RESTART_PLAYBACK ) );
00818 }
00819     
00820 
00821 /**********************************************
00822  *      EVENT LOOP
00823  *********************************************/
00824 
00825 void QXineWidget::run()
00826 {
00827   debugOut("Start event loop...\n");
00828 
00829   XEvent event;
00830 
00831   while( xineRunning )
00832   {
00833      XNextEvent ( xineDisplay, &event );
00834      XLockDisplay( xineDisplay );
00835      
00836      if (event.type == Expose)
00837      {
00838        if (event.xexpose.count == 0)
00839        {
00840          xine_gui_send_vo_data (xineStream, XINE_GUI_SEND_EXPOSE_EVENT, &event);
00841        }
00842      }
00843         
00844      XUnlockDisplay( xineDisplay );
00845   }
00846 
00847   debugOut("Exiting event loop...\n");
00848 }    
00849   
00850 
00851 
00852 /**********************************************************
00853  *           INIT XINE ENGINE
00854  *********************************************************/
00855 
00856 void QXineWidget::polish()
00857 {
00858   if (!startXineManual)  /* start xine engine automatically? */
00859   {
00860     if (!InitXine()) emit signalQuit(); /* no success */
00861   }  
00862 }    
00863 
00864 bool QXineWidget::InitXine()
00865 {
00866   if (xineRunning) return true;
00867  
00868   bool cmdlAudioEnum = false, cmdlVideoEnum = false;
00869 
00870   GlobalPosChanged(); /* get global pos of the window */
00871    
00872 /**** INIT XINE DISPLAY  ****/
00873  
00874   if (!XInitThreads ())
00875   {
00876     QApplication::beep();
00877     messageBoxError(0, i18n("XInitThreads failed!"));
00878     return false;
00879   }
00880 
00881   xineDisplay = XOpenDisplay( getenv("DISPLAY") );
00882 
00883   if (!xineDisplay)
00884   {
00885     QApplication::beep();
00886     messageBoxError(0, i18n("Failed to connect to X-Server!"));
00887     return false;
00888   }
00889 
00890   xineScreen = DefaultScreen( xineDisplay );
00891   xineWindow = winId();
00892 
00893   XLockDisplay( xineDisplay );
00894 
00895   XSelectInput( xineDisplay, xineWindow, ExposureMask );
00896 
00897 
00898 /* determine display aspect ratio  */
00899   double resHor = DisplayWidth( xineDisplay, xineScreen )*1000 / DisplayWidthMM( xineDisplay, xineScreen );
00900   double resVer = DisplayHeight( xineDisplay, xineScreen )*1000 / DisplayHeightMM( xineDisplay, xineScreen );
00901 
00902   displayRatio = resVer / resHor;
00903   //if (QABS( displayRatio - 1.0 ) < 0.01) displayRatio   = 1.0;
00904 
00905   debugOut(QString("Display aspect ratio (v/h): %1").arg(displayRatio));
00906 
00907   XUnlockDisplay( xineDisplay );
00908 
00909 /**** INIT XINE ENGINE ****/
00910 
00911   debugOut(QString("Using xine version %1\n").arg(xine_get_version_string()));
00912 
00913   xineEngine = xine_new();
00914   if (!xineEngine)
00915   {
00916     QApplication::beep();
00917     messageBoxError(0, i18n("Can't init xine Engine!"));
00918     return false;
00919   }
00920 
00921   if (xineVerbose)
00922    xine_engine_set_param( xineEngine, XINE_ENGINE_PARAM_VERBOSITY, 99 );
00923 
00924 /* load configuration */
00925 
00926   configFile = QDir::homeDirPath();
00927   configFile.append("/.kaffeine/config");
00928 
00929   if (QFile::exists(configFile))
00930     xine_config_load (xineEngine, configFile);
00931   else
00932     warningOut("No config file found, will create one...\n");
00933 
00934 
00935    debugOut("Post-init xine engine\n");
00936    xine_init(xineEngine);
00937 
00940   const char* const* drivers = NULL;
00941   char** audioChoices = NULL;
00942   int i = 0;
00943 
00944   drivers = xine_list_audio_output_plugins (xineEngine);
00945   audioChoices = new char*[15];
00946   for(i = 0; i < 15; i++) audioChoices[i] = new char[10];
00947   audioChoices[0] = const_cast<char*>("auto");
00948   i = 0;
00949   while(drivers[i])
00950   {
00951     audioChoices[i+1] = (char*)drivers[i];
00952     if (preferedAudio == drivers[i]) cmdlAudioEnum = true;
00953     i++;
00954   }  
00955   audioChoices[i+1] = NULL;
00956   if (preferedAudio == "auto") cmdlAudioEnum = true;
00957   
00958   char* audioInfo = new char[200];
00959   strcpy(audioInfo, i18n("Audiodriver to use (default: auto)").local8Bit() );
00960   i = xine_config_register_enum(xineEngine, "gui.audiodriver", 0,
00961                    audioChoices, audioInfo, NULL, 10, &QXineWidget::AudioDriverChangedCallback, this);
00962 
00963   if (cmdlAudioEnum)
00964     audioDriverName = preferedAudio;
00965    else 
00966     audioDriverName = audioChoices[i];
00967 
00968   debugOut(QString("Use audio driver %1\n").arg(audioDriverName));
00969 
00970   i = 0;
00971   char** videoChoices = NULL;
00972   drivers = xine_list_video_output_plugins (xineEngine);
00973   videoChoices = new char*[15];
00974   for(i = 0; i < 15; i++) videoChoices[i] = new char[10];
00975   i = 0;
00976   videoChoices[0] = const_cast<char*>("auto");
00977   while(drivers[i])
00978   {
00979     videoChoices[i+1] = (char*)drivers[i];
00980     if (preferedVideo == drivers[i]) cmdlVideoEnum = true;
00981     i++;
00982   }
00983   videoChoices[i+1] = NULL;
00984   if (preferedVideo == "auto") cmdlVideoEnum = true;
00985 
00986   char* videoInfo = new char[200];
00987   strcpy( videoInfo, i18n("Videodriver to use (default: auto)").local8Bit() );
00988   i = xine_config_register_enum(xineEngine, "gui.videodriver", 0,
00989                    videoChoices, videoInfo, NULL, 10, &QXineWidget::VideoDriverChangedCallback, this);
00990 
00991   if (cmdlVideoEnum)
00992     videoDriverName = preferedVideo;
00993    else 
00994     videoDriverName = videoChoices[i];
00995 
00996   debugOut(QString("Use video driver %1\n").arg(videoDriverName));
00997 
00998 
00999 
01000 /* init video driver */
01001   visual.display          = xineDisplay;
01002   visual.screen           = xineScreen;
01003   visual.d                = xineWindow;
01004   visual.dest_size_cb     = &QXineWidget::DestSizeCallback;
01005   visual.frame_output_cb  = &QXineWidget::FrameOutputCallback;
01006   visual.user_data        = (void*)this;
01007 
01008   debugOut("Init video driver\n");
01009 
01010   videoDriver = xine_open_video_driver(xineEngine,
01011                videoDriverName,  XINE_VISUAL_TYPE_X11,
01012                (void *) &(visual));
01013   if (!videoDriver)
01014   {
01015     QApplication::beep();
01016     messageBoxError(0, i18n("Can't init Video Driver!") + " (" + videoDriverName + ")");
01017     return false;
01018   }
01019 
01020 /* init audio driver */  
01021   debugOut("Init audio driver\n");
01022   
01023   audioDriver = xine_open_audio_driver (xineEngine, audioDriverName, NULL);
01024   if (!audioDriver)
01025   {
01026     QApplication::beep();
01027     messageBoxError(0, i18n("Can't init Audio Driver!")+ " (" + audioDriverName + ")");
01028     return false;
01029   }
01030 
01031 // debugOut("Open stream\n");
01032   
01033   xineStream  = xine_stream_new(xineEngine, audioDriver, videoDriver);
01034   if (!xineStream)
01035   {
01036     QApplication::beep();
01037     messageBoxError(0, i18n("Can't create a new xine Stream!"));
01038     return false;
01039   }
01040   
01043   eventQueue = xine_event_new_queue (xineStream);
01044   xine_event_create_listener_thread(eventQueue, &QXineWidget::XineEventListener, (void*)this);
01045 
01046 /* set path to logo file */
01047   setLogoFile();
01048 
01051 #ifdef HAVE_XTEST
01052 int a,b,c,d;
01053   haveXTest = XTestQueryExtension(x11Display(), &a, &b, &c, &d);
01054   if (haveXTest)
01055     xTestKeycode = XKeysymToKeycode(x11Display(), XK_Shift_L);
01056   
01057 #endif
01058 
01059        
01060   debugOut("xine init successful\n");
01061   xineRunning = true;
01062 
01064   start();
01065 
01066   parentWidget()->polish(); /* make sure gui will build correctly */
01067   
01068   return true;
01069 }
01070 
01071 void QXineWidget::setLogoFile()
01072 {
01073         // virtual function, Reimplemented in VideoWindow
01074 }
01075 
01076 /************************************************
01077  *              PLAY MRL
01078  ************************************************/
01079 
01080 
01081 bool QXineWidget::PlayMRL(const QString& mrl, const QString& title, bool returnInfo)
01082 {
01083   lengthInfoTimer.stop();
01084   
01085  // if (xine_get_status(xineStream) == XINE_STATUS_PLAY)
01086  //   xine_stop(xineStream);
01087 
01088   emit signalNewInfo(i18n("Opening..."));
01089   setCursor(QCursor(Qt::WaitCursor));
01090 
01091   currentMRL = mrl;
01092 
01093  /* check for external subtitle file or save url */
01094   extraInfo = QString::null;
01095   QString ref;
01096   
01097   for (int i = 1; i <= mrl.contains('#'); i++)
01098   {
01099     ref = mrl.section('#', i, i);
01100     if (ref.section(':', 0, 0) == "subtitle")
01101       extraInfo = extraInfo + " ** " + i18n("Subtitles: ") + ref.section(':', 1);
01102     if (ref.section(':', 0, 0) == "save")
01103       extraInfo = extraInfo + " ** " + i18n("Save as: ") + ref.section(':', 1);
01104   }
01105  
01106   debugOut(QString("Playing: %1").arg(currentMRL.local8Bit()));
01107 
01108   if (!xine_open(xineStream, currentMRL.local8Bit() )) 
01109   {
01110     SendXineError( returnInfo );
01111     setCursor(QCursor(Qt::ArrowCursor));
01112     return false;
01113   }  
01114 
01115 /**** use visualization ? ****/
01116 
01117   if ( (xine_get_stream_info (xineStream, XINE_STREAM_INFO_HAS_AUDIO)) &&
01118        (!xine_get_stream_info (xineStream, XINE_STREAM_INFO_HAS_VIDEO)) )
01119   {
01120 
01121     if (visualPluginName && (!xinePost))
01122     {
01123       debugOut(QString("Init visual plugin: %1").arg(visualPluginName));
01124       xinePost = xine_post_init (xineEngine, visualPluginName, 0,
01125           &audioDriver,
01126           &videoDriver);
01127 
01128       postAudioSource = xine_get_audio_source (xineStream);
01129       postInput = (xine_post_in_t*)xine_post_input (xinePost, const_cast<char*>("audio in"));
01130       xine_post_wire (postAudioSource, postInput);
01131     }
01132   }
01133   else
01134   {
01135     if (xinePost)
01136     {
01137       debugOut(QString("Dispose visual plugin: %1").arg(visualPluginName));
01138       postAudioSource = xine_get_audio_source (xineStream);
01139       xine_post_wire_audio_port (postAudioSource, audioDriver);
01140       xine_post_dispose (xineEngine, xinePost);
01141       xinePost = NULL;
01142     }
01143   }
01144   
01145 /*** play ***/
01146 
01147   if (!xine_play(xineStream, 0,0))
01148   {
01149     SendXineError( returnInfo );
01150     setCursor(QCursor(Qt::ArrowCursor));
01151     return false;
01152   }
01153 
01154 /* do the stream have chapters ? */
01155   if (xine_get_stream_info(xineStream, XINE_STREAM_INFO_HAS_CHAPTERS))
01156     emit signalHasChapters(true);
01157    else
01158     emit signalHasChapters(false);
01159 
01160 
01163   currentTitle = title;
01164 
01165   if ( (title.contains('.')) || (title.contains(":/")) ) /* tags was still read? */
01166   {
01167     QString metaTitle = QString::fromLocal8Bit( xine_get_meta_info(xineStream, XINE_META_INFO_TITLE) );
01168     if ( (metaTitle) && (!metaTitle.isEmpty()) )  //usable meta info
01169     {
01170       QString metaArtist = QString::fromLocal8Bit(xine_get_meta_info(xineStream, XINE_META_INFO_ARTIST));
01171       QString metaAlbum = QString::fromLocal8Bit(xine_get_meta_info(xineStream, XINE_META_INFO_ALBUM));
01172       QString metaTrack = ""; /* not implemented in xine-lib */
01173       QString metaInfo = metaString;
01174       metaInfo.replace( "artist", metaArtist );
01175       metaInfo.replace( "title",  metaTitle );
01176       metaInfo.replace( "album",  metaAlbum );
01177       metaInfo.replace( "track",  metaTrack );;
01178       currentTitle = metaInfo;
01179       if ((metaInfo != title) && (returnInfo))
01180       {
01181         emit signalMetaInfo(metaInfo);
01182       }
01183     }
01184     if (returnInfo)
01185     {
01186       QString length = GetLengthInfo();
01187       if (!length.isNull())
01188         emit signalLengthInfo( length );
01189        else
01190         lengthInfoTimer.start( 1000 ); /* wait for available track length info */
01191     }      
01192   }
01193 
01194   trackInfoRow = currentTitle;
01195 
01196   QString streamInfo = GetStreamInfo();
01197   if (returnInfo)
01198   {
01199      emit signalStreamInfo(streamInfo);
01200   }
01201 
01202   streamInfo = streamInfo + extraInfo;
01203                                                                                                         
01204   trackInfoRow.append( streamInfo.prepend(" ** ") );
01205   emit signalNewInfo(trackInfoRow);
01206    
01207   slotSetAudioChannel(0); //refresh channel info
01208 
01209   posTimer.start(500);
01210 
01211   setCursor(QCursor(Qt::ArrowCursor));
01212                 
01213   emit signalShowOSD(currentTitle);
01214 
01215   return true;
01216 }
01217 
01218 
01219 /****** error processing ****/
01220 
01221 void QXineWidget::SendXineError( bool returnInfo )
01222 {
01223   QString error;
01224   int errCode = xine_get_error(xineStream);
01225 
01226   switch (errCode)
01227   {
01228     case XINE_ERROR_NO_INPUT_PLUGIN:    
01229     case XINE_ERROR_NO_DEMUX_PLUGIN:
01230     {
01231       error = i18n("No plugin found to handle this resource");
01232       break;
01233     }
01234     case XINE_ERROR_DEMUX_FAILED:
01235     {
01236       error = i18n("Resource seems to be broken");
01237       break;
01238     }
01239     case XINE_ERROR_MALFORMED_MRL:
01240     {
01241       error = i18n("Requested resource does not exist");
01242       break;
01243     }
01244     case XINE_ERROR_INPUT_FAILED:
01245     {
01246       error = i18n("Resource can not be opened");
01247       break;
01248     }
01249     default:
01250     {
01251       error = i18n("Generic error");
01252       break;
01253     }  
01254   }
01255 
01256   emit signalNewInfo( i18n("Error: ") + error );
01257 
01258   if (returnInfo)
01259   {
01260       emit signalStreamInfo( error );
01261       emit signalLengthInfo( i18n("*Error*") );
01262   }
01263 }
01264 
01265 
01266 /****  visual plugin **********/
01267 
01268 
01269 void QXineWidget::GetVisualPlugins(QStringList& visuals) const
01270 {
01271   const char* const* plugins = xine_list_post_plugins_typed(xineEngine, XINE_POST_TYPE_AUDIO_VISUALIZATION);
01272 
01273   for (int i = 0; plugins[i]; i++)
01274   {
01275     visuals << plugins[i];
01276   }
01277 }   
01278 
01279 
01280 /**************** change visualization plugin *****************/
01281 
01282 void QXineWidget::SetVisualPlugin(const QString& visual)
01283 {
01284   if ( visualPluginName == visual ) return;
01285   
01286   debugOut(QString("New visualization plugin: %1").arg(visual));
01287 
01288   if (visual == "none")
01289     visualPluginName = QString::null;
01290    else
01291     visualPluginName = visual;
01292 
01293   if (xinePost)
01294   {
01295     xine_post_out_t *pp;
01296 
01297     pp = xine_get_audio_source (xineStream);
01298     xine_post_wire_audio_port (pp, audioDriver);
01299     xine_post_dispose (xineEngine, xinePost);
01300     xinePost = NULL;
01301   }
01302 
01303 
01304 
01305   if ( (xine_get_status( xineStream ) == XINE_STATUS_PLAY)
01306        && (!xine_get_stream_info(xineStream, XINE_STREAM_INFO_HAS_VIDEO)) && (visualPluginName) )
01307   {
01308 
01309     xinePost = xine_post_init (xineEngine, visualPluginName, 0, &audioDriver, &videoDriver);
01310     postAudioSource = xine_get_audio_source(xineStream);
01311     postInput = (xine_post_in_t*)xine_post_input(xinePost, const_cast<char*>("audio in"));
01312     xine_post_wire( postAudioSource, postInput );
01313   }
01314 }
01315 
01316 
01317 /*****/
01318 
01319 
01320 void QXineWidget::GetAutoplayPlugins(QStringList& autoPlayList) const
01321 {
01322   char** pluginIds = NULL;
01323   int i = 0;
01324 
01325   pluginIds = (char**)xine_get_autoplay_input_plugin_ids(xineEngine);
01326 
01327   while(pluginIds[i])
01328   {
01329     autoPlayList << pluginIds[i];
01330     
01331     autoPlayList << xine_get_input_plugin_description(xineEngine, pluginIds[i]);    
01332     i++;
01333   }
01334 }
01335 
01336  
01337 bool QXineWidget::GetAutoplayPluginMrl(const QString& plugin, QStringList& list)
01338 {
01339   char** mrls = NULL;
01340   int num;
01341   int i = 0;
01342 
01343   mrls = xine_get_autoplay_mrls(xineEngine, plugin, &num);
01344 
01345   if (mrls)
01346   {
01347     while (mrls[i])
01348       {
01349         list << mrls[i];
01350         i++;
01351       }  
01352 
01353     return true;
01354    } 
01355    else 
01356    {
01357      QString error(i18n("Error: No "));
01358      error.append(plugin);
01359      error.append(i18n(", or wrong path to device."));
01360      signalNewInfo(error);
01361      return false;
01362    }
01363 }
01364 
01365 
01366 void QXineWidget::slotSetVolume(int vol)
01367 {
01368   xine_set_param(xineStream, XINE_PARAM_AUDIO_VOLUME, -vol);
01369 }
01370 
01371 
01372 void QXineWidget::mouseMoveEvent(QMouseEvent* mev)
01373 {
01374    if (!xineRunning) return;
01375 
01376  //  debugOut("mouse move event");
01377    
01378    if (cursor().shape() == Qt::BlankCursor)
01379    {
01380      setCursor(QCursor(Qt::ArrowCursor));
01381    }  
01382 
01383     x11_rectangle_t   rect;
01384     xine_event_t      event;
01385     xine_input_data_t input;
01386 
01387     rect.x = mev->x();
01388     rect.y = mev->y();
01389     rect.w = 0;
01390     rect.h = 0;
01391 
01392     xine_gui_send_vo_data (xineStream,
01393                XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO,
01394                 (void*)&rect);
01395 
01396     event.type        = XINE_EVENT_INPUT_MOUSE_MOVE;
01397     event.data        = &input;
01398     event.data_length = sizeof(input);
01399     input.button      = 0; 
01400     input.x           = rect.x;
01401     input.y           = rect.y;
01402     xine_event_send (xineStream, &event);
01403 }
01404 
01405 
01406 void QXineWidget::mousePressEvent(QMouseEvent* mev)
01407 {
01408    if (!xineRunning) return;
01409    int cur = cursor().shape();
01410 
01411  //  debugOut("mouse press event");
01412 
01413    if (mev->button() == Qt::MidButton)
01414      emit signalToggleFullscreen();
01415 
01416    if (mev->button() == Qt::RightButton)
01417    {
01418      if ( (cur == Qt::ArrowCursor) || (cur == Qt::BlankCursor) )
01419      {
01420        emit signalShowContextMenu(mev->globalPos());
01421        return;
01422      }  
01423    }  
01424 
01425    if (mev->button() == Qt::LeftButton)
01426    {
01427      if ( (cur == Qt::ArrowCursor) || (cur == Qt::BlankCursor) )
01428      {
01429        emit signalShowFullscreenPanel(mev->globalPos());
01430        return;
01431      }  
01432 
01433      x11_rectangle_t   rect;
01434      xine_event_t      event;
01435      xine_input_data_t input;
01436 
01437      rect.x = mev->x();
01438      rect.y = mev->y();
01439      rect.w = 0;
01440      rect.h = 0;
01441 
01442      xine_gui_send_vo_data (xineStream,
01443                 XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO,
01444                    (void*)&rect);
01445 
01446      event.type        = XINE_EVENT_INPUT_MOUSE_BUTTON;
01447      event.data        = &input;
01448      event.data_length = sizeof(input);
01449      input.button      = 1;
01450      input.x           = rect.x;
01451      input.y           = rect.y;
01452      xine_event_send (xineStream, &event);
01453    }
01454 }
01455 
01456 
01457 void QXineWidget::PlayNextChapter() const
01458 {
01459 
01460   xine_event_t xev;
01461 
01462   xev.type = XINE_EVENT_INPUT_NEXT;
01463   xev.data = NULL;
01464   xev.data_length = 0;
01465 
01466   xine_event_send(xineStream, &xev);
01467 }  
01468 
01469 
01470 void QXineWidget::PlayPreviousChapter() const
01471 {
01472 
01473   xine_event_t xev;
01474 
01475   xev.type = XINE_EVENT_INPUT_PREVIOUS;
01476   xev.data = NULL;
01477   xev.data_length = 0;
01478 
01479   xine_event_send(xineStream, &xev);
01480 }  
01481 
01482 
01483 void QXineWidget::slotStopPlayback()
01484 {
01485   posTimer.stop();
01486 }
01487 
01488 
01489 void QXineWidget::SetDevice(const QString& device)
01490 {
01491   debugOut(QString("Set CD/VCD/DVD device to %1\n").arg(device));
01492   devicePath = device;
01493 
01494   xine_cfg_entry_t config;
01495 
01496   xine_config_lookup_entry (xineEngine, "input.cdda_device", &config);
01497   cachedCDPath = config.str_value;
01498   config.str_value = (char*)device.latin1();
01499   xine_config_update_entry (xineEngine, &config);
01500 
01501   xine_config_lookup_entry (xineEngine, "input.vcd_device", &config);
01502   cachedVCDPath = config.str_value;
01503   config.str_value = (char*)device.latin1();
01504   xine_config_update_entry (xineEngine, &config);
01505 
01506   xine_config_lookup_entry (xineEngine, "input.dvd_device", &config);
01507   cachedDVDPath = config.str_value;
01508   config.str_value = (char*)device.latin1();
01509   xine_config_update_entry (xineEngine, &config);
01510 }
01511 
01512 
01513 void QXineWidget::SetStreamSaveDir(const QString& dir)
01514 {
01515   xine_cfg_entry_t config;
01516 
01517   if (!xine_config_lookup_entry (xineEngine, "misc.save_dir", &config)) return; /* older xine-lib */
01518 
01519   debugOut(QString("Set misc.save_dir to: %1").arg(dir));
01520   config.str_value = (char*)dir.latin1();
01521   xine_config_update_entry (xineEngine, &config);
01522 }  
01523 
01524 
01525 const QString QXineWidget::GetStreamSaveDir()
01526 {
01527   xine_cfg_entry_t config;
01528 
01529   if (!xine_config_lookup_entry (xineEngine, "misc.save_dir", &config)) return QString::null; /* older xine-lib */
01530 
01531   return QString( config.str_value );
01532 }
01533 
01534 
01535 void QXineWidget::SetBroadcasterPort(const uint port)
01536 {
01537   debugOut(QString("Set broadcaster port to ").arg(port));
01538   xine_set_param(xineStream, XINE_PARAM_BROADCASTER_PORT, port);
01539 }  
01540 
01541 
01542 void QXineWidget::slotSpeedPause()
01543 {
01544   xine_set_param(xineStream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
01545   posTimer.stop();
01546   signalNewInfo("Pause.");
01547 }
01548 
01549 
01550 void QXineWidget::slotSpeedNormal()
01551 {
01552   xine_set_param(xineStream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
01553   posTimer.start(500);
01554   signalNewInfo(trackInfoRow);
01555 }
01556 
01557 
01558 QString QXineWidget::GetSupportedExtensions() const
01559 {  
01560   return xine_get_file_extensions( xineEngine );
01561 }
01562 
01563 
01564 void QXineWidget::slotSetAudioChannel(int ch)
01565 {
01566   xine_set_param(xineStream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, ch-1);
01567 }  
01568 
01569 
01570 void QXineWidget::slotSetSubtitleChannel(int ch)
01571 {
01572   xine_set_param(xineStream, XINE_PARAM_SPU_CHANNEL, ch-1);
01573 }
01574 
01575 
01576 void QXineWidget::slotSetFileSubtitles(QString newMRL)
01577 {
01578   int pos;
01579   int time;
01580   int length;
01581   
01582   QString oldMRL = currentMRL;
01583   
01584   if ( !xine_get_pos_length(xineStream, &pos, &time, &length) )
01585   {
01586     debugOut("No valid stream position information");
01587     return;
01588   }    
01589   
01590   if (xine_get_status(xineStream) == XINE_STATUS_PLAY)
01591     xine_stop(xineStream);
01592     
01593   posTimer.stop();
01594   
01595   if(!PlayMRL(newMRL, currentTitle, true))
01596      PlayMRL(oldMRL, currentTitle, true);
01597      
01598   slotChangePosition(pos);
01599 }
01600 
01601 
01602 void QXineWidget::slotTogglePlayMode()
01603 {
01604   switch (playMode)
01605  {
01606    case NORMAL_PLAY:
01607    {
01608      playMode = REPEAT_PLAY;
01609      break;
01610    }
01611    case REPEAT_PLAY:
01612    {
01613      playMode = PERCENT_PLAY;
01614      break;
01615    }
01616    case PERCENT_PLAY:
01617    {
01618      playMode = NORMAL_PLAY;
01619      break;
01620    }
01621  }
01622 }
01623 
01624 
01625 void QXineWidget::slotGetPosition()
01626 {
01627   if (!xineRunning) return;
01628 
01629   int pos;
01630   int time;
01631   int length;
01632   
01633   double perc;
01634 
01635   QString t;
01636   
01637   if ( !xine_get_pos_length(xineStream, &pos, &time, &length) )
01638   {
01639     debugOut("No valid stream position information");
01640     return;
01641   }  
01642   
01643   switch (playMode)
01644   { 
01645     case PERCENT_PLAY:
01646     {
01647       perc = pos/655,35;
01648       time = (int) (perc);
01649       if ( (time < 0) || (time > 100) )
01650       {
01651         emit signalNewPosition( pos , "  --%  " );
01652         return;
01653       }  
01654       t = t.setNum(time);
01655       t = QString(" %1%2 ").arg(t).arg("%");
01656       emit signalNewPosition( pos, t );
01657       break;
01658     }  
01659     case REPEAT_PLAY:
01660     {
01661       time = length - time;      
01662     }
01663     case NORMAL_PLAY:
01664     {
01665       if (time < 0)
01666       {
01667         emit signalNewPosition( pos , "-:--:--" );
01668         return;
01669       } 
01670       emit signalNewPosition( pos, msToTimeString(time) );
01671       break;
01672     }
01673   }
01674 }
01675 
01676 
01677 void QXineWidget::slotChangePosition(int pos)
01678 {
01679   if (!xineRunning) return;
01680 
01681   int pause = !xine_get_param(xineStream, XINE_PARAM_SPEED);
01682   if ( (xine_get_status(xineStream) == XINE_STATUS_PLAY) && (xine_get_stream_info(xineStream, XINE_STREAM_INFO_SEEKABLE)) )
01683   {
01684     posTimer.stop();
01685     xine_play(xineStream, pos, 0);
01686     posTimer.start(500,false);
01687   }
01688   
01689   if (pause)
01690     slotSpeedPause();
01691 }
01692 
01693 
01694 void QXineWidget::slotEject()
01695 {
01696   xine_eject(xineStream);
01697 }
01698 
01699 void QXineWidget::slotEnableAutoresize(bool enable)
01700 {
01701   autoresizeEnabled = enable;
01702   if (!autoresizeEnabled)
01703   {
01704     videoFrameHeight = 0;
01705     videoFrameWidth = 0;
01706   }  
01707 }
01708 
01709 
01710 void QXineWidget::slotToggleDeinterlace()
01711 {
01712   if (xine_get_param(xineStream, XINE_PARAM_VO_DEINTERLACE))
01713     xine_set_param(xineStream, XINE_PARAM_VO_DEINTERLACE, false);
01714    else
01715     xine_set_param(xineStream, XINE_PARAM_VO_DEINTERLACE, true);
01716 }
01717 
01718 
01719 void QXineWidget::slotAspectRatioAuto()
01720 {
01721   xine_set_param(xineStream, XINE_PARAM_VO_ASPECT_RATIO, XINE_VO_ASPECT_AUTO);
01722 }  
01723 
01724 
01725 void QXineWidget::slotAspectRatio4_3()
01726 {
01727   xine_set_param(xineStream, XINE_PARAM_VO_ASPECT_RATIO, XINE_VO_ASPECT_4_3);
01728 }
01729 
01730 
01731 void QXineWidget::slotAspectRatio16_9()
01732 {
01733   xine_set_param(xineStream, XINE_PARAM_VO_ASPECT_RATIO, XINE_VO_ASPECT_ANAMORPHIC);
01734 }
01735 
01736 
01737 void QXineWidget::slotAspectRatioSquare()
01738 {
01739   xine_set_param(xineStream, XINE_PARAM_VO_ASPECT_RATIO, XINE_VO_ASPECT_SQUARE);
01740 }
01741 
01742 
01743 void QXineWidget::slotZoomOut()
01744 {
01745   if ((currentZoom - 5) >= 100)
01746   {
01747     currentZoom -= 5;
01748     xine_set_param(xineStream, XINE_PARAM_VO_ZOOM_X, currentZoom);
01749     xine_set_param(xineStream, XINE_PARAM_VO_ZOOM_Y, currentZoom);
01750   }
01751 }
01752 
01753 
01754 void QXineWidget::slotZoomIn()
01755 {
01756   if ((currentZoom + 5) <= XINE_VO_ZOOM_MAX)
01757   {
01758     currentZoom += 5;
01759     xine_set_param(xineStream, XINE_PARAM_VO_ZOOM_X, currentZoom);
01760     xine_set_param(xineStream, XINE_PARAM_VO_ZOOM_Y, currentZoom);
01761   }
01762 }
01763 
01764 
01765 void QXineWidget::slotZoomOff()
01766 {
01767   xine_set_param(xineStream, XINE_PARAM_VO_ZOOM_X, 100);
01768   xine_set_param(xineStream, XINE_PARAM_VO_ZOOM_Y, 100);
01769   currentZoom = 100;
01770 }
01771 
01772 
01773 QString QXineWidget::GetStreamInfo()
01774 {
01775   QString streamInfo;
01776 
01777   streamInfo = streamInfo + "(" + xine_get_meta_info(xineStream, XINE_META_INFO_INPUT_PLUGIN) + ") ";
01778 
01779   if (xine_get_stream_info(xineStream, XINE_STREAM_INFO_HAS_VIDEO))
01780   {
01781      streamInfo.append(xine_get_meta_info(xineStream, XINE_META_INFO_VIDEOCODEC));
01782      streamInfo.append(" (");
01783      streamInfo.append( QString::number(xine_get_stream_info(xineStream, XINE_STREAM_INFO_VIDEO_WIDTH)) );
01784      streamInfo.append("x");
01785      streamInfo.append( QString::number(xine_get_stream_info(xineStream, XINE_STREAM_INFO_VIDEO_HEIGHT)) );
01786      streamInfo.append(") ");
01787   }
01788 
01789   if (xine_get_stream_info(xineStream, XINE_STREAM_INFO_HAS_AUDIO))
01790   {
01791      streamInfo.append(xine_get_meta_info(xineStream, XINE_META_INFO_AUDIOCODEC));
01792      streamInfo.append(" (");
01793      streamInfo.append( QString::number(xine_get_stream_info(xineStream, XINE_STREAM_INFO_AUDIO_BITRATE)/1000) );
01794      streamInfo.append("kb)");
01795   }
01796 
01797   return streamInfo;
01798 }
01799 
01800 
01801 QString QXineWidget::GetLengthInfo()
01802 {
01803   int pos, time, length;
01804 
01805   bool ok = xine_get_pos_length(xineStream, &pos, &time, &length);
01806 
01807   if ( (ok) && (length > 0) )
01808   {
01809     return msToTimeString(length);
01810   }
01811   
01812   return QString::null;
01813 }  
01814 
01815 
01816 void QXineWidget::slotEmitLengthInfo()
01817 {
01818   QString length = GetLengthInfo();
01819   if (!length.isNull())
01820   {
01821     lengthInfoTimer.stop();
01822     emit signalLengthInfo( length );
01823   }  
01824 }
01825 
01826 
01827 void QXineWidget::slotSetScreensaverTimeout( int ssTimeout )
01828 {
01829   screensaverTimeout = ssTimeout;
01830 
01831 #ifdef HAVE_XTEST
01832   if (screensaverTimeout > 0)
01833     screensaverTimer.start(screensaverTimeout* 60000); //min
01834    else
01835     screensaverTimer.stop();
01836 #endif    
01837 }
01838 
01839 
01840 int QXineWidget::GetScreensaverTimeout() const
01841 {
01842   return screensaverTimeout;
01843 }
01844 
01845 
01846 void QXineWidget::GlobalPosChanged()
01847 {
01848   QPoint g = mapToGlobal(QPoint(0,0));
01849   globX = g.x();
01850   globY = g.y();
01851 //  debugOut(QString("QXineWidget: x: %1 y: %2").arg(globX).arg(globY));
01852 }    
01853 
01854 
01855 void QXineWidget::slotFakeKeyEvent()
01856 {
01857 #ifdef HAVE_XTEST
01858 
01859 // debugOut("Fake key event...\n");
01860 
01861  if (haveXTest)
01862  {
01863    XTestFakeKeyEvent(x11Display(), xTestKeycode, true, CurrentTime);
01864    XTestFakeKeyEvent(x11Display(), xTestKeycode, false, CurrentTime);
01865    XSync(x11Display(), false);
01866  }  
01867 
01868 #endif 
01869 
01870 }
01871 
01872 
01873 const xine_t* const QXineWidget::GetXineEngine()const
01874 {
01875   return xineEngine;
01876 }
01877 
01878   
01879 /************ video settings ****************/
01880 
01881 void QXineWidget::GetVideoSettings(int& hue, int& sat, int& contrast, int& bright,
01882                                    int& audioAmp, int& avOffset, int& spuOffset) const
01883 {
01884   hue = xine_get_param(xineStream, XINE_PARAM_VO_HUE);
01885   sat = xine_get_param(xineStream, XINE_PARAM_VO_SATURATION);
01886   contrast = xine_get_param(xineStream, XINE_PARAM_VO_CONTRAST);
01887   bright = xine_get_param(xineStream, XINE_PARAM_VO_BRIGHTNESS);
01888 
01889   audioAmp = xine_get_param(xineStream, XINE_PARAM_AUDIO_AMP_LEVEL);
01890   avOffset = xine_get_param(xineStream, XINE_PARAM_AV_OFFSET);
01891   spuOffset = xine_get_param(xineStream, XINE_PARAM_SPU_OFFSET);
01892 }
01893 
01894 
01895 void QXineWidget::slotSetHue(int hue)
01896 {
01897   xine_set_param(xineStream, XINE_PARAM_VO_HUE, hue);
01898 }
01899   
01900 
01901 void QXineWidget::slotSetSaturation(int sat)
01902 {
01903   xine_set_param(xineStream, XINE_PARAM_VO_SATURATION, sat);
01904 }
01905   
01906 
01907 void QXineWidget::slotSetContrast(int contrast)
01908 {
01909   xine_set_param(xineStream, XINE_PARAM_VO_CONTRAST, contrast);
01910 }
01911   
01912 
01913 void QXineWidget::slotSetBrightness(int bright)
01914 {
01915   xine_set_param(xineStream, XINE_PARAM_VO_BRIGHTNESS, bright);
01916 }
01917   
01918 
01919 void QXineWidget::slotSetAudioAmp(int amp)
01920 {
01921   xine_set_param(xineStream, XINE_PARAM_AUDIO_AMP_LEVEL, amp);
01922 }
01923   
01924 
01925 void QXineWidget::slotSetAVOffset(int av)
01926 {
01927   xine_set_param(xineStream, XINE_PARAM_AV_OFFSET, av);
01928 }
01929   
01930 
01931 void QXineWidget::slotSetSpuOffset(int spu)
01932 {
01933   xine_set_param(xineStream, XINE_PARAM_SPU_OFFSET, spu);
01934 }
01935 
01936 
01937 
01938 /**************** equalizer *****************/
01939 
01940 void QXineWidget::slotSetEq30(int val)
01941 {
01942   xine_set_param(xineStream, XINE_PARAM_EQ_30HZ, -val);
01943 }
01944 
01945 
01946 void QXineWidget::slotSetEq60(int val)
01947 {
01948   xine_set_param(xineStream, XINE_PARAM_EQ_60HZ, -val);
01949 }
01950 
01951 
01952 void QXineWidget::slotSetEq125(int val)
01953 {
01954   xine_set_param(xineStream, XINE_PARAM_EQ_125HZ, -val);
01955 }
01956 
01957 
01958 void QXineWidget::slotSetEq250(int val)
01959 {
01960   xine_set_param(xineStream, XINE_PARAM_EQ_250HZ, -val);
01961 }
01962 
01963 
01964 void QXineWidget::slotSetEq500(int val)
01965 {
01966   xine_set_param(xineStream, XINE_PARAM_EQ_500HZ, -val);
01967 }
01968 
01969 
01970 void QXineWidget::slotSetEq1k(int val)
01971 {
01972   xine_set_param(xineStream, XINE_PARAM_EQ_1000HZ, -val);
01973 }
01974 
01975 
01976 void QXineWidget::slotSetEq2k(int val)
01977 {
01978   xine_set_param(xineStream, XINE_PARAM_EQ_2000HZ, -val);
01979 }
01980 
01981 
01982 void QXineWidget::slotSetEq4k(int val)
01983 {
01984   xine_set_param(xineStream, XINE_PARAM_EQ_4000HZ, -val);
01985 }
01986 
01987 
01988 void QXineWidget::slotSetEq8k(int val)
01989 {
01990   xine_set_param(xineStream, XINE_PARAM_EQ_8000HZ, -val);
01991 }
01992 
01993 
01994 void QXineWidget::slotSetEq16k(int val)
01995 {
01996   xine_set_param(xineStream, XINE_PARAM_EQ_16000HZ, -val);
01997 }
01998 
01999 /*************** dvd menus ******************/
02000 
02001 void QXineWidget::slotMenu1()
02002 {
02003   xine_event_t xev;
02004   xev.type = XINE_EVENT_INPUT_MENU1;
02005   xev.data = NULL;
02006   xev.data_length = 0;
02007   
02008   xine_event_send(xineStream, &xev);
02009 }
02010 
02011 
02012 void QXineWidget::slotMenu2()
02013 {
02014   xine_event_t xev;
02015   xev.type = XINE_EVENT_INPUT_MENU2;
02016   xev.data = NULL;
02017   xev.data_length = 0;
02018 
02019   xine_event_send(xineStream, &xev);
02020   
02021 }
02022 
02023 
02024 void QXineWidget::slotMenu3()
02025 {
02026   xine_event_t xev;
02027   xev.type = XINE_EVENT_INPUT_MENU3;
02028   xev.data = NULL;
02029   xev.data_length = 0;
02030 
02031   xine_event_send(xineStream, &xev);
02032 }
02033 
02034 
02035 void QXineWidget::slotMenu4()
02036 {
02037   xine_event_t xev;
02038   xev.type = XINE_EVENT_INPUT_MENU4;
02039   xev.data = NULL;
02040   xev.data_length = 0;
02041 
02042   xine_event_send(xineStream, &xev);
02043 }
02044 
02045 
02046 void QXineWidget::slotMenu5()
02047 {
02048   xine_event_t xev;
02049   xev.type = XINE_EVENT_INPUT_MENU5;
02050   xev.data = NULL;
02051   xev.data_length = 0;
02052 
02053   xine_event_send(xineStream, &xev);
02054 }
02055 
02056 
02057 void QXineWidget::slotMenu6()
02058 {
02059   xine_event_t xev;
02060   xev.type = XINE_EVENT_INPUT_MENU6;
02061   xev.data = NULL;
02062   xev.data_length = 0;
02063 
02064   xine_event_send(xineStream, &xev);
02065 }
02066 
02067 
02068 void QXineWidget::slotMenu7()
02069 {
02070   xine_event_t xev;
02071   xev.type = XINE_EVENT_INPUT_MENU7;
02072   xev.data = NULL;
02073   xev.data_length = 0;
02074 
02075   xine_event_send(xineStream, &xev);
02076 }
02077 
02078 
02079 void QXineWidget::keyPressEvent(QKeyEvent *e)
02080 {  
02081   if (keyboardGrabber() == this)
02082   {
02083     xine_event_t xev;
02084     xev.data = NULL;
02085     xev.data_length = 0;
02086 
02087     switch(e->key())
02088     {
02089       case Qt::Key_Up:
02090         xev.type = XINE_EVENT_INPUT_UP;
02091         break;
02092       case Qt::Key_Down:
02093         xev.type = XINE_EVENT_INPUT_DOWN;
02094         break;
02095       case Qt::Key_Left:
02096         xev.type = XINE_EVENT_INPUT_LEFT;
02097         break;
02098       case Qt::Key_Right:
02099         xev.type = XINE_EVENT_INPUT_RIGHT;
02100         break;
02101       case Qt::Key_Return:
02102         xev.type = XINE_EVENT_INPUT_SELECT;
02103         break;
02104       default:
02105         break;
02106     }
02107     xine_event_send(xineStream, &xev);
02108       
02109     e->accept();
02110     return;
02111   }
02112   e->ignore();
02113 }
02114 
02115 
02116 
02117 /******** mouse hideing at fullscreen ****/
02118 
02119 
02120 void QXineWidget::StartMouseHideTimer()
02121 {
02122   mouseHideTimer.start(5000);
02123 }
02124   
02125 
02126 void QXineWidget::StopMouseHideTimer()
02127 {
02128   mouseHideTimer.stop();
02129 }
02130   
02131 
02132 void QXineWidget::slotHideMouse()
02133 {
02134   if (cursor().shape() == Qt::ArrowCursor)
02135   {
02136     setCursor(QCursor(Qt::BlankCursor));
02137   }  
02138 }   
02139 
02140 
02141 /************************************************************
02142  *   Take a Screenshot                                      *
02143  ************************************************************/
02144 
02145 
02146 void QXineWidget::GetScreenshot(uchar*& rgb32BitData, int& videoWidth, int& videoHeight, double& scaleFactor) const
02147 {
02148 
02149   uint8_t   *yuv = NULL, *y = NULL, *u = NULL, *v =NULL;
02150   
02151   int        width, height, ratio, format;
02152   double     desired_ratio, image_ratio;
02153 
02154   if (!xine_get_current_frame (xineStream, &width, &height, &ratio, &format, NULL))
02155     return;
02156 
02157   yuv = new uint8_t[((width+8) * (height+1) * 2)];
02158   if (yuv == NULL)
02159     {
02160       errorOut("Not enough memory to make screenshot!");
02161       return;
02162     }  
02163 
02164   xine_get_current_frame (xineStream, &width, &height, &ratio, &format, yuv);
02165 
02166   videoWidth = width;
02167   videoHeight = height;
02168 
02169 /*
02170  * convert to yv12 if necessary
02171  */
02172 
02173   switch (format) {
02174   case XINE_IMGFMT_YUY2:
02175     {
02176       uint8_t *yuy2 = yuv;
02177 
02178       yuv = new uint8_t[(width * height * 2)];
02179       if (yuv == NULL)
02180       {
02181 //        errorOut("Not enough memory to make screenshot!");
02182         return;
02183       }  
02184       y = yuv;
02185       u = yuv + width * height;
02186       v = yuv + width * height * 5 / 4;
02187 
02188       yuy2Toyv12 (y, u, v, yuy2, width, height);
02189 
02190       delete [] yuy2;
02191     }
02192     break;
02193   case XINE_IMGFMT_YV12:
02194     y = yuv;
02195     u = yuv + width * height;
02196     v = yuv + width * height * 5 / 4;
02197 
02198     break;
02199   default:
02200     {
02201       warningOut(QString("Screenshot: Format %1 not supported!\n").arg((char*)&format));
02202       delete [] yuv;
02203       return;
02204     }  
02205   }
02206 
02207   /*
02208    * convert to rgb
02209    */
02210 
02211   rgb32BitData = yv12ToRgb (y, u, v, width, height);
02212 
02213 
02214   image_ratio = (double) width / (double) height;
02215 
02216 
02217   switch (ratio) {
02218   case XINE_VO_ASPECT_ANAMORPHIC:  /* anamorphic  */
02219 //  case XINE_VO_ASPECT_PAN_SCAN:  /* depreciated */
02220     desired_ratio = 16.0 /9.0;
02221     break;
02222   case XINE_VO_ASPECT_DVB:         /* 2.11:1 */
02223     desired_ratio = 2.11/1.0;
02224     break;
02225   case XINE_VO_ASPECT_SQUARE:      /* square pels */
02226 //  case XINE_VO_ASPECT_DONT_TOUCH:  /* depreciated */
02227     desired_ratio = image_ratio;
02228     break; 
02229   default:
02230     warningOut(QString("Screenshot: Unknown aspect ratio: %1 - using 4:3").arg(ratio));
02231   case XINE_VO_ASPECT_4_3:         /* 4:3   */
02232     desired_ratio = 4.0 / 3.0;
02233     break;
02234   }
02235 
02236   scaleFactor = desired_ratio / image_ratio;
02237 
02238   delete [] yuv;
02239 }
02240 
02241 
02242 
02243 
02244 
02245 
02246 
02247 
02248 
02249 
02250 
02251 
02252 
02253 

Generated on Thu Apr 22 05:12:29 2004 for QXineWidget by doxygen 1.3.5