diff options
Diffstat (limited to 'src/part')
-rw-r--r-- | src/part/SConscript | 12 | ||||
-rw-r--r-- | src/part/part.cpp | 83 | ||||
-rw-r--r-- | src/part/part.h | 38 | ||||
-rw-r--r-- | src/part/toolbar.cpp | 44 | ||||
-rw-r--r-- | src/part/toolbar.h | 18 | ||||
-rw-r--r-- | src/part/videoWindow.cpp | 192 | ||||
-rw-r--r-- | src/part/videoWindow.h | 94 | ||||
-rw-r--r-- | src/part/xineEngine.cpp | 345 |
8 files changed, 826 insertions, 0 deletions
diff --git a/src/part/SConscript b/src/part/SConscript new file mode 100644 index 0000000..c2bce67 --- /dev/null +++ b/src/part/SConscript @@ -0,0 +1,12 @@ +# Copyright 2005 Max Howell <[email protected]> + +Import( "*" ) +myenv=env.Copy() + +## Additional paths for compiling the source files +## Always add '../' (top-level directory) because moc makes code that needs it +KDEaddpaths( ['./', '../', '../../'], myenv ) + +KDEaddlibs( ['qt-mt', 'kdecore', 'kdeui', 'kparts', 'xine'], myenv ) + +KDEshlib( "libcodeine", Split( "part.cpp xineEngine.cpp videoWindow.cpp toolbar.cpp ../mxcl.library.cpp" ), myenv ) diff --git a/src/part/part.cpp b/src/part/part.cpp new file mode 100644 index 0000000..20d1577 --- /dev/null +++ b/src/part/part.cpp @@ -0,0 +1,83 @@ +// Author: Max Howell <[email protected]>, (C) 2005
+// Copyright: See COPYING file that comes with this distribution
+
+#include "codeine.h"
+#include "debug.h"
+#include <kaboutdata.h>
+#include <kparts/genericfactory.h>
+#include "part.h"
+#include <qtimer.h>
+#include "toolbar.h"
+#include "videoWindow.h"
+
+#include <kaction.h>
+#include <qslider.h>
+
+namespace Codeine
+{
+ typedef KParts::GenericFactory<Codeine::Part> Factory;
+}
+
+
+K_EXPORT_COMPONENT_FACTORY( libcodeine, Codeine::Factory )
+
+
+namespace Codeine
+{
+ Part::Part( QWidget *parentWidget, const char *widgetName, QObject *parent, const char *name, const QStringList& )
+ : ReadOnlyPart( parent, name )
+ , m_statusBarExtension( new KParts::StatusBarExtension( this ) )
+ {
+ setInstance( Factory::instance() );
+ setWidget( new VideoWindow( parentWidget, widgetName ) );
+
+ if( !videoWindow()->init() )
+ //FIXME this will terminate the host, eg Konqueror
+ Debug::fatal() << "Couldn't init xine!\n";
+
+ KAction *play = new KToggleAction( i18n("Play"), "player_play", Qt::Key_Space, videoWindow(), SLOT(togglePlay()), actionCollection(), "play" );
+ KAction *mute = new KToggleAction( i18n("Mute"), "player_mute", Qt::Key_M, videoWindow(), SLOT(toggleMute()), actionCollection(), "mute" );
+ KToolBar *toolBar = new MouseOverToolBar( widget() );
+ play->plug( toolBar );
+ mute->plug( toolBar );
+ m_slider = new QSlider( Qt::Horizontal, toolBar, "slider" );
+ m_slider->setMaxValue( 65535 );
+ toolBar->setStretchableWidget( m_slider );
+ toolBar->addSeparator(); //FIXME ugly
+
+ QObject *o = (QObject*)statusBar();
+ connect( videoWindow(), SIGNAL(statusMessage( const QString& )), o, SLOT(message( const QString& )) );
+ connect( videoWindow(), SIGNAL(titleChanged( const QString& )), o, SLOT(message( const QString& )) ); //FIXME
+ }
+
+ bool
+ Part::openURL( const KURL &url )
+ {
+ //FIXME nasty, we'd rather not do this way
+ killTimers();
+ startTimer( 100 );
+
+ return videoWindow()->play( m_url = url );
+ }
+
+ bool
+ Part::closeURL()
+ {
+ m_url = KURL();
+ videoWindow()->eject();
+ return true;
+ }
+
+ KAboutData*
+ Part::createAboutData()
+ {
+ // generic factory expects this on the heap
+ return new KAboutData( APP_NAME, PRETTY_NAME, APP_VERSION );
+ }
+
+ void
+ Part::timerEvent( QTimerEvent* )
+ {
+ m_slider->setValue( videoWindow()->position() );
+ }
+}
diff --git a/src/part/part.h b/src/part/part.h new file mode 100644 index 0000000..30467ac --- /dev/null +++ b/src/part/part.h @@ -0,0 +1,38 @@ +// Author: Max Howell <[email protected]>, (C) 2005
+// Copyright: See COPYING file that comes with this distribution
+
+#ifndef CODEINE_PART_H
+#define CODEINE_PART_H
+
+#include <kparts/statusbarextension.h>
+#include <kparts/part.h>
+#include <kurl.h>
+
+class KAboutData;
+class QSlider;
+
+
+namespace Codeine
+{
+ class Part : public KParts::ReadOnlyPart
+ {
+ public:
+ Part( QWidget*, const char*, QObject*, const char*, const QStringList& );
+
+ virtual bool openFile() { return false; } //pure virtual in base class
+ virtual bool openURL( const KURL& );
+ virtual bool closeURL();
+
+ static KAboutData *createAboutData();
+
+ private:
+ KParts::StatusBarExtension *m_statusBarExtension;
+ QSlider *m_slider;
+
+ KStatusBar *statusBar() { return m_statusBarExtension->statusBar(); }
+
+ virtual void timerEvent( QTimerEvent* );
+ };
+}
+
+#endif
diff --git a/src/part/toolbar.cpp b/src/part/toolbar.cpp new file mode 100644 index 0000000..8939074 --- /dev/null +++ b/src/part/toolbar.cpp @@ -0,0 +1,44 @@ +// (C) 2005 Max Howell ([email protected]) +// See COPYING file for licensing information + +#include <kpushbutton.h> +#include <qapplication.h> +#include <qevent.h> +#include "toolbar.h" + + +MouseOverToolBar::MouseOverToolBar( QWidget *parent ) + : KToolBar( parent ) +{ + parent->installEventFilter( this ); + move( 0, 0 ); //TODO necessary? + hide(); + + setPalette( QApplication::palette() ); //videoWindow palette has a black background +} + +bool +MouseOverToolBar::eventFilter( QObject *o, QEvent *e ) +{ + Q_ASSERT( o == parent() ); + + switch( e->type() ) + { + case QEvent::Resize: + resize( static_cast<QResizeEvent*>(e)->size().width(), sizeHint().height() ); + break; + + case QEvent::Enter: + show(); + break; + + case QEvent::Leave: + hide(); + break; + + default: + ; + } + + return false; +}
\ No newline at end of file diff --git a/src/part/toolbar.h b/src/part/toolbar.h new file mode 100644 index 0000000..cd189d4 --- /dev/null +++ b/src/part/toolbar.h @@ -0,0 +1,18 @@ +// (C) 2005 Max Howell ([email protected]) +// See COPYING file for licensing information + +#ifndef CODEINE_TOOLBAR_H +#define CODEINE_TOOLBAR_H + +#include <ktoolbar.h> + + +class MouseOverToolBar : public KToolBar +{ + virtual bool eventFilter( QObject*, QEvent* ); + +public: + MouseOverToolBar( QWidget *parent ); +}; + +#endif diff --git a/src/part/videoWindow.cpp b/src/part/videoWindow.cpp new file mode 100644 index 0000000..d798b36 --- /dev/null +++ b/src/part/videoWindow.cpp @@ -0,0 +1,192 @@ +// (C) 2005 Max Howell ([email protected]) +// See COPYING file for licensing information + +#define CODEINE_DEBUG_PREFIX "videoWindow" + +#include <cstdlib> +#include "debug.h" +#include <qapplication.h> //sendEvent() +#include <qcursor.h> +#include <qevent.h> +#include "videoWindow.h" +#include <X11/Xlib.h> //TODO this breaks compile for lots of people due to excessive macro content +#include <xine.h> //x11_visual_t + + +namespace Codeine { + + +VideoWindow *VideoWindow::s_instance = 0; + + +namespace X +{ + Display *d; + int s, w; +} + + +VideoWindow::VideoWindow( QWidget *parent, const char *name ) + : QWidget( parent, name ) + , m_osd( 0 ) + , m_stream( 0 ) + , m_eventQueue( 0 ) + , m_videoPort( 0 ) + , m_audioPort( 0 ) + , m_xine( 0 ) + , m_displayRatio( 1 ) +{ + s_instance = this; + + // with this Konqueror would crash on exit + // without this we may be unstable! + //XInitThreads(); + + show(); + + setWFlags( Qt::WNoAutoErase ); + setMouseTracking( true ); + setAcceptDrops( true ); + setUpdatesEnabled( false ); //to stop Qt drawing over us + setPaletteBackgroundColor( Qt::black ); + + X::d = XOpenDisplay( std::getenv("DISPLAY") ); + X::s = DefaultScreen( X::d ); + X::w = winId(); + + XLockDisplay( X::d ); + XSelectInput( X::d, X::w, ExposureMask ); + + { + using X::d; using X::s; + + //these are Xlib macros + double w = DisplayWidth( d, s ) * 1000 / DisplayWidthMM( d, s ); + double h = DisplayHeight( d, s ) * 1000 / DisplayHeightMM( d, s ); + + m_displayRatio = w / h; + } + + XUnlockDisplay( X::d ); + + connect( &m_timer, SIGNAL(timeout()), SLOT(hideCursor()) ); +} + +VideoWindow::~VideoWindow() +{ + DEBUG_BLOCK + + if( m_osd ) xine_osd_free( m_osd ); + if( m_stream ) xine_close( m_stream ); + if( m_eventQueue ) xine_event_dispose_queue( m_eventQueue ); + if( m_stream ) xine_dispose( m_stream ); + if( m_videoPort ) xine_close_video_driver( m_xine, m_videoPort ); + if( m_audioPort ) xine_close_audio_driver( m_xine, m_audioPort ); + if( m_xine ) xine_exit( m_xine ); + + XCloseDisplay( X::d ); +} + +void* +VideoWindow::x11Visual() const +{ + x11_visual_t* visual = new x11_visual_t; + + visual->display = X::d; + visual->screen = X::s; + visual->d = X::w; + visual->dest_size_cb = &VideoWindow::destSizeCallBack; + visual->frame_output_cb = &VideoWindow::frameOutputCallBack; + visual->user_data = (void*)this; + + return visual; +} + +void +VideoWindow::destSizeCallBack( + void* p, int /*video_width*/, int /*video_height*/, + double /*video_aspect*/, int* dest_width, + int* dest_height, double* dest_aspect ) +{ + if( !p ) + return; + + #define vw static_cast<VideoWindow*>(p) + + *dest_width = vw->width(); + *dest_height = vw->height(); + *dest_aspect = vw->m_displayRatio; +} + +void +VideoWindow::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 ) + return; + + *dest_x = 0; + *dest_y = 0 ; + *dest_width = vw->width(); + *dest_height = vw->height(); + *win_x = vw->x(); + *win_y = vw->y(); + *dest_aspect = vw->m_displayRatio; + + // correct size with video aspect + // TODO what's this about? + 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 ); + + #undef vw +} + +bool +VideoWindow::event( QEvent *e ) +{ + switch( e->type() ) + { + case QEvent::MouseMove: + case QEvent::MouseButtonPress: + unsetCursor(); + m_timer.start( CURSOR_HIDE_TIMEOUT, true ); + break; + + case QEvent::Close: + case QEvent::Hide: + xine_stop( m_stream ); + break; + + case QEvent::Leave: + m_timer.stop(); + break; + + default: + ; + } + + return QWidget::event( e ); +} + +bool +VideoWindow::x11Event( XEvent *e ) +{ + if( e->type == Expose && e->xexpose.count == 0 ) { + xine_gui_send_vo_data( m_stream, XINE_GUI_SEND_EXPOSE_EVENT, e ); + return true; + } + + return false; +} + +void +VideoWindow::hideCursor() +{ + setCursor( Qt::BlankCursor ); +} + +} //namespace Codeine diff --git a/src/part/videoWindow.h b/src/part/videoWindow.h new file mode 100644 index 0000000..7db72ab --- /dev/null +++ b/src/part/videoWindow.h @@ -0,0 +1,94 @@ +// (C) 2005 Max Howell ([email protected]) +// See COPYING file for licensing information + +#ifndef CODEINE_VIDEO_WINDOW_H +#define CODEINE_VIDEO_WINDOW_H + +#include "../codeine.h" +#include <qtimer.h> +#include <qwidget.h> +#include <kurl.h> + +typedef struct xine_s xine_t; +typedef struct xine_stream_s xine_stream_t; +typedef struct xine_video_port_s xine_video_port_t; +typedef struct xine_audio_port_s xine_audio_port_t; +typedef struct xine_event_queue_s xine_event_queue_t; +typedef struct xine_post_s xine_post_t; +typedef struct xine_osd_s xine_osd_t; + + +namespace Codeine +{ + class VideoWindow : public QWidget + { + Q_OBJECT + + static VideoWindow *s_instance; + static const uint CURSOR_HIDE_TIMEOUT = 2000; + + friend VideoWindow* const videoWindow(); + + public: + VideoWindow( QWidget *parent, const char *name ); + ~VideoWindow(); + + bool init(); + + bool play( KURL ); + void eject(); + + int position(); + + signals: + void statusMessage( const QString& ); + void titleChanged( const QString& ); + + private: + /// @see xineEngine.cpp + #ifdef HAVE_XINE_H + static void xineEventListener( void*, const xine_event_t* ); + #endif + + void showErrorMessage(); //TODO don't use this, just show delayed message + + virtual void customEvent( QCustomEvent* ); + virtual bool x11Event( XEvent* ); + virtual bool event( QEvent* ); + + xine_osd_t *m_osd; + xine_stream_t *m_stream; + xine_event_queue_t *m_eventQueue; + xine_video_port_t *m_videoPort; + xine_audio_port_t *m_audioPort; + xine_t *m_xine; + + KURL m_url; + + private: + void *x11Visual() const; + + static void destSizeCallBack( void*, int, int, double, int*, int*, double* ); + static void frameOutputCallBack( void*, int, int, double, int*, int*, int*, int*, double*, int*, int* ); + + double m_displayRatio; + QTimer m_timer; + + public slots: + void togglePlay(); + void toggleMute(); + + private slots: + void hideCursor(); + + private: + /// prevent compiler generated functions + VideoWindow( const VideoWindow& ); + VideoWindow &operator=( const VideoWindow& ); + bool operator==( const VideoWindow& ); + }; + + inline VideoWindow* const videoWindow() { return VideoWindow::s_instance; } +} + +#endif diff --git a/src/part/xineEngine.cpp b/src/part/xineEngine.cpp new file mode 100644 index 0000000..2365f83 --- /dev/null +++ b/src/part/xineEngine.cpp @@ -0,0 +1,345 @@ +// (C) 2005 Max Howell ([email protected]) +// See COPYING file for licensing information + +#define CODEINE_DEBUG_PREFIX "engine" + +#include "debug.h" +#include <kglobalsettings.h> +#include <klocale.h> +#include "mxcl.library.h" +#include <qapplication.h> //::sendEvent() +#include <qdatetime.h> //::play() +#include <qdir.h> //QDir::homeDir() +#include <xine.h> +#include "videoWindow.h" + + +namespace Codeine { + + +bool +VideoWindow::init() +{ + mxcl::WaitCursor allocateOnStack; + + debug() << "xine_new()\n"; + m_xine = xine_new(); + if( !m_xine ) + return false; + + debug() << "xine_config_load()\n"; + xine_config_load( m_xine, QFile::encodeName( QDir::homeDirPath() + "/.xine/config" ) ); + + debug() << "xine_init()\n"; + xine_init( m_xine ); + + debug() << "xine_open_video_driver()\n"; + m_videoPort = xine_open_video_driver( m_xine, "auto", XINE_VISUAL_TYPE_X11, x11Visual() ); + + debug() << "xine_open_audio_driver()\n"; + m_audioPort = xine_open_audio_driver( m_xine, "auto", NULL ); + + debug() << "xine_stream_new()\n"; + m_stream = xine_stream_new( m_xine, m_audioPort, m_videoPort ); + if( !m_stream ) + return false; + + if( !m_audioPort ) + MessageBox::error( i18n("xine was unable to initialize any audio-drivers.") ); + if( !m_videoPort ) + MessageBox::error( i18n("xine was unable to initialize any video-drivers.") ); + + debug() << "xine_osd_new()\n"; + m_osd = xine_osd_new( m_stream, 10, 10, 1000, 18 * 6 + 10 ); + if( m_osd ) { + xine_osd_set_font( m_osd, "sans", 18 ); + xine_osd_set_text_palette( m_osd, XINE_TEXTPALETTE_WHITE_BLACK_TRANSPARENT, XINE_OSD_TEXT1 ); + } + + debug() << "xine_event_create_listener_thread()\n"; + xine_event_create_listener_thread( + m_eventQueue = xine_event_new_queue( m_stream ), + &VideoWindow::xineEventListener, (void*)this ); + + { /// set save directory + xine_cfg_entry_t config; + + if( xine_config_lookup_entry( m_xine, "misc.save_dir", &config ) ) { + const QCString dir = KGlobalSettings::desktopPath().local8Bit(); + config.str_value = qstrdup( dir ); + xine_config_update_entry( m_xine, &config ); + } + } + + return true; +} + +bool +VideoWindow::play( KURL url ) +{ + DEBUG_BLOCK + + m_url = url; + + mxcl::WaitCursor allocateOnStack; + + //TODO make sensible + if( url.protocol() == "http" ) { + /// automatically save http streams to Desktop folder + + const QString fileName = url.filename(); + + QString + u = url.url(); + u += "#save:"; + u += url.host(); + u += " ["; + u += QDate::currentDate().toString(); + u += ']'; + u += fileName.mid( fileName.findRev( '.' ) + 1 ).lower(); + + url = u; + } + + debug() << "About to load..\n"; + if( xine_open( m_stream, url.url().local8Bit() ) ) + { + debug() << "About to play..\n"; + if( xine_play( m_stream, 0, 0 ) ) + return true; + } + + showErrorMessage(); + return false; +} + +void +VideoWindow::togglePlay() +{ + if( xine_get_param( m_stream, XINE_PARAM_SPEED ) ) { + xine_set_param( m_stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE ); + xine_set_param( m_stream, XINE_PARAM_AUDIO_CLOSE_DEVICE, 1); + } + else + xine_set_param( m_stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL ); +} + +void +VideoWindow::toggleMute() +{ + bool const muted = xine_get_param( m_stream, XINE_PARAM_AUDIO_MUTE ); + xine_set_param( m_stream, XINE_PARAM_AUDIO_MUTE, !muted ); +} + +void +VideoWindow::eject() +{ + m_url = KURL(); + + xine_stop( m_stream ); +} + +int +VideoWindow::position() +{ + int pos = 0, time = 0, length = 0; + xine_get_pos_length( m_stream, &pos, &time, &length ); + + return pos; +} + +void +VideoWindow::showErrorMessage() +{ + const QString filename = m_url.fileName(); + + debug() << "xine_get_error()\n"; + + // NOTE these error messages are somewhat customised + // relative to the main application + // This is because when embedded in some other application + // the error messages have no context, so we must say that we are a video player! + + switch( xine_get_error( m_stream ) ) + { + case XINE_ERROR_NO_INPUT_PLUGIN: + MessageBox::sorry( i18n("The Codeine video player could not find an input plugin for '%1'.").arg( filename ) ); + break; + case XINE_ERROR_NO_DEMUX_PLUGIN: + MessageBox::sorry( i18n("The Codeine video player could not find a demux plugin for '%1'.").arg( filename ) ); + break; + case XINE_ERROR_DEMUX_FAILED: + MessageBox::sorry( i18n("The Codeine video player failed to demux '%1'; please check your xine installation.").arg( filename ) ); + break; + case XINE_ERROR_INPUT_FAILED: + case XINE_ERROR_MALFORMED_MRL: + case XINE_ERROR_NONE: + MessageBox::sorry( i18n("The Codeine video player reports an internal error; please check your xine installation.") ); + break; + } +} + +void +VideoWindow::customEvent( QCustomEvent *e ) +{ + switch( e->type() - 2000 ) { + case XINE_EVENT_UI_PLAYBACK_FINISHED: +//FIXME emit stateChanged( Engine::TrackEnded ); + break; + + case 1000: + #define message static_cast<QString*>(e->data()) + emit statusMessage( *message ); + delete message; + break; + + case 1001: + MessageBox::sorry( (*message).arg( "FIXME" ) ); //FIXME + delete message; + break; + + case 1002: + emit titleChanged( *message ); + delete message; + break; + #undef message + + default: + ; + } +} + +void +VideoWindow::xineEventListener( void *p, const xine_event_t* xineEvent ) +{ + if( !p ) + return; + + #define engine static_cast<VideoWindow*>(p) + + switch( xineEvent->type ) { + case XINE_EVENT_MRL_REFERENCE: + { + mxcl::WaitCursor allocateOnStack; + const char *mrl = ((xine_mrl_reference_data_t*)xineEvent->data)->mrl; + + debug() << "XINE_EVENT_MRL_REFERENCE: " << mrl << endl; + + if( xine_open( engine->m_stream, mrl ) ) + xine_play( engine->m_stream, 0, 0 ); + + break; + } + + case XINE_EVENT_UI_NUM_BUTTONS: debug() << "XINE_EVENT_UI_NUM_BUTTONS\n"; break; + case XINE_EVENT_DROPPED_FRAMES: debug() << "XINE_EVENT_DROPPED_FRAMES\n"; break; + + case XINE_EVENT_UI_PLAYBACK_FINISHED: + case XINE_EVENT_FRAME_FORMAT_CHANGE: + case XINE_EVENT_UI_CHANNELS_CHANGED: + { + QCustomEvent *ce; + ce = new QCustomEvent( 2000 + xineEvent->type ); + ce->setData( const_cast<xine_event_t*>(xineEvent) ); + QApplication::postEvent( engine, ce ); + break; + } + + case XINE_EVENT_UI_SET_TITLE: + QApplication::postEvent( engine, new QCustomEvent( + QEvent::Type(3002), + new QString( QString::fromUtf8( static_cast<xine_ui_data_t*>(xineEvent->data)->str ) ) ) ); + break; + + case XINE_EVENT_PROGRESS: + { + xine_progress_data_t* pd = (xine_progress_data_t*)xineEvent->data; + + QString + msg = "%1 %2%"; + msg = msg.arg( QString::fromUtf8( pd->description ) ) + .arg( KGlobal::locale()->formatNumber( pd->percent, 0 ) ); + + QApplication::postEvent( engine, new QCustomEvent( QEvent::Type(3000), new QString( msg ) ) ); + break; + } + case XINE_EVENT_UI_MESSAGE: + { + debug() << "Message received from xine\n"; + + xine_ui_message_data_t *data = (xine_ui_message_data_t *)xineEvent->data; + QString message; + + switch( data->type ) { + case XINE_MSG_NO_ERROR: + { + //series of \0 separated strings, terminated with a \0\0 + char str[2000]; + char *p = str; + for( char *msg = data->messages; !(*msg == '\0' && *(msg+1) == '\0'); ++msg, ++p ) + *p = *msg == '\0' ? '\n' : *msg; + *p = '\0'; + + debug() << str << endl; + + break; + } + + case XINE_MSG_ENCRYPTED_SOURCE: + message = i18n("The source is encrypted and can not be decrypted."); goto param; + case XINE_MSG_UNKNOWN_HOST: + message = i18n("The host is unknown for the URL: <i>%1</i>"); goto param; + case XINE_MSG_UNKNOWN_DEVICE: + message = i18n("The device name you specified seems invalid."); goto param; + case XINE_MSG_NETWORK_UNREACHABLE: + message = i18n("The network appears unreachable."); goto param; + case XINE_MSG_AUDIO_OUT_UNAVAILABLE: + message = i18n("Audio output unavailable; the device is busy."); goto param; + case XINE_MSG_CONNECTION_REFUSED: + message = i18n("The connection was refused for the URL: <i>%1</i>"); goto param; + case XINE_MSG_FILE_NOT_FOUND: + message = i18n("xine could not find the URL: <i>%1</i>"); goto param; + case XINE_MSG_PERMISSION_ERROR: + message = i18n("Access was denied for the URL: <i>%1</i>"); goto param; + case XINE_MSG_READ_ERROR: + message = i18n("The source cannot be read for the URL: <i>%1</i>"); goto param; + case XINE_MSG_LIBRARY_LOAD_ERROR: + message = i18n("A problem occurred while loading a library or decoder."); goto param; + + case XINE_MSG_GENERAL_WARNING: + case XINE_MSG_SECURITY: + default: + + if(data->explanation) + { + message += "<b>"; + message += QString::fromUtf8( (char*) data + data->explanation ); + message += "</b>"; + } + else break; //if no explanation then why bother! + + //FALL THROUGH + + param: + + message.prepend( "<p>" ); + message += "<p>"; + + if(data->parameters) + { + message += "xine says: <i>"; + message += QString::fromUtf8( (char*) data + data->parameters); + message += "</i>"; + } + else message += i18n("Sorry, no additional information is available."); + + QApplication::postEvent( engine, new QCustomEvent(QEvent::Type(3001), new QString(message)) ); + } + + } //case + } //switch + + #undef engine +} + +} //namespace Codeine |