/tags/release-0.5.2.1/player/kxinewidget.cpp
http://kmediafactory.googlecode.com/ · C++ · 3929 lines · 3129 code · 614 blank · 186 comment · 482 complexity · b529aab7b4f5caa1b90f7740683af989 MD5 · raw file
Large files are truncated click here to view the full file
- /***************************************************************************
- kxinewidget.cpp
- A KDE/QT API for the xine-lib. Define USE_QT_ONLY if you use QT only.
- -------------------
- begin : Fre Apr 18 2003
- revision : $Revision: 1.48 $
- last modified : $Date: 2005/08/22 19:36:46 $ by $Author: juergenk $
- copyright : (C) 2003-2005 by JĂrgen Kofler
- email : kaffeine@gmx.net
- ***************************************************************************/
- /***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
- #include <qapplication.h>
- #include <qwidget.h>
- #include <qstringlist.h>
- #include <qtimer.h>
- #include <qevent.h>
- #include <qthread.h>
- #include <qdir.h>
- #include <qcursor.h>
- #include <qimage.h>
- #include <qdatetime.h>
- #include <qtextcodec.h>
- #include <xine/xineutils.h>
- #include <math.h>
- #include <string.h>
- #include <stdlib.h>
- #include "kxinewidget.h"
- #ifdef HAVE_XINERAMA
- #include <X11/extensions/Xinerama.h>
- #endif
- #ifndef USE_QT_ONLY
- #include "kxinewidget.moc"
- #include <klocale.h>
- #include <kdebug.h>
- #endif
- #define TIMER_EVENT_PLAYBACK_FINISHED 100
- #define TIMER_EVENT_NEW_CHANNELS 101
- #define TIMER_EVENT_NEW_TITLE 102
- #define TIMER_EVENT_NEW_STATUS 103
- #define TIMER_EVENT_CHANGE_CURSOR 104
- #define TIMER_EVENT_NEW_MRL_REFERENCE 105
- #define TIMER_EVENT_NEW_XINE_MESSAGE 106
- #define TIMER_EVENT_NEW_XINE_ERROR 107
- #define TIMER_EVENT_FRAME_FORMAT_CHANGE 108
- #define TIMER_EVENT_NEW_VOLUME_LEVEL 109
- #define TIMER_EVENT_RESTART_PLAYBACK 200
- #define TIMER_EVENT_RESIZE_PARENT 300
- KXineWidget::KXineWidget(QWidget* parent, const char* name,
- const QString& pathToConfigFile, const QString& pathToLogoFile,
- const QString& audioDriver, const QString& videoDriver,
- bool startManual, bool verbose)
- : QWidget(parent,name), QThread(), m_startXineManual(startManual), m_xineReady(false),
- m_logoFile(pathToLogoFile), m_preferedAudio(audioDriver), m_preferedVideo(videoDriver), m_xineVerbose(verbose),
- m_xineDisplay(NULL), m_xineEngine(NULL), m_audioDriver(NULL), m_videoDriver(NULL), m_xineStream(NULL),
- m_eventQueue(NULL), m_osd(NULL), m_osdUnscaled(false), m_osdShow(false), m_osdSize(0), m_osdFont(NULL),
- m_audioChoices(NULL), m_audioInfo(NULL), m_videoChoices(NULL), m_videoInfo(NULL), m_mixerInfo(NULL),
- m_osdShowInfo(NULL),
- m_osdSizeOptions(NULL), m_osdSizeInfo(NULL), m_osdFontInfo(NULL),
- #ifndef USE_QT_ONLY
- m_videoFiltersEnabled(true), m_audioFiltersEnabled(true), m_deinterlaceFilter(NULL),
- m_deinterlaceEnabled(false),
- m_visualPlugin(NULL),
- #else
- m_xinePost(NULL), m_postAudioSource(NULL), m_postInput(NULL),
- #endif
- m_visualPluginName(QString::null), m_currentSpeed(Normal), m_softwareMixer(false), m_volumeGain(false),
- m_currentZoom(100), m_currentZoomX(100), m_currentZoomY(100), m_currentAudio(0), m_currentSub(0), m_savedPos(0), m_autoresizeEnabled(false)
- {
- setMinimumSize(QSize(20,20)); // set a size hint
- setPaletteBackgroundColor(QColor(0,0,0)); //black
- /* dvb */
- TimeShiftFilename = "";
- dvbHaveVideo = 0;
- dvbOSD = 0;
- dvbColor[0] = 0;
- connect( &dvbOSDHideTimer, SIGNAL(timeout()), this, SLOT(dvbHideOSD()) );
- if (pathToConfigFile.isNull())
- {
- debugOut("Using default config file ~/.xine/config");
- m_configFilePath = QDir::homeDirPath();
- m_configFilePath.append("/.xine/config");
- }
- else
- m_configFilePath = pathToConfigFile;
- if (!m_logoFile.isNull())
- appendToQueue(m_logoFile);
- #ifndef USE_QT_ONLY
- m_videoFilterList.setAutoDelete(true); /*** delete post plugin on removing from list ***/
- m_audioFilterList.setAutoDelete(true); /*** delete post plugin on removing from list ***/
- #endif
- connect(&m_posTimer, SIGNAL(timeout()), this, SLOT(slotSendPosition()));
- connect(&m_lengthInfoTimer, SIGNAL(timeout()), this, SLOT(slotEmitLengthInfo()));
- connect(&m_mouseHideTimer, SIGNAL(timeout()), this, SLOT(slotHideMouse()));
- connect(&m_osdTimer, SIGNAL(timeout()), this, SLOT(slotOSDHide()));
- connect(&m_recentMessagesTimer, SIGNAL(timeout()), this, SLOT(slotNoRecentMessage()));
- setUpdatesEnabled(false);
- setMouseTracking(true);
- }
- KXineWidget::~KXineWidget()
- {
- /* "careful" shutdown, maybe xine initialization was not successful */
- m_xineReady = false;
- /* stop all timers */
- m_posTimer.stop();
- m_mouseHideTimer.stop();
- #ifndef USE_QT_ONLY
- slotRemoveAllAudioFilters();
- slotRemoveAllVideoFilters();
- #endif
- if (m_osd)
- xine_osd_free(m_osd);
- if (m_xineStream)
- xine_close(m_xineStream);
- if (running())
- {
- XEvent ev;
- ev.type = Expose;
- ev.xexpose.display = m_xineDisplay;
- ev.xexpose.window = winId();
- ev.xexpose.x = x();
- ev.xexpose.y = y();
- ev.xexpose.width = width();
- ev.xexpose.height = height();
- ev.xexpose.count = 0;
- XSendEvent( x11Display(), winId(), False, ExposureMask, &ev ); /* send a fake expose event */
- XFlush(x11Display());
- if( !wait(1000) ) /* wait a second for thread exiting */
- {
- warningOut("XEvent thread don't exit. Terminating it...");
- terminate();
- }
- }
- debugOut("Shut down xine engine");
- #ifndef USE_QT_ONLY
- if (m_deinterlaceFilter)
- {
- debugOut("Unwire video filters");
- unwireVideoFilters();
- delete m_deinterlaceFilter;
- m_deinterlaceFilter = NULL;
- }
- if (m_visualPlugin)
- {
- debugOut("Unwire audio filters");
- unwireAudioFilters();
- debugOut(QString("Dispose visual plugin: %1").arg(m_visualPluginName ));
- delete m_visualPlugin;
- m_visualPlugin = NULL;
- }
- #else
- if (m_xinePost)
- {
- debugOut(QString("Dispose visual plugin: %1").arg(m_visualPluginName));
- m_postAudioSource = xine_get_audio_source(m_xineStream);
- xine_post_wire_audio_port(m_postAudioSource, m_audioDriver);
- xine_post_dispose(m_xineEngine, m_xinePost);
- }
- #endif
- if (m_eventQueue)
- {
- debugOut("Dispose event queue");
- xine_event_dispose_queue(m_eventQueue);
- }
- if (m_xineStream)
- {
- debugOut("Dispose stream");
- xine_dispose(m_xineStream);
- }
- if (m_audioDriver)
- {
- debugOut("Close audio driver");
- xine_close_audio_driver(m_xineEngine, m_audioDriver);
- }
- if (m_videoDriver)
- {
- debugOut("Close video driver");
- xine_close_video_driver(m_xineEngine, m_videoDriver);
- }
- if (m_xineEngine)
- {
- saveXineConfig();
- debugOut("Close xine engine");
- xine_exit(m_xineEngine);
- }
- m_xineEngine = NULL;
- /* free xine config strings */
- if (m_osdShowInfo) free(m_osdShowInfo);
- if (m_osdFontInfo) free(m_osdFontInfo);
- if (m_osdFont) free(m_osdFont);
- if (m_osdSizeInfo) free(m_osdSizeInfo);
- if (m_osdSizeOptions)
- {
- int i=0;
- while (m_osdSizeOptions[i])
- {
- free(m_osdSizeOptions[i]);
- i++;
- }
- delete [] m_osdSizeOptions;
- }
- if (m_mixerInfo) free(m_mixerInfo);
- if (m_videoInfo) free(m_videoInfo);
- if (m_videoChoices)
- {
- int i=0;
- while (m_videoChoices[i])
- {
- free(m_videoChoices[i]);
- i++;
- }
- delete [] m_videoChoices;
- }
- if (m_audioInfo) free(m_audioInfo);
- if (m_audioChoices)
- {
- int i=0;
- while (m_audioChoices[i])
- {
- free(m_audioChoices[i]);
- i++;
- }
- delete [] m_audioChoices;
- }
- if (m_xineDisplay)
- {
- debugOut("Close xine display");
- XCloseDisplay(m_xineDisplay); /* close xine display */
- }
- m_xineDisplay = NULL;
- debugOut("xine closed");
- }
- void KXineWidget::saveXineConfig()
- {
- debugOut("Set CD/VCD/DVD path back");
- xine_cfg_entry_t config;
- if (!m_cachedCDPath.isNull())
- {
- xine_config_lookup_entry (m_xineEngine, "input.cdda_device", &config);
- config.str_value = (char*)m_cachedCDPath.latin1();
- xine_config_update_entry (m_xineEngine, &config);
- }
- if (!m_cachedVCDPath.isNull())
- {
- xine_config_lookup_entry (m_xineEngine, "input.vcd_device", &config);
- config.str_value = (char*)m_cachedVCDPath.latin1();
- xine_config_update_entry (m_xineEngine, &config);
- }
- if (!m_cachedDVDPath.isNull())
- {
- xine_config_lookup_entry (m_xineEngine, "input.dvd_device", &config);
- config.str_value = (char*)m_cachedDVDPath.latin1();
- xine_config_update_entry (m_xineEngine, &config);
- }
- debugOut(QString("Save xine config to: %1").arg(m_configFilePath));
- xine_config_save(m_xineEngine, m_configFilePath.ascii());
- }
- /***************************************************
- * CALLBACKS
- ***************************************************/
- void KXineWidget::destSizeCallback(void* p, int /*video_width*/, int /*video_height*/, double /*video_aspect*/,
- int* dest_width, int* dest_height, double* dest_aspect)
- {
- if (p == NULL) return;
- KXineWidget* vw = (KXineWidget*) p;
- *dest_width = vw->width();
- *dest_height = vw->height();
- *dest_aspect = vw->m_displayRatio;
- }
- void KXineWidget::frameOutputCallback(void* p, int video_width, int video_height, double video_aspect,
- int* dest_x, int* dest_y, int* dest_width, int* dest_height,
- double* dest_aspect, int* win_x, int* win_y)
- {
- if (p == NULL) return;
- KXineWidget* vw = (KXineWidget*) p;
- *dest_x = 0;
- *dest_y = 0 ;
- *dest_width = vw->width();
- *dest_height = vw->height();
- *win_x = vw->m_globalX;
- *win_y = vw->m_globalY;
- *dest_aspect = vw->m_displayRatio;
- /* give false aspect for audio visualization*/
- if ( !vw->hasVideo() ) {
- *dest_aspect = (video_width*video_aspect)/((vw->width()*video_height/vw->height())-0.5);
- }
- /* correct size with video aspect */
- if (video_aspect >= vw->m_displayRatio)
- video_width = (int) ( (double) (video_width * video_aspect / vw->m_displayRatio + 0.5) );
- else
- video_height = (int) ( (double) (video_height * vw->m_displayRatio / video_aspect) + 0.5);
- /* frame size changed */
- if ( (video_width != vw->m_videoFrameWidth) || (video_height != vw->m_videoFrameHeight) )
- {
- debugOut(QString("New video frame size: %1x%2 - aspect ratio: %3").arg(video_width).arg(video_height).arg(video_aspect));
- vw->m_videoFrameWidth = video_width;
- vw->m_videoFrameHeight = video_height;
- vw->m_videoAspect = video_aspect;
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_FRAME_FORMAT_CHANGE));
- /* auto-resize parent widget */
- if ((vw->m_autoresizeEnabled) && (vw->parentWidget()) && (vw->m_posTimer.isActive()) && (!vw->parentWidget()->isFullScreen())
- && (video_width > 0) && (video_height > 0))
- {
- vw->m_newParentSize = vw->parentWidget()->size() - QSize((vw->width() - video_width), vw->height() - video_height);
- debugOut(QString("Resize video window to: %1x%2").arg(vw->m_newParentSize.width()).arg(vw->m_newParentSize.height()));
- /* we should not do a resize() inside a xine thread,
- but post an event to the main thread */
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_RESIZE_PARENT));
- }
- }
- }
- /*
- * XINE EVENT THREAD
- * only the QT event thread should do GUI operations,
- * we use QApplication::postEvent() and a reimplementation of QObject::timerEvent() to
- * make sure all critical jobs are done within the QT main thread context
- *
- * for more information see http://doc.trolltech.com/3.1/threads.html
- */
- void KXineWidget::xineEventListener(void *p, const xine_event_t* xineEvent)
- {
- if (p == NULL) return;
- KXineWidget* vw = (KXineWidget*) p;
- switch (xineEvent->type)
- {
- case XINE_EVENT_UI_PLAYBACK_FINISHED:
- {
- debugOut("xine event: playback finished");
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_PLAYBACK_FINISHED ));
- break;
- }
- case XINE_EVENT_UI_CHANNELS_CHANGED: /* new channel informations */
- {
- debugOut("xine event: channels changed");
- int i,j,channels;
- char* lang = new char[128];
- QString num;
- vw->m_audioCh.clear();
- vw->m_audioCh.append(i18n("auto"));
- vw->m_subCh.clear();
- vw->m_subCh.append(i18n("off"));
- /*** get audio channels ***/
- channels = QMAX(10, xine_get_stream_info(vw->m_xineStream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL));
- for(i = 0; i < channels; i++)
- {
- if (xine_get_audio_lang(vw->m_xineStream, i, lang))
- vw->m_audioCh << lang;
- else
- vw->m_audioCh << i18n("Ch ") + num.setNum(i+1);
- }
- /*** get subtitle channels ***/
- channels = QMAX(10, xine_get_stream_info(vw->m_xineStream, XINE_STREAM_INFO_MAX_SPU_CHANNEL));
- for(j = 0; j < channels; j++)
- {
- if (xine_get_spu_lang(vw->m_xineStream, j, lang))
- vw->m_subCh << lang;
- else
- vw->m_subCh << i18n("Ch ") + num.setNum(j+1);
- }
- delete [] lang;
- vw->m_currentAudio = xine_get_param(vw->m_xineStream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL) + 1;
- vw->m_currentSub = xine_get_param(vw->m_xineStream, XINE_PARAM_SPU_CHANNEL) + 1;
- if (vw->m_currentAudio > (i-1))
- {
- vw->slotSetAudioChannel(0);
- vw->m_currentAudio = -1;
- }
- if (vw->m_currentSub > (j-1))
- {
- vw->slotSetSubtitleChannel(0);
- vw->m_currentSub = -1;
- }
- //check if stream is seekable
- vw->m_trackIsSeekable = (bool)xine_get_stream_info(vw->m_xineStream, XINE_STREAM_INFO_SEEKABLE);
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_CHANNELS));
- break;
- }
- case XINE_EVENT_UI_SET_TITLE: /* set new title */
- {
- debugOut("xine event: ui set title");
- xine_ui_data_t* xd = (xine_ui_data_t*)xineEvent->data;
- vw->m_trackTitle = QString::fromLocal8Bit( (char*)xd->str );
- vw->m_lengthInfoTries = 0;
- vw->m_lengthInfoTimer.start(1000); /* May be new Length on Changing DVD/VCD titles */
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_TITLE));
- break;
- }
- case XINE_EVENT_PROGRESS:
- {
- debugOut("xine event: progress info");
- xine_progress_data_t* pd = (xine_progress_data_t*)xineEvent->data;
- vw->m_statusString = QString::fromLocal8Bit(pd->description) + " " + QString::number(pd->percent) + "%";
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_STATUS));
- break;
- }
- case XINE_EVENT_DROPPED_FRAMES:
- {
- debugOut("xine event: dropped frames");
- xine_dropped_frames_t* dropped = (xine_dropped_frames_t*)xineEvent->data;
- warningOut(QString("Skipped frames: %1 - discarded frames: %2").arg(dropped->skipped_frames/10).arg(dropped->discarded_frames/10));
- break;
- }
- case XINE_EVENT_SPU_BUTTON:
- {
- debugOut("xine event: spu button");
- xine_spu_button_t* button = (xine_spu_button_t*)xineEvent->data;
- if (button->direction == 1) /* enter a button */
- {
- debugOut("DVD Menu: Mouse entered button");
- vw->m_DVDButtonEntered = true;
- }
- else
- {
- debugOut("DVD Menu: Mouse leaved button");
- vw->m_DVDButtonEntered = false;
- }
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_CHANGE_CURSOR));
- break;
- }
- case XINE_EVENT_UI_NUM_BUTTONS:
- {
- debugOut("xine event: ui num buttons");
- break;
- }
- case XINE_EVENT_MRL_REFERENCE:
- {
- debugOut("xine event: mrl reference");
- xine_mrl_reference_data_t* mrldata = (xine_mrl_reference_data_t*)xineEvent->data;
- vw->m_newMRLReference = mrldata->mrl;
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_MRL_REFERENCE));
- break;
- }
- case XINE_EVENT_FRAME_FORMAT_CHANGE:
- {
- // debugOut("xine event: frame format change");
- // QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_FRAME_FORMAT_CHANGE));
- break;
- }
- case XINE_EVENT_AUDIO_LEVEL:
- {
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_VOLUME_LEVEL));
- break;
- }
- case XINE_EVENT_UI_MESSAGE:
- {
- debugOut("xine event: xine message");
- xine_ui_message_data_t *data = (xine_ui_message_data_t *)xineEvent->data;
- QString message;
- switch(data->type)
- {
- case XINE_MSG_NO_ERROR:
- {
- /* copy strings, and replace '\0' separators by '\n' */
- char* s = data->messages;
- char* d = new char[2000];
- while(s && (*s != '\0') && ((*s + 1) != '\0'))
- {
- switch(*s)
- {
- case '\0':
- {
- *d = '\n';
- break;
- }
- default:
- {
- *d = *s;
- break;
- }
- }
- s++;
- d++;
- }
- *++d = '\0';
- message = d;
- delete [] d;
- break;
- }
- case XINE_MSG_GENERAL_WARNING:
- {
- message = i18n("General Warning: \n");
- if(data->explanation)
- message = message + ((char *) data + data->explanation) + " " + ((char *) data + data->parameters);
- else
- message = message + i18n("No Informations available.");
- break;
- }
- case XINE_MSG_SECURITY:
- {
- message = i18n("Security Warning: \n");
- if(data->explanation)
- message = message + ((char *) data + data->explanation) + " " + ((char *) data + data->parameters);
- break;
- }
- case XINE_MSG_UNKNOWN_HOST:
- {
- message = i18n("The host you're trying to connect is unknown.\nCheck the validity of the specified hostname. ");
- if(data->explanation)
- message = message + "(" + ((char *) data + data->parameters) + ")";
- break;
- }
- case XINE_MSG_UNKNOWN_DEVICE:
- {
- message = i18n("The device name you specified seems invalid. ");
- if(data->explanation)
- message = message + "(" + ((char *) data + data->parameters) + ")";
- break;
- }
- case XINE_MSG_NETWORK_UNREACHABLE:
- {
- message = i18n("The network looks unreachable.\nCheck your network setup and the server name. ");
- if(data->explanation)
- message = message + "(" + ((char *) data + data->parameters) + ")";
- break;
- }
- case XINE_MSG_AUDIO_OUT_UNAVAILABLE:
- {
- message = i18n("Audio output unavailable. Device is busy. ");
- if(data->explanation)
- message = message + "(" + ((char *) data + data->parameters) + ")";
- break;
- }
- case XINE_MSG_CONNECTION_REFUSED:
- {
- message = i18n("The connection was refused.\nCheck the host name. ");
- if(data->explanation)
- message = message + "(" + ((char *) data + data->parameters) + ")";
- break;
- }
- case XINE_MSG_FILE_NOT_FOUND:
- {
- message = i18n("The specified file or url was not found. Please check it. ");
- if(data->explanation)
- message = message + "(" + QString::fromLocal8Bit((char *) data + data->parameters) + ")";
- break;
- }
- case XINE_MSG_PERMISSION_ERROR:
- {
- message = i18n("Permission to this source was denied. ");
- // if(data->explanation)
- message = message + "(" + ((char *) data + data->parameters) + ")";
- break;
- }
- case XINE_MSG_READ_ERROR:
- {
- message = 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). ");
- if(data->explanation)
- message = message + "(" + ((char *) data + data->parameters) + ")";
- break;
- }
- case XINE_MSG_LIBRARY_LOAD_ERROR:
- {
- message = i18n("A problem occur while loading a library or a decoder: ");
- if(data->explanation)
- message = message + ((char *) data + data->parameters);
- break;
- }
- case XINE_MSG_ENCRYPTED_SOURCE:
- {
- message = i18n("The source seems encrypted, and can't be read. ");
- if (vw->m_trackURL.contains("dvd:/"))
- message = message + 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. ");
- if(data->explanation)
- message = message + "(" + ((char *) data + data->parameters) + ")";
- break;
- }
- default:
- {
- message = i18n("Unknown error: \n");
- if(data->explanation)
- message = message + ((char *) data + data->explanation) + " " + ((char *) data + data->parameters);
- break;
- }
- }
- vw->m_xineMessage = message;
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_XINE_MESSAGE));
- break;
- }
- default:
- {
- //debugOut("xine event: unhandled type ");
- break;
- }
- }
- }
- void KXineWidget::timerEvent( QTimerEvent* tevent )
- {
- switch ( tevent->timerId() )
- {
- case TIMER_EVENT_PLAYBACK_FINISHED:
- {
- #ifdef XINE_PARAM_GAPLESS_SWITCH
- if ( xine_check_version(1,1,1) )
- xine_set_param( m_xineStream, XINE_PARAM_GAPLESS_SWITCH, 1);
- #endif
- if ( !TimeShiftFilename.isEmpty() )
- {
- QTimer::singleShot(0, this, SLOT(slotPlayTimeShift()));
- break;
- }
- if ( m_trackURL=="DVB" || m_trackURL.contains(".kaxtv.ts") )
- break;
- if (isQueueEmpty())
- {
- if (m_trackURL != m_logoFile)
- emit signalPlaybackFinished();
- else
- xine_stop(m_xineStream);
- }
- else
- QTimer::singleShot(0, this, SLOT(slotPlay()));
- break;
- }
- case TIMER_EVENT_NEW_CHANNELS:
- {
- emit signalNewChannels(m_audioCh, m_subCh, m_currentAudio, m_currentSub);
- break;
- }
- case TIMER_EVENT_NEW_TITLE:
- {
- emit signalTitleChanged();
- break;
- }
- case TIMER_EVENT_FRAME_FORMAT_CHANGE:
- {
- if ((m_trackHasVideo) && (m_trackURL != m_logoFile))
- emit signalVideoSizeChanged();
- break;
- }
- case TIMER_EVENT_NEW_STATUS:
- {
- emit signalXineStatus(m_statusString);
- break;
- }
- case TIMER_EVENT_CHANGE_CURSOR:
- {
- if (m_DVDButtonEntered)
- setCursor(QCursor(Qt::PointingHandCursor));
- else
- setCursor(QCursor(Qt::ArrowCursor));
- break;
- }
- case TIMER_EVENT_NEW_MRL_REFERENCE:
- {
- m_queue.prepend(m_newMRLReference );
- break;
- }
- case TIMER_EVENT_NEW_VOLUME_LEVEL:
- {
- emit signalSyncVolume();
- break;
- }
- case TIMER_EVENT_NEW_XINE_MESSAGE:
- {
- if (!m_recentMessagesTimer.isActive())
- {
- m_recentMessagesTimer.start(1500);
- emit signalXineMessage(m_xineMessage);
- }
- else
- {
- //restart
- warningOut(QString("Message: '%1' was blocked!").arg(m_xineMessage));
- m_recentMessagesTimer.start(1500);
- }
- break;
- }
- case TIMER_EVENT_NEW_XINE_ERROR:
- {
- emit signalXineError(m_xineError);
- break;
- }
- case TIMER_EVENT_RESTART_PLAYBACK:
- {
- appendToQueue(m_trackURL);
- slotPlay();
- break;
- }
- case TIMER_EVENT_RESIZE_PARENT:
- {
- parentWidget()->resize(m_newParentSize);
- break;
- }
- default: break;
- }
- }
- void KXineWidget::slotNoRecentMessage()
- {
- m_recentMessagesTimer.stop();
- }
- /******************* new video driver *********************/
- void KXineWidget::videoDriverChangedCallback(void* p, xine_cfg_entry_t* entry)
- {
- if (p == NULL) return;
- if (entry == NULL) return;
- #ifndef USE_QT_ONLY
- KXineWidget* vw = (KXineWidget*) p;
- xine_video_port_t* oldVideoDriver = vw->m_videoDriver;
- xine_video_port_t* noneVideoDriver;
- int pos, time, length;
- debugOut(QString("New video driver: %1").arg(entry->enum_values[entry->num_value]));
- if (vw->m_osd)
- {
- xine_osd_free(vw->m_osd);
- vw->m_osd = NULL;
- }
- noneVideoDriver = xine_open_video_driver(vw->m_xineEngine, "none",
- XINE_VISUAL_TYPE_NONE, NULL);
- if (!noneVideoDriver)
- {
- errorOut("Can't init Video Driver 'none', operation aborted.");
- return;
- }
- bool playing = false;
- if (vw->isPlaying())
- {
- playing = true;
- vw->m_savedPos = 0;
- int t = 0, ret = 0;
- while(((ret = xine_get_pos_length(vw->m_xineStream, &pos, &time, &length)) == 0) && (++t < 5))
- xine_usec_sleep(100000);
- if ( ret != 0 )
- vw->m_savedPos = pos;
- }
- xine_close(vw->m_xineStream);
- /* wire filters to "none" driver so the old one can be safely disposed */
- vw->m_videoDriver = noneVideoDriver;
- vw->unwireVideoFilters();
- vw->wireVideoFilters();
- vw->unwireAudioFilters();
- if (vw->m_visualPlugin)
- {
- debugOut(QString("Dispose visual plugin: %1").arg(vw->m_visualPluginName));
- delete vw->m_visualPlugin;
- vw->m_visualPlugin = NULL;
- }
- xine_event_dispose_queue(vw->m_eventQueue);
- xine_dispose(vw->m_xineStream);
- xine_close_video_driver(vw->m_xineEngine, oldVideoDriver);
- vw->m_videoDriver = xine_open_video_driver(vw->m_xineEngine,
- entry->enum_values[entry->num_value], XINE_VISUAL_TYPE_X11,
- (void *) &(vw->m_x11Visual));
- if (!vw->m_videoDriver)
- {
- vw->m_xineError = i18n("Error: Can't init new Video Driver %1 - using %2!").arg(entry->enum_values[entry->num_value]).arg(vw->m_videoDriverName);
- QApplication::postEvent(vw, new QTimerEvent( TIMER_EVENT_NEW_XINE_ERROR));
- playing = false;
- vw->m_videoDriver = xine_open_video_driver(vw->m_xineEngine,
- vw->m_videoDriverName.ascii(), XINE_VISUAL_TYPE_X11,
- (void *) &(vw->m_x11Visual));
- }
- else
- {
- vw->m_videoDriverName = entry->enum_values[entry->num_value];
- vw->m_statusString = i18n("Using Video Driver: ") + vw->m_videoDriverName;
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_STATUS));
- }
- vw->m_xineStream = xine_stream_new(vw->m_xineEngine, vw->m_audioDriver, vw->m_videoDriver);
- vw->m_eventQueue = xine_event_new_queue (vw->m_xineStream);
- xine_event_create_listener_thread(vw->m_eventQueue, &KXineWidget::xineEventListener, p);
- /* rewire filters to the new driver */
- vw->unwireVideoFilters();
- vw->wireVideoFilters();
- /* "none" can now be disposed too */
- xine_close_video_driver(vw->m_xineEngine, noneVideoDriver);
- vw->initOSD();
- if (playing)
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_RESTART_PLAYBACK));
- #endif
- }
- /*********************** new audio driver *************************/
- void KXineWidget::audioDriverChangedCallback(void* p, xine_cfg_entry_t* entry)
- {
- if (p == NULL) return;
- if (entry == NULL) return;
- #ifndef USE_QT_ONLY
- KXineWidget* vw = (KXineWidget*) p;
- int pos, time, length;
- debugOut(QString("New audio driver: %1").arg(entry->enum_values[entry->num_value]));
- if (vw->m_osd)
- {
- xine_osd_free(vw->m_osd);
- vw->m_osd = NULL;
- }
- vw->unwireVideoFilters();
- bool playing = false;
- if (vw->isPlaying())
- {
- playing = true;
- vw->m_savedPos = 0;
- int t = 0, ret = 0;
- while(((ret = xine_get_pos_length(vw->m_xineStream, &pos, &time, &length)) == 0) && (++t < 5))
- xine_usec_sleep(100000);
- if ( ret != 0 )
- vw->m_savedPos = pos;
- }
- xine_close(vw->m_xineStream);
- vw->unwireAudioFilters();
- if (vw->m_visualPlugin)
- {
- debugOut(QString("Dispose visual plugin: %1").arg(vw->m_visualPluginName));
- delete vw->m_visualPlugin;
- vw->m_visualPlugin = NULL;
- }
- xine_event_dispose_queue(vw->m_eventQueue);
- xine_dispose(vw->m_xineStream);
- xine_close_audio_driver(vw->m_xineEngine, vw->m_audioDriver);
- vw->m_audioDriver = NULL;
- vw->m_audioDriver = xine_open_audio_driver(vw->m_xineEngine, entry->enum_values[entry->num_value], NULL);
- if (!vw->m_audioDriver)
- {
- vw->m_xineError = i18n("Error: Can't init new Audio Driver %1 - using %2!").arg(entry->enum_values[entry->num_value]).arg(vw->m_audioDriverName);
- QApplication::postEvent(vw, new QTimerEvent( TIMER_EVENT_NEW_XINE_ERROR));
- playing = false;
- vw->m_audioDriver = xine_open_audio_driver(vw->m_xineEngine, vw->m_audioDriverName.ascii(), NULL);
- }
- else
- {
- vw->m_audioDriverName = entry->enum_values[entry->num_value];
- vw->m_statusString = i18n("Using Audio Driver: ") + vw->m_audioDriverName;
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_STATUS));
- }
- vw->m_xineStream = xine_stream_new(vw->m_xineEngine, vw->m_audioDriver, vw->m_videoDriver);
- vw->m_eventQueue = xine_event_new_queue (vw->m_xineStream);
- xine_event_create_listener_thread(vw->m_eventQueue, &KXineWidget::xineEventListener, p);
- vw->wireVideoFilters();
- vw->initOSD();
- if (playing)
- QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_RESTART_PLAYBACK));
- #endif
- }
- /******** change audio mixer method ****************/
- void KXineWidget::audioMixerMethodChangedCallback(void* p, xine_cfg_entry_t* entry)
- {
- if (p == NULL) return;
- KXineWidget* vw = (KXineWidget*) p;
- vw->m_softwareMixer = (bool)entry->num_value;
- }
- /******** Callback for OSD configuration ****************/
- void KXineWidget::showOSDMessagesChangedCallback(void* p, xine_cfg_entry_t* entry)
- {
- if (p == NULL) return;
- KXineWidget* vw = (KXineWidget*) p;
- if (vw->m_osd)
- vw->m_osdShow = (bool)entry->num_value;
- }
- void KXineWidget::sizeForOSDMessagesChangedCallback(void* p, xine_cfg_entry_t* entry)
- {
- if (p == NULL) return;
- KXineWidget* vw = (KXineWidget*) p;
- const int fontsizetable[] = { 16,20,24,32,48,64 };
- if (entry->num_value >= 6)
- {
- debugOut("Font size not defined: Shouldn't have happened");
- return;
- }
- if (vw->m_osd)
- {
- vw->m_osdSize = entry->num_value;
- xine_osd_set_font(vw->m_osd, vw->m_osdFont, fontsizetable[vw->m_osdSize]);
- }
- }
- void KXineWidget::fontForOSDMessagesChangedCallback(void* p, xine_cfg_entry_t* entry)
- {
- if (p == NULL) return;
- KXineWidget* vw = (KXineWidget*) p;
- const int fontsizetable[] = { 16,20,24,32,48,64 };
- if (vw->m_osd)
- if (entry->str_value)
- {
- free(vw->m_osdFont);
- vw->m_osdFont = strdup(entry->str_value);
- if (!xine_osd_set_font(vw->m_osd, vw->m_osdFont, fontsizetable[vw->m_osdSize]))
- {
- free(vw->m_osdFont);
- vw->m_osdFont = strdup("sans");
- if (!xine_osd_set_font(vw->m_osd, vw->m_osdFont, fontsizetable[vw->m_osdSize]))
- warningOut("Default SANS font not found: shouldn't have happened.");
- }
- }
- }
- /**********************************************
- * EVENT LOOP
- *********************************************/
- void KXineWidget::run()
- {
- debugOut("Start event loop...");
- XEvent event;
- while (isXineReady())
- {
- XNextEvent (m_xineDisplay, &event);
- XLockDisplay(m_xineDisplay);
- if (event.type == Expose)
- {
- if (event.xexpose.count == 0)
- {
- xine_port_send_gui_data(m_videoDriver, XINE_GUI_SEND_EXPOSE_EVENT, &event);
- }
- }
- XUnlockDisplay(m_xineDisplay);
- }
- debugOut("Exiting event loop...");
- }
- /**********************************************************
- * INIT XINE ENGINE
- *********************************************************/
- void KXineWidget::polish()
- {
- if ((!m_startXineManual) && (!isXineReady())) /* start xine engine automatically? */
- {
- initXine();
- }
- }
- bool KXineWidget::initXine()
- {
- if (isXineReady())
- return true;
- emit signalXineStatus(i18n("Init xine..."));
- globalPosChanged(); /* get global pos of the window */
- /**** INIT XINE DISPLAY ****/
- XInitThreads();
- m_xineDisplay = XOpenDisplay( getenv("DISPLAY") );
- if (!m_xineDisplay)
- {
- emit signalXineFatal(i18n("Failed to connect to X-Server!"));
- return false;
- }
- m_xineScreen = DefaultScreen(m_xineDisplay);
- m_xineWindow = winId();
- XLockDisplay(m_xineDisplay);
- XSelectInput(m_xineDisplay, m_xineWindow, ExposureMask);
- /* determine display aspect ratio */
- double resHor = DisplayWidth(m_xineDisplay, m_xineScreen)*1000 / DisplayWidthMM(m_xineDisplay, m_xineScreen);
- double resVer = DisplayHeight(m_xineDisplay, m_xineScreen)*1000 / DisplayHeightMM(m_xineDisplay, m_xineScreen);
- m_displayRatio = resVer / resHor;
- #ifdef HAVE_XINERAMA
- int dummy_event, dummy_error;
- if (XineramaQueryExtension(m_xineDisplay, &dummy_event, &dummy_error))
- {
- int count = 1;
- debugOut("Xinerama extension present");
- XineramaQueryScreens(m_xineDisplay, &count);
- debugOut(QString("%1 screens detected").arg(count));
- if (count > 1)
- /* multihead -> assuming square pixels */
- m_displayRatio = 1.0;
- }
- #endif
- debugOut(QString("Display aspect ratio (v/h): %1").arg(m_displayRatio));
- XUnlockDisplay(m_xineDisplay);
- /**** INIT XINE ENGINE ****/
- debugOut(QString("Using xine version %1").arg(xine_get_version_string()));
- m_xineEngine = xine_new();
- if (!m_xineEngine)
- {
- emit signalXineFatal(i18n("Can't init xine Engine!"));
- return false;
- }
- if (m_xineVerbose)
- xine_engine_set_param(m_xineEngine, XINE_ENGINE_PARAM_VERBOSITY, 99);
- /* load configuration */
- if (!QFile::exists(m_configFilePath))
- warningOut("No config file found, will create one...");
- else
- xine_config_load(m_xineEngine, m_configFilePath.ascii());
- debugOut("Post-init xine engine");
- xine_init(m_xineEngine);
- /** set xine parameters **/
- const char* const* drivers = NULL;
- drivers = xine_list_audio_output_plugins(m_xineEngine);
- int i = 0;
- while (drivers[i] != NULL) i++;
- m_audioChoices = new char*[i+2];
- m_audioChoices[0] = strdup("auto");
- m_audioDriverList << m_audioChoices[0];
- i = 0;
- while(drivers[i])
- {
- m_audioChoices[i+1] = strdup(drivers[i]);
- m_audioDriverList << m_audioChoices[i+1];
- i++;
- }
- m_audioChoices[i+1] = NULL;
- m_audioInfo = strdup(i18n("Audiodriver to use (default: auto)").utf8());
- i = xine_config_register_enum(m_xineEngine, "audio.driver", 0,
- m_audioChoices, m_audioInfo, NULL, 10, &KXineWidget::audioDriverChangedCallback, this);
- if (m_audioDriverList.contains(m_preferedAudio))
- m_audioDriverName = m_preferedAudio;
- else
- m_audioDriverName = m_audioChoices[i];
- debugOut(QString("Use audio driver %1").arg(m_audioDriverName));
- drivers = xine_list_video_output_plugins(m_xineEngine);
- i = 0;
- while (drivers[i] != NULL) i++;
- m_videoChoices = new char*[i+2];
- m_videoChoices[0] = strdup("auto");
- m_videoDriverList << m_videoChoices[0];
- i = 0;
- while(drivers[i])
- {
- m_videoChoices[i+1] = strdup(drivers[i]);
- m_videoDriverList << m_videoChoices[i+1];
- i++;
- }
- m_videoChoices[i+1] = NULL;
- m_videoInfo = strdup(i18n("Videodriver to use (default: auto)").utf8());
- i = xine_config_register_enum(m_xineEngine, "video.driver", 0,
- m_videoChoices, m_videoInfo, NULL, 10, &KXineWidget::videoDriverChangedCallback, this);
- if (m_videoDriverList.contains(m_preferedVideo))
- m_videoDriverName = m_preferedVideo;
- else
- m_videoDriverName = m_videoChoices[i];
- debugOut(QString("Use video driver %1").arg(m_videoDriverName));
- m_mixerInfo = strdup(i18n("Use software audio mixer").utf8());
- m_softwareMixer = (bool)xine_config_register_bool(m_xineEngine, "audio.mixer_software", 1, m_mixerInfo,
- NULL, 10, &KXineWidget::audioMixerMethodChangedCallback, this);
- m_osdShowInfo = strdup(i18n("Show OSD Messages").utf8());
- m_osdShow = (bool)xine_config_register_bool(m_xineEngine, "osd.osd_messages", 1, m_osdShowInfo,
- NULL, 10, &KXineWidget::showOSDMessagesChangedCallback, this);
- m_osdSizeOptions = new char*[7];
- m_osdSizeOptions[0] = strdup("tiny");
- m_osdSizeOptions[1] = strdup("small");
- m_osdSizeOptions[2] = strdup("medium");
- m_osdSizeOptions[3] = strdup("large");
- m_osdSizeOptions[4] = strdup("very large");
- m_osdSizeOptions[5] = strdup("huge");
- m_osdSizeOptions[6] = NULL;
- m_osdSizeInfo = strdup(i18n("Size of OSD text").utf8());
- m_osdSize = (int)xine_config_register_enum(m_xineEngine, "osd.osd_size", 1 /*small - 20P*/, m_osdSizeOptions, m_osdSizeInfo,
- NULL, 10, &KXineWidget::sizeForOSDMessagesChangedCallback, this);
- m_osdFontInfo = strdup(i18n("Font for OSD Messages").utf8());
- m_osdFont = strdup((char*)xine_config_register_string(m_xineEngine, "osd.osd_font", "sans", m_osdFontInfo,
- NULL, 10, &KXineWidget::fontForOSDMessagesChangedCallback, this));
- /* init video driver */
- debugOut("Init video driver");
- m_x11Visual.display = m_xineDisplay;
- m_x11Visual.screen = m_xineScreen;
- m_x11Visual.d = m_xineWindow;
- m_x11Visual.dest_size_cb = &KXineWidget::destSizeCallback;
- m_x11Visual.frame_output_cb = &KXineWidget::frameOutputCallback;
- m_x11Visual.user_data = (void*)this;
- m_videoDriver = xine_open_video_driver(m_xineEngine,
- m_videoDriverName.ascii(), XINE_VISUAL_TYPE_X11,
- (void *) &(m_x11Visual));
- if (!m_videoDriver && m_videoDriverName != "auto")
- {
- emit signalXineError(i18n("Can't init Video Driver '%1' - trying 'auto'...").arg(m_videoDriverName));
- m_videoDriverName = "auto";
- m_videoDriver = xine_open_video_driver(m_xineEngine,
- m_videoDriverName.ascii(), XINE_VISUAL_TYPE_X11,
- (void *) &(m_x11Visual));
- }
- if (!m_videoDriver)
- {
- emit signalXineFatal(i18n("All Video Drivers failed to initialize!"));
- return false;
- }
- /* init audio driver */
- debugOut("Init audio driver");
- m_audioDriver = xine_open_audio_driver(m_xineEngine, m_audioDriverName.ascii(), NULL);
- if (!m_audioDriver && m_audioDriverName != "auto")
- {
- emit signalXineError(i18n("Can't init Audio Driver '%1' - trying 'auto'...").arg(m_audioDriverName));
- m_audioDriverName = "auto";
- m_audioDriver = xine_open_audio_driver (m_xineEngine, m_audioDriverName.ascii(), NULL);
- }
- if (!m_audioDriver)
- {
- emit signalXineFatal(i18n("All Audio Drivers failed to initialize!"));
- return false;
- }
- //debugOut("Open xine stream");
- m_xineStream = xine_stream_new(m_xineEngine, m_audioDriver, m_videoDriver);
- if (!m_xineStream)
- {
- emit signalXineFatal(i18n("Can't create a new xine Stream!"));
- return false;
- }
- #ifdef XINE_PARAM_EARLY_FINISHED_EVENT
- if ( xine_check_version(1,1,1) ) {
- // enable gapless playback
- xine_set_param(m_xineStream, XINE_PARAM_EARLY_FINISHED_EVENT, 1 );
- }
- #endif
- /*** OSD ***/
- initOSD();
- /** event handling **/
- m_eventQueue = xine_event_new_queue (m_xineStream);
- xine_event_create_listener_thread(m_eventQueue, &KXineWidget::xineEventListener, (void*)this);
- //maybe user closed player in muted state
- if (m_softwareMixer)
- xine_set_param(m_xineStream, XINE_PARAM_AUDIO_AMP_MUTE, 0);
- else
- xine_set_param(m_xineStream, XINE_PARAM_AUDIO_MUTE, 0);
- m_xineReady = true;
- start();
- debugOut("xine init successful");
- emit signalXineStatus(i18n("Ready"));
- emit signalXineReady();
- /** something to play? **/
- slotPlay();
- return true;
- }
- void KXineWidget::initOSD()
- {
- debugOut("Init OSD");
- const int fontsizetable[] = { 16,20,24,32,48,64 };
- m_osd = xine_osd_new(m_xineStream, 10, 10, 1000, 200);
- if (m_osd)
- {
- if (!xine_osd_set_font(m_osd, m_osdFont, fontsizetable[m_osdSize]))
- {
- debugOut(QString("Font ->%1<- specified for OSD doesn't exists.").arg(m_osdFont));
- free(m_osdFont);
- m_osdFont = strdup("sans");
- xine_osd_set_font(m_osd, m_osdFont, fontsizetable[m_osdSize]);
- }
- debugOut(QString("Font for OSD: %1").arg(m_osdFont));
- xine_osd_set_text_palette(m_osd, XINE_TEXTPALETTE_WHITE_BLACK_TRANSPARENT, XINE_OSD_TEXT1);
- m_osdUnscaled = (xine_osd_get_capabilities(m_osd) & XINE_OSD_CAP_UNSCALED);
- if (m_osdUnscaled)
- debugOut("Unscaled OSD available");
- }
- else
- warningOut("Initialisation of xine OSD failed.");
- }
- /************************************************
- * PLAY MRL
- ************************************************/
- bool KXineWidget::playDvb()
- {
- #ifndef USE_QT_ONLY
- unwireAudioFilters();
- QPtrList<PostFilter> activeList;
- if (m_audioFilterList.count() && m_audioFiltersEnabled)
- activeList = m_audioFilterList;
- if ( !dvbHaveVideo )
- {
- if (!m_visualPlugin)
- {
- debugOut(QString("Init visual plugin: %1").arg(m_visualPluginName));
- m_visualPlugin = new PostFilter(m_visualPluginName, m_xineEngine, m_audioDriver, m_videoDriver, NULL);
- }
- activeList.insert (0, m_visualPlugin);
- }
- else
- {
- if (m_visualPlugin)
- {
- debugOut(QString("Dispose visual plugin: %1").arg(m_visualPluginName));
- delete m_visualPlugin;
- m_visualPlugin = NULL;
- }
- }
- if (activeList.count())
- {
- xine_post_wire_audio_port(activeList.at(activeList.count()-1)->getOutput(), m_audioDriver);
- for (uint i = activeList.count()-1; i >0; i--)
- {
- xine_post_wire(activeList.at(i-1)->getOutput(), activeList.at(i)->getInput());
- }
- xine_post_wire( xine_get_audio_source(m_xineStream), activeList.at(0)->getInput());
- }
- #endif
- if (!xine_play(m_xineStream, 0,0))
- {
- sendXineError();
- return false;
- }
- m_currentSpeed = Normal;
- m_trackHasChapters = false;
- m_trackArtist = QString::null;
- m_trackAlbum = QString::null;
- m_trackNumber = QString::null;
- m_trackYear = QString::null;
- m_trackComment = QString::null;
- m_trackIsSeekable = false;
- if ( !dvbHaveVideo ) m_trackHasVideo = false;
- else m_trackHasVideo = (bool)xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_VIDEO);
- if (m_trackHasVideo)
- {
- m_trackVideoCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_VIDEOCODEC);
- m_videoFrameWidth = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_WIDTH);
- m_videoFrameHeight = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_HEIGHT);
- m_trackVideoBitrate = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_BITRATE);
- }
- else
- {
- m_trackVideoCodec = QString::null;
- m_videoFrameWidth = 0;
- m_videoFrameHeight = 0;
- m_trackVideoBitrate = 0;
- }
- m_trackHasAudio = (bool)xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_AUDIO);
- if (m_trackHasAudio)
- {
- m_trackAudioCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_AUDIOCODEC);
- m_trackAudioBitrate = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_AUDIO_BITRATE);
- }
- else
- {
- m_trackAudioCodec = QString::null;
- m_trackAudioBitrate = 0;
- }
- m_trackLength = getLengthInfo();
- slotSetAudioChannel(0); //refresh channel info
- m_posTimer.start(1000);
- emit signalXinePlaying();
- emit signalXineStatus(i18n("Playing"));
- return true;
- }
- unsigned int KXineWidget::rgb2yuv( unsigned int R, unsigned int G, unsigned int B )
- {
- return ((((((66*R+129*G+25*B+128)>>8)+16)<<8)|(((112*R-94*G-18*B+128)>>8)+128))<<8|(((-38*R-74*G+112*B+128)>>8)+128));
- }
- void KXineWidget::initDvbPalette()
- {
- if ( dvbColor[0] ) return;
- memset( dvbColor, 0, sizeof(dvbColor) );
- memset( dvbTrans, 0, sizeof(dvbTrans) );
- dvbColor[0]=1;
- unsigned int blueText[11] = {
- rgb2yuv(0,0,0), /* 0 : not used */
- rgb2yuv(0,0,0), /* 1 : font bg */
- rgb2yuv(10,50,40), /* 2 : transition bg->border */
- rgb2yuv(30,100,85), /* 3 */
- rgb2yuv(50,150,130), /* 4 */
- rgb2yuv(70,200,175), /* 5 */
- rgb2yuv(90,255,220), /* 6 : border */
- rgb2yuv(90,255,220), /* 7 : transition border->fg */
- rgb2yuv(90,255,220), /* 8 */
- rgb2yuv(90,255,220), /* 9 */
- rgb2yuv(90,255,220), /* 10 : font fg */
- };
- unsigned int whiteText[11] = {
- rgb2yuv(0,0,0),
- rgb2yuv(0,0,0),
- rgb2yuv(50,50,50),
- rgb2yuv(100,100,100),
- rgb2yuv(150,150,150),
- rgb2yuv(200,200,200),
- rgb2yuv(255,255,255),
- rgb2yuv(255,255,255),
- rgb2yuv(255,255,255),
- rgb2yuv(255,255,255),
- rgb2yuv(255,255,255),
- };
- unsigned int greenText[11] = {
- rgb2yuv(0,0,0),
- rgb2yuv(0,0,0),
- rgb2yuv(30,50,30),
- rgb2yuv(60,100,30),
- rgb2yuv(90,150,90),
- rgb2yuv(120,200,120),
- rgb2yuv(150,255,150),
- rgb2yuv(150,255,150),
- rgb2yuv(150,255,150),
- rgb2yuv(150,255,150),
- rgb2yuv(150,255,150),
- };
- unsigned char textAlpha[11] = { 0, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, };
- #define DVB_TEXT_WHITE 100
- #define DVB_TEXT_BLUE 111
- #define DVB_TEXT_GREEN 122
- int a;
- for ( a=DVB_TEXT_BLUE; a<DVB_TEXT_BLUE+11; a++ )
- {
- dvbColor[a]=blueText[a-DVB_TEXT_BLUE];
- dvbTrans[a]=textAlpha[a-DVB_TEXT_BLUE];
- }
- for ( a=DVB_TEXT_GREEN; a<DVB_TEXT_GREEN+11; a++ )
- {
- dvbColor[a]=greenText[a-DVB_TEXT_GREEN];
- dvbTrans[a]=textAlpha[a-DVB_TEXT_GREEN];
- }
- for ( a=DVB_TEXT_WHITE; a<DVB_TEXT_WHITE+11; a++ )
- {
- dvbColor[a]=whiteText[a-DVB_TEXT_WHITE];
- dvbTrans[a]=textAlpha[a-DVB_TEXT_WHITE];
- }
- #define DVB_COLOR_RED 200
- dvbColor[DVB_COLOR_RED] = rgb2yuv(255,0,0); dvbTrans[DVB_COLOR_RED] = 15;
- #define DVB_COLOR_GREEN 201
- dvbColor[DVB_COLOR_GREEN] = rgb2yuv(0,255,0); dvbTrans[DVB_COLOR_GREEN] = 15;
- #define DVB_COLOR_MAGENTA 202
- dvbColor[DVB_COLOR_MAGENTA] = rgb2yuv(255,128,255); dvbTrans[DVB_COLOR_MAGENTA] = 15;
- }
- void KXineWidget::dvbShowOSD()
- {
- if ( m_trackURL!="DVB" )
- return;
- if ( xine_get_status(m_xineStream)!=XINE_STATUS_PLAY )
- return;
- if ( !dvbHaveVideo )
- m_trackHasVideo = false;
- else
- m_trackHasVideo = (bool)xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_VIDEO);
- if (m_trackHasVideo) {
- m_trackVideoCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_VIDEOCODEC);
- m_videoFrameWidth = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_WIDTH);
- m_videoFrameHeight = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_HEIGHT);
- m_trackVideoBitrate = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_BITRATE);
- }
- else {
- m_trackVideoCodec = QString::null;
- m_videoFrameWidth = 0;
- m_videoFrameHeight = 0;
- m_trackVideoBitrate = 0;
- }
- m_trackHasAudio = (bool)xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_AUDIO);
- if (m_trackHasAudio) {
- m_trackAudioCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_AUDIOCODEC);
- m_trackAudioBitrate = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_AUDIO_BITRATE);
- }
- else {
- m_trackAudioCodec = QString::null;
- m_trackAudioBitrate = 0;
- }
- if ( dvbOSD ) {
- xine_osd_free( dvbOSD );
- dvbOSD = 0;
- }
- int border=40;
- int w = m_videoFrameWidth;
- int h = m_videoFrameHeight;
- if ( !w || !h )
- return;
- if ( w<800 ) {
- if ( dvbCurrentNext[0]=="E" ) {
- dvbOSDHideTimer.stop();
- dvbOSD = xine_osd_new( m_xineStream, border, border, w-(2*border), h-(2/border) );
- }
- else
- dvbOSD = xine_osd_new( m_xineStream, border, h-border-100, w-(2*border), 100 );
- }
- if ( dvbOSD ) {
- QCString ct, cs;
- if ( !dvbColor[0] ) initDvbPalette();
- //xine_osd_get_palette( dvbOSD, dvbColor, dvbTrans );
- xine_osd_set_palette( dvbOSD, dvbColor, dvbTrans );
- xine_osd_set_font( dvbOSD, m_osdFont, 16 );
- xine_osd_set_encoding( dvbOSD, "utf-8" );
- if ( dvbCurrentNext[0]=="E" )
- xine_osd_draw_rect( dvbOSD, 0, 0, w-(2*border), h-(2*border), DVB_TEXT_WHITE+1, 1 );
- else
- xine_osd_draw_rect( dvbOSD, 0, 0, w-(2*border), 100, DVB_TEXT_WHITE+1, 1 );
- QString t = QTime::currentTime().toString( "hh:mm" );
- int tw, th, len;
- xine_osd_get_text_size(dvbOSD, t.utf8(), &tw, &th);
- len = tw;
- int offset = 5;
- xine_osd_draw_text( dvbOSD, w-(2*border)-tw-offset, 5, t.utf8(), DVB_TEXT_BLUE );
- int i;
- for ( i=0; i<(int)dvbCurrentNext.count(); i++ ) {
- if ( dvbCurrentNext[i]=="R" ) {
- xine_osd_draw_rect( dvbOSD, offset, 5, offset+16, 21, DVB_COLOR_RED, 1 );
- offset+=21;
- }
- else if ( dvbCurrentNext[i]=="T" ) {
- xine_osd_draw_rect( dvbOSD, offset, 5, offset+16, 21, DVB_COLOR_GREEN, 1 );
- offset+=21;
- }
- }
- if (m_dvbChannelName == "")
- t = m_trackTitle;
- else
- t = m_dvbChannelName;
- i=0;
- ct = t.utf8();
- while ( i<(int)t.length() ) {
- xine_osd_get_text_size( dvbOSD, ct, &tw, &th );
- if ( tw<=(w-(2*border)-offset-5-len) ) break;
- ct = ct.remove( ct.length()-1, ct.length() );
- i++;
- }
- xine_osd_draw_text( dvbOSD, offset, 5, ct, DVB_TEXT_BLUE );
- xine_osd_draw_line( dvbOSD, 5, 10+18, w-(2*border)-5, 10+18, DVB_COLOR_MAGENTA );
- QString s, c;
- int y=43;
- int pos;
- if ( dvbCurrentNext[0]=="E" ) {
- if ( dvbCurrentNext.count()<2 ) {
- xine_osd_show( dvbOSD, 0 );
- return;
- }
- if ( !dvbCurrentNext[1].isEmpty() ) {
- s = dvbCurrentNext[1];
- pos = s.find("-");
- c = s.left( pos+1 );
- s = s.right( s.length()-pos-1 );
- t = s;
- xine_osd_draw_text( dvbOSD, 10, y, c.utf8(), DVB_TEXT_GREEN );
- xine_osd_get_text_size( dvbOSD, c.utf8(), &offset, &th );
- i=0;
- cs = s.utf8();
- while ( i<(int)t.length() ) {
- ct = cs.remove( cs.length()-i, cs.length() );
- xine_osd_get_text_size( dvbOSD, ct, &tw, &th );
- if ( tw<=(w-(2*border)-20) ) break;
- i++;
- }
- xine_osd_draw_text( dvbOSD, 10+offset, y, ct, DVB_TEXT_WHITE );
- y+= 40;
- }
- if ( !dvbCurrentNext[2].isEmpty() ) {
- cs = dvbCurrentNext[2].utf8();
- pos = 0;
- while ( pos!=-1 && y<(h-(2*border)-23) ) {
- ct = cs;
- i = 0;
- while ( pos!=-1 ) {
- xine_osd_get_text_size( dvbOSD, ct, &tw, &th );
- if ( tw<=(w-(2*border)-20) ) break;
- pos = ct.findRev(" ");
- ct = ct.left( pos );
- i++;
- }
- xine_osd_draw_text( dvbOSD, 10, y, ct, DVB_TEXT_BLUE );
- if ( !ct.length() || !i ) break;
- cs = cs.right( cs.length()-ct.length()-1 );
- y+= 28;
- }
- y+= 40;
- }
- if ( !dvbCurrentNext[3].isEmpty() ) {
- cs = dvbCurrentNext[3].utf8();
- pos = 0;
- while ( pos!=-1 && y<(h-(2*border)-23) ) {
- ct = cs;
- i = 0;
- while ( pos!=-1 ) {
- xine_osd_get_text_size( dvbOSD, ct, &tw, &th );
- if ( tw<=(w-(2*border)-20) ) break;
- pos = ct.findRev(" ");
- ct = ct.left( pos );
- i++;
- }
- xine_osd_draw_text( dvbOSD, 10, y, ct, DVB_TEXT_WHITE );
- if ( !ct.length() || !i ) break;
- cs = cs.right( cs.length()-ct.length()-1 );
- y+= 28;
- }
- }
- xine_osd_show( dvbOSD, 0 );
- return;
- }
- for ( int j=0; j<(int)dvbCurrentNext.count(); j++ ) {
- if ( (dvbCurrentNext[ j ]=="T") || (dvbCurrentNext[ j ]=="R") ) continue;
- s = dvbCurrentNext[ j ];
- pos = s.find("-");
- c = s.left( pos+1 );
- s = s.right( s.length()-pos-1 );
- ct = cs = s.utf8();
- xine_osd_draw_text( dvbOSD, 10, y, c.utf8(), DVB_TEXT_GREEN );
- xine_osd_get_text_size( dvbOSD, c.utf8(), &offs…