summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/multimedia/opieplayer2/lib.cpp18
-rw-r--r--noncore/multimedia/opieplayer2/lib.h2
-rw-r--r--noncore/multimedia/opieplayer2/threadutil.cpp17
-rw-r--r--noncore/multimedia/opieplayer2/threadutil.h6
4 files changed, 28 insertions, 15 deletions
diff --git a/noncore/multimedia/opieplayer2/lib.cpp b/noncore/multimedia/opieplayer2/lib.cpp
index 8afb318..f1b9773 100644
--- a/noncore/multimedia/opieplayer2/lib.cpp
+++ b/noncore/multimedia/opieplayer2/lib.cpp
@@ -1,168 +1,168 @@
/*
                This file is part of the Opie Project
              Copyright (c) 2002 Max Reiss <harlekin@handhelds.org>
Copyright (c) 2002 LJP <>
Copyright (c) 2002 Holger Freyther <zecke@handhelds.org>
=.
.=l.
           .>+-=
 _;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU General Public
.="- .-=="i,     .._ License as published by the Free Software
 - .   .-<_>     .<> Foundation; either version 2 of the License,
     ._= =}       : or (at your option) any later version.
    .%`+i>       _;_.
    .i_,=:_.      -<s. This program is distributed in the hope that
     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
    : ..    .:,     . . . without even the implied warranty of
    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
 :     =  ...= . :.=-
 -.   .:....=;==+<; You should have received a copy of the GNU
  -_. . .   )=.  = Library General Public License along with
    --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "xinevideowidget.h"
#include "frame.h"
#include "lib.h"
/* OPIE */
#include <opie2/odebug.h>
-using namespace Opie::Core;
+#include <qpe/global.h>
/* QT */
#include <qtextstream.h>
#include <qdir.h>
#include <qgfx_qws.h>
/* STD */
#include <assert.h>
#include <unistd.h>
typedef void (*display_xine_frame_t) (void *user_data, uint8_t* frame,
int width, int height,int bytes );
extern "C" {
xine_vo_driver_t* init_video_out_plugin( xine_t *xine, void* video, display_xine_frame_t, void * );
int null_is_showing_video( const xine_vo_driver_t* self );
void null_set_show_video( const xine_vo_driver_t* self, int show );
int null_is_fullscreen( const xine_vo_driver_t* self );
void null_set_fullscreen( const xine_vo_driver_t* self, int screen );
int null_is_scaling( const xine_vo_driver_t* self );
void null_set_scaling( const xine_vo_driver_t* self, int scale );
void null_set_gui_width( const xine_vo_driver_t* self, int width );
void null_set_gui_height( const xine_vo_driver_t* self, int height );
void null_set_mode( const xine_vo_driver_t* self, int depth, int rgb );
void null_set_videoGamma( const xine_vo_driver_t* self , int value );
void null_display_handler( const xine_vo_driver_t* self, display_xine_frame_t t, void* user_data );
void null_preload_decoders( xine_stream_t *stream );
}
using namespace XINE;
Lib::Lib( InitializationMode initMode, XineVideoWidget* widget )
{
m_initialized = false;
m_duringInitialization = false;
m_video = false;
m_wid = widget;
printf("Lib");
QString configPath = QDir::homeDirPath() + "/Settings/opiexine.cf";
// get the configuration
// not really OO, should be an extra class, later
if ( !QFile::exists(configPath) ) {
QFile f(configPath);
f.open(IO_WriteOnly);
QTextStream ts( &f );
ts << "misc.memcpy_method:glibc\n";
ts << "# uncomment if you experience double speed audio \n #audio.oss_sync_method:softsync\n";
ts << "codec.ffmpeg_pp_quality:3\n";
ts << "audio.num_buffers:50\n";
ts << "audio.size_buffers:4096\n";
ts << "video.num_buffers:20\n";
ts << "video.size_buffers:4096\n";
ts << "audio.out_num_audio_buf:16\n";
ts << "audio.out_size_audio_buf:8096\n";
ts << "audio.out_size_zero_buf:1024\n";
ts << "audio.passthrough_offset:0\n";
f.close();
}
if ( initMode == InitializeImmediately ) {
initialize();
m_initialized = true;
}
else
start();
}
void Lib::run()
{
odebug << "Lib::run() started" << oendl;
initialize();
m_initialized = true;
odebug << "Lib::run() finished" << oendl;
}
void Lib::initialize()
{
m_duringInitialization = true;
m_xine = xine_new( );
QString configPath = QDir::homeDirPath() + "/Settings/opiexine.cf";
xine_config_load( m_xine, QFile::encodeName( configPath ) );
xine_init( m_xine );
// allocate oss for sound
// and fb for framebuffer
m_audioOutput = xine_open_audio_driver( m_xine, "oss", NULL );
m_videoOutput = ::init_video_out_plugin( m_xine, NULL, xine_display_frame, this );
m_stream = xine_stream_new (m_xine, m_audioOutput, m_videoOutput );
if (m_wid != 0 )
setWidget( m_wid );
m_queue = xine_event_new_queue (m_stream);
xine_event_create_listener_thread (m_queue, xine_event_handler, this);
::null_preload_decoders( m_stream );
m_duringInitialization = false;
}
Lib::~Lib() {
assert( isRunning() == false );
assert( m_initialized );
// free( m_config );
xine_close( m_stream );
xine_event_dispose_queue( m_queue );
xine_dispose( m_stream );
xine_exit( m_xine );
/* FIXME either free or delete but valgrind bitches against both */
//free( m_videoOutput );
//delete m_audioOutput;
}
void Lib::resize ( const QSize &s ) {
assert( m_initialized || m_duringInitialization );
if ( s. width ( ) && s. height ( ) ) {
::null_set_gui_width( m_videoOutput, s. width() );
::null_set_gui_height( m_videoOutput, s. height() );
@@ -201,214 +201,224 @@ int Lib::play( const QString& fileName, int startPos, int start_time ) {
void Lib::stop() {
assert( m_initialized );
xine_stop( m_stream );
}
void Lib::pause( bool toggle ) {
assert( m_initialized );
xine_set_param( m_stream, XINE_PARAM_SPEED, toggle ? XINE_SPEED_PAUSE : XINE_SPEED_NORMAL );
}
int Lib::speed() const {
assert( m_initialized );
return xine_get_param ( m_stream, XINE_PARAM_SPEED );
}
void Lib::setSpeed( int speed ) {
assert( m_initialized );
xine_set_param ( m_stream, XINE_PARAM_SPEED, speed );
}
int Lib::status() const {
assert( m_initialized );
return xine_get_status( m_stream );
}
int Lib::currentPosition() const {
assert( m_initialized );
int pos, time, length;
xine_get_pos_length( m_stream, &pos, &time, &length );
return pos;
}
int Lib::currentTime() const {
assert( m_initialized );
int pos, time, length;
pos = time = length = 0;
if ( xine_get_pos_length( m_stream, &pos, &time, &length ) )
return time/1000;
else
return 0;
}
int Lib::length() const {
assert( m_initialized );
int pos, time, length;
/* dilb: patch to solve the wrong stream length reported to the GUI*/
int iRetVal=0, iTestLoop=0;
do
{
iRetVal = xine_get_pos_length( m_stream, &pos, &time, &length );
if (iRetVal)
{/* if the function didn't return 0, then pos, time and length are valid.*/
return length/1000;
}
/*don't poll too much*/
usleep(100000);
iTestLoop++;
}
while ( iTestLoop < 10 ); /* if after 1s, we still don't have any
valid stream, then return -1 (this value could be used to make the stream
unseekable, but it should never occur!! Mr. Murphy ? :) ) */
return -1;
}
bool Lib::isSeekable() const {
assert( m_initialized );
return xine_get_stream_info( m_stream, XINE_STREAM_INFO_SEEKABLE );
}
void Lib::seekTo( int time ) {
assert( m_initialized );
xine_play( m_stream, 0, time*1000 );
}
Frame Lib::currentFrame() const {
assert( m_initialized );
Frame frame;
return frame;
};
QString Lib::metaInfo( int number) const {
assert( m_initialized );
return xine_get_meta_info( m_stream, number );
}
int Lib::error() const {
assert( m_initialized );
return xine_get_error( m_stream );
};
void Lib::ensureInitialized()
{
if ( m_initialized )
return;
odebug << "waiting for initialization thread to finish" << oendl;
wait();
odebug << "initialization thread finished!" << oendl;
}
void Lib::setWidget( XineVideoWidget *widget )
{
m_wid = widget;
resize ( m_wid-> size ( ) );
::null_set_mode( m_videoOutput, qt_screen->depth(), qt_screen->pixelType() );
m_wid->repaint();
}
void Lib::receiveMessage( ThreadUtil::ChannelMessage *msg, SendType sendType )
{
assert( sendType == ThreadUtil::Channel::OneWay );
- handleXineEvent( msg->type() );
+ handleXineEvent( msg->type(), msg->data(), msg->msg() );
delete msg;
}
void Lib::handleXineEvent( const xine_event_t* t ) {
- send( new ThreadUtil::ChannelMessage( t->type ), OneWay );
+ int prog = -1; const char* name = 0;
+ if ( t->type == XINE_EVENT_PROGRESS ) {
+ xine_progress_data_t *pt = static_cast<xine_progress_data_t*>( t->data );
+ prog = pt->percent;
+ name = pt->description;
+ }
+
+ send( new ThreadUtil::ChannelMessage( t->type, prog, name ), OneWay );
}
-void Lib::handleXineEvent( int type ) {
+void Lib::handleXineEvent( int type, int data, const char* name ) {
assert( m_initialized );
if ( type == XINE_EVENT_UI_PLAYBACK_FINISHED ) {
emit stopped();
+ }else if ( type == XINE_EVENT_PROGRESS ) {
+ QString str = name == 0 ? QString::null : QString::fromUtf8( name );
+ Global::statusMessage( tr( "Progress: %1 %2" ).arg( name, data ) );;
}
}
void Lib::setShowVideo( bool video ) {
assert( m_initialized );
m_video = video;
::null_set_show_video( m_videoOutput, video );
}
bool Lib::isShowingVideo() const {
assert( m_initialized );
return ::null_is_showing_video( m_videoOutput );
}
bool Lib::hasVideo() const {
assert( m_initialized );
return xine_get_stream_info( m_stream, 18 );
}
void Lib::showVideoFullScreen( bool fullScreen ) {
assert( m_initialized );
::null_set_fullscreen( m_videoOutput, fullScreen );
}
bool Lib::isVideoFullScreen() const {
assert( m_initialized );
return ::null_is_fullscreen( m_videoOutput );
}
void Lib::setScaling( bool scale ) {
assert( m_initialized );
::null_set_scaling( m_videoOutput, scale );
}
void Lib::setGamma( int value ) {
assert( m_initialized );
::null_set_videoGamma( m_videoOutput, value );
}
bool Lib::isScaling() const {
assert( m_initialized );
return ::null_is_scaling( m_videoOutput );
}
void Lib::xine_event_handler( void* user_data, const xine_event_t* t ) {
( (Lib*)user_data)->handleXineEvent( t );
}
void Lib::xine_display_frame( void* user_data, uint8_t *frame,
int width, int height, int bytes ) {
( (Lib*)user_data)->drawFrame( frame, width, height, bytes );
}
void Lib::drawFrame( uint8_t* frame, int width, int height, int bytes ) {
assert( m_initialized );
if ( !m_video ) {
return;
}
assert( m_wid );
m_wid-> setVideoFrame ( frame, width, height, bytes );
}
diff --git a/noncore/multimedia/opieplayer2/lib.h b/noncore/multimedia/opieplayer2/lib.h
index 0ff14d0..dfddc2a 100644
--- a/noncore/multimedia/opieplayer2/lib.h
+++ b/noncore/multimedia/opieplayer2/lib.h
@@ -78,139 +78,139 @@ namespace XINE {
* Set the speed of the stream, if codec supports it
* XINE_SPEED_PAUSE 0
* XINE_SPEED_SLOW_4 1
* XINE_SPEED_SLOW_2 2
* XINE_SPEED_NORMAL 4
* XINE_SPEED_FAST_2 8
*XINE_SPEED_FAST_4 16
*/
void setSpeed( int speed = XINE_SPEED_PAUSE );
int status() const;
int currentPosition()const;
//in seconds
int currentTime()const;
int length() const;
bool isSeekable()const;
/**
* Whether or not to show video output
*/
void setShowVideo(bool video);
/**
* is we show video
*/
bool isShowingVideo() const;
/**
*
*/
void showVideoFullScreen( bool fullScreen );
/**
*
*/
bool isVideoFullScreen() const;
/**
* Get the meta info (like author etc) from the stream
* XINE_META_INFO_TITLE 0
* XINE_META_INFO_COMMENT 1
* XINE_META_INFO_ARTIST 2
* XINE_META_INFO_GENRE 3
* XINE_META_INFO_ALBUM 4
* XINE_META_INFO_YEAR 5
* XINE_META_INFO_VIDEOCODEC 6
* XINE_META_INFO_AUDIOCODEC 7
* XINE_META_INFO_SYSTEMLAYER 8
* XINE_META_INFO_INPUT_PLUGIN 9
*/
QString metaInfo( int number ) const;
/**
*
*/
bool isScaling() const;
/**
* seek to a position
*/
void seekTo( int time );
/**
*
* @return is media stream has video
*/
bool hasVideo() const;
/**
*
*/
void setScaling( bool );
/**
* Set the Gamma value for video output
* @param int the value between -100 and 100, 0 is original
*/
void setGamma( int );
/**
* test
*/
Frame currentFrame() const;
/**
* Returns the error code
* XINE_ERROR_NONE 0
* XINE_ERROR_NO_INPUT_PLUGIN 1
* XINE_ERROR_NO_DEMUXER_PLUGIN 2
* XINE_ERROR_DEMUXER_FAILED 3
*/
int error() const;
void ensureInitialized();
void setWidget( XineVideoWidget *widget );
signals:
void stopped();
void initialized();
protected:
virtual void receiveMessage( ThreadUtil::ChannelMessage *msg, SendType sendType );
virtual void run();
private:
void initialize();
int m_bytes_per_pixel;
bool m_initialized:1;
bool m_duringInitialization:1;
bool m_video:1;
XineVideoWidget *m_wid;
xine_t *m_xine;
xine_stream_t *m_stream;
xine_cfg_entry_t *m_config;
xine_vo_driver_t *m_videoOutput;
xine_ao_driver_t* m_audioOutput;
xine_event_queue_t *m_queue;
void handleXineEvent( const xine_event_t* t );
- void handleXineEvent( int type );
+ void handleXineEvent( int type, int data, const char* name );
void drawFrame( uint8_t* frame, int width, int height, int bytes );
// C -> C++ bridge for the event system
static void xine_event_handler( void* user_data, const xine_event_t* t);
static void xine_display_frame( void* user_data, uint8_t* frame ,
int width, int height, int bytes );
};
};
#endif
diff --git a/noncore/multimedia/opieplayer2/threadutil.cpp b/noncore/multimedia/opieplayer2/threadutil.cpp
index 6ed9853..b5cac61 100644
--- a/noncore/multimedia/opieplayer2/threadutil.cpp
+++ b/noncore/multimedia/opieplayer2/threadutil.cpp
@@ -1,395 +1,394 @@
/* This file is part of the KDE project
Copyright (C) 2002 Simon Hausmann <hausmann@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "threadutil.h"
#include <opie2/odebug.h>
#include <qsocketnotifier.h>
#include <pthread.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
using namespace ThreadUtil;
struct Mutex::Data
{
Data()
{
pthread_mutex_init( &mutex, 0 );
}
~Data()
{
pthread_mutex_destroy( &mutex );
}
pthread_mutex_t mutex;
};
Mutex::Mutex()
: d( new Data )
{
}
Mutex::~Mutex()
{
delete d;
}
void Mutex::lock()
{
pthread_mutex_lock( &d->mutex );
}
void Mutex::unlock()
{
pthread_mutex_unlock( &d->mutex );
}
bool Mutex::tryLock()
{
return pthread_mutex_trylock( &d->mutex ) == 0;
}
bool Mutex::isLocked()
{
if ( !tryLock() )
return true;
unlock();
return false;
}
struct WaitCondition::Data
{
Data()
{
int result = pthread_cond_init( &waitCondition, 0 );
assert( result == 0 );
}
~Data()
{
pthread_cond_destroy( &waitCondition );
}
pthread_cond_t waitCondition;
};
WaitCondition::WaitCondition()
: d( new Data )
{
}
WaitCondition::~WaitCondition()
{
delete d;
}
bool WaitCondition::wait()
{
Mutex m;
m.lock();
return wait( m );
}
bool WaitCondition::wait( Mutex &mutex )
{
return pthread_cond_wait( &d->waitCondition, &mutex.d->mutex );
}
void WaitCondition::wakeOne()
{
pthread_cond_signal( &d->waitCondition );
}
void WaitCondition::wakeAll()
{
pthread_cond_broadcast( &d->waitCondition );
}
struct Thread::Data
{
- Data() : isRunning( false )
+ Data() : isRunning( false )
{}
pthread_t self;
Mutex guard;
bool isRunning;
WaitCondition finishCondition;
Thread *thr;
void run() { thr->run(); }
};
extern "C"
{
static void terminate_thread( void *arg )
{
Thread::Data *data = ( Thread::Data* )arg;
assert( data );
AutoLock locker( data->guard );
data->isRunning = false;
data->finishCondition.wakeAll();
}
static void *start_thread( void *arg )
{
Thread::Data *data = ( Thread::Data* )arg;
pthread_cleanup_push( terminate_thread, data );
data->isRunning = true;
data->run();
pthread_cleanup_pop( true );
Thread::exit();
return 0; // never reached
}
}
Thread::Thread()
: d( new Data )
{
d->thr = this;
}
Thread::~Thread()
{
assert( d->isRunning == false );
delete d;
}
void Thread::start()
{
AutoLock lock( d->guard );
if ( d->isRunning ) {
- odebug << "ThreadUtil::Thread::start() called for running thread." << oendl;
+ odebug << "ThreadUtil::Thread::start() called for running thread." << oendl;
return;
}
pthread_attr_t attributes;
pthread_attr_init( &attributes );
pthread_attr_setscope( &attributes, PTHREAD_SCOPE_SYSTEM );
int err = pthread_create( &d->self, &attributes, start_thread, ( void* )d );
if ( err != 0 ) {
- odebug << "ThreadUtil::Thread::start() : can't create thread: " << strerror( err ) << "" << oendl;
+ odebug << "ThreadUtil::Thread::start() : can't create thread: " << strerror( err ) << "" << oendl;
pthread_attr_destroy( &attributes );
return;
}
pthread_attr_destroy( &attributes );
}
void Thread::terminate()
{
AutoLock lock( d->guard );
if ( !d->isRunning )
return;
pthread_cancel( d->self );
}
bool Thread::wait()
{
AutoLock lock( d->guard );
if ( !d->isRunning )
return true;
return d->finishCondition.wait( d->guard );
}
bool Thread::isRunning() const
{
AutoLock lock( d->guard );
return d->isRunning;
}
void Thread::exit()
{
pthread_exit( 0 );
}
OnewayNotifier::OnewayNotifier()
{
int fds[ 2 ];
pipe( fds );
m_readFd = fds[ 0 ];
m_writeFd = fds[ 1 ];
m_notifier = new QSocketNotifier( m_readFd, QSocketNotifier::Read );
connect( m_notifier, SIGNAL( activated(int) ),
this, SLOT( wakeUp() ) );
}
OnewayNotifier::~OnewayNotifier()
{
delete m_notifier;
::close( m_readFd );
::close( m_writeFd );
}
void OnewayNotifier::notify()
{
const char c = 42;
::write( m_writeFd, &c, 1 );
}
void OnewayNotifier::wakeUp()
{
char c = 0;
if ( ::read( m_readFd, &c, 1 ) != 1 )
return;
emit awake();
}
-ChannelMessage::ChannelMessage( int type )
- : m_type( type ), m_isCall( false ), m_replied( false ),
- m_inEventHandler( false )
-{
-}
+ChannelMessage::ChannelMessage( int type, int data, const char* msg )
+ : m_type( type ), m_data( data ), m_msg( msg ),
+ m_isCall( false ), m_replied( false ), m_inEventHandler( false )
+{}
ChannelMessage::~ChannelMessage()
{
if ( m_guard.isLocked() )
m_guard.unlock();
}
void ChannelMessage::reply()
{
if ( !m_isCall )
{
- odebug << "ChannelMessage::reply() - can't reply oneway message!" << oendl;
+ odebug << "ChannelMessage::reply() - can't reply oneway message!" << oendl;
return;
}
if ( m_inEventHandler )
{
m_replied = true;
return;
}
m_condition.wakeOne();
m_guard.unlock();
}
struct Channel::Private
{
Private()
{
ownerThread = pthread_self();
}
pthread_t ownerThread;
};
Channel::Channel( QObject *parent, const char *name )
: QObject( parent, name ), d( new Private )
{
connect( &m_notifier, SIGNAL( awake() ),
this, SLOT( deliver() ) );
}
Channel::~Channel()
{
delete d;
}
void Channel::send( ChannelMessage *message, SendType type )
{
if ( type == WaitForReply )
{
message->m_guard.lock();
message->m_isCall = true;
}
m_pendingMessagesGuard.lock();
m_pendingMessages << MsgEnvelope( type, message );
m_pendingMessagesGuard.unlock();
if ( d->ownerThread == pthread_self() ) {
assert( type != WaitForReply );
deliver();
}
else
m_notifier.notify();
//QThread::postEvent( this, new QCustomEvent( QEvent::User, envelope ) );
if ( type == WaitForReply )
{
message->m_condition.wait( message->m_guard );
message->m_guard.unlock();
}
}
void Channel::deliver()
{
AutoLock lock( m_pendingMessagesGuard );
while ( !m_pendingMessages.isEmpty() ) {
MsgEnvelope envelope = m_pendingMessages.first();
m_pendingMessages.remove( m_pendingMessages.begin() );
m_pendingMessagesGuard.unlock();
deliverOne( envelope );
m_pendingMessagesGuard.lock();
}
}
void Channel::deliverOne( const MsgEnvelope &envelope )
{
ChannelMessage *msg = envelope.msg;
assert( msg );
if ( envelope.type == WaitForReply )
{
msg->m_guard.lock();
msg->m_inEventHandler = true;
}
receiveMessage( msg, envelope.type );
if ( envelope.type == WaitForReply )
{
msg->m_inEventHandler = false;
if ( msg->m_replied )
{
msg->m_condition.wakeOne();
// this is a bit tricky. we unlock only when we reply.
// reply() does an unlock as well.
msg->m_guard.unlock();
}
}
}
/* vim: et sw=4 ts=4
*/
diff --git a/noncore/multimedia/opieplayer2/threadutil.h b/noncore/multimedia/opieplayer2/threadutil.h
index 2e83d3a..f97a18b 100644
--- a/noncore/multimedia/opieplayer2/threadutil.h
+++ b/noncore/multimedia/opieplayer2/threadutil.h
@@ -8,192 +8,196 @@
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef THREADUTIL_H
#define THREADUTIL_H
#include <qvaluelist.h>
#include <qobject.h>
#include <qguardedptr.h>
class QSocketNotifier;
namespace ThreadUtil
{
class Mutex
{
friend class WaitCondition;
public:
Mutex();
~Mutex();
void lock();
void unlock();
bool tryLock();
bool isLocked();
private:
struct Data;
Data *d;
Mutex( const Mutex & );
Mutex &operator=( const Mutex & );
};
class AutoLock
{
public:
AutoLock( Mutex &mutex ) : m_mutex( mutex ) { m_mutex.lock(); }
~AutoLock() { m_mutex.unlock(); }
Mutex *operator &() const { return &m_mutex; }
private:
Mutex &m_mutex;
};
class WaitCondition
{
public:
WaitCondition();
~WaitCondition();
bool wait();
bool wait( Mutex &mutex );
void wakeOne();
void wakeAll();
private:
struct Data;
Data *d;
WaitCondition( const WaitCondition & );
WaitCondition &operator=( const WaitCondition & );
};
class Thread
{
public:
struct Data;
friend struct Data;
Thread();
virtual ~Thread();
void start();
void terminate();
bool wait();
bool isRunning() const;
static void exit();
protected:
virtual void run() = 0;
private:
Data *d;
};
class OnewayNotifier : public QObject
{
Q_OBJECT
public:
OnewayNotifier();
~OnewayNotifier();
void notify();
signals:
void awake();
private slots:
void wakeUp();
private:
int m_readFd;
int m_writeFd;
QSocketNotifier *m_notifier;
};
class Channel;
class ChannelMessage
{
friend class Channel;
public:
- ChannelMessage( int type = -1 );
+ ChannelMessage( int type = -1, int data = -1, const char* msg = 0 );
virtual ~ChannelMessage();
int type() const { return m_type; }
+ int data() const { return m_data; }
+ const char* msg()const { return m_msg; }
void reply();
private:
ChannelMessage( const ChannelMessage & );
ChannelMessage &operator=( const ChannelMessage );
int m_type;
+ int m_data;
+ const char *m_msg;
bool m_isCall : 1;
bool m_replied : 1;
bool m_inEventHandler : 1;
Mutex m_guard;
WaitCondition m_condition;
};
class Channel : public QObject
{
Q_OBJECT
public:
enum SendType { OneWay, WaitForReply };
Channel( QObject *parent = 0, const char *name = 0 );
virtual ~Channel();
void send( ChannelMessage *message, SendType type );
protected:
virtual void receiveMessage( ChannelMessage *message, SendType type ) = 0;
private slots:
void deliver();
private:
OnewayNotifier m_notifier;
struct MsgEnvelope
{
MsgEnvelope() : type( OneWay ), msg( 0 ) {}
MsgEnvelope( SendType _type , ChannelMessage *_msg )
: type( _type ), msg( _msg ) {}
SendType type;
ChannelMessage *msg;
};
void deliverOne( const MsgEnvelope &envelope );
typedef QValueList<MsgEnvelope> MsgEnvelopeList;
MsgEnvelopeList m_pendingMessages;
Mutex m_pendingMessagesGuard;
struct Private;
Private *d;
};
}
#endif // THREADUTIL_H
/* vim: et sw=4 ts=4
*/