Index: /trunk/src/kernel/qsound_pm.cpp
===================================================================
--- /trunk/src/kernel/qsound_pm.cpp	(revision 46)
+++ /trunk/src/kernel/qsound_pm.cpp	(revision 46)
@@ -0,0 +1,641 @@
+/****************************************************************************
+** $Id$
+**
+** Implementation of QSound class and QAuServer internal class
+**
+** Copyright (C) 1999-2000 Trolltech AS.  All rights reserved.
+** Copyright (C) 2005 netlabs.org.  OS/2 Version.
+**
+** This file is part of the kernel module of the Qt GUI Toolkit.
+**
+** This file may be distributed under the terms of the Q Public License
+** as defined by Trolltech AS of Norway and appearing in the file
+** LICENSE.QPL included in the packaging of this file.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+**   information about Qt Commercial License Agreements.
+** See http://www.trolltech.com/qpl/ for QPL licensing information.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "qsound.h"
+
+#ifndef QT_NO_SOUND
+
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include "qguardedptr.h"
+
+#include <qintdict.h>
+#include <qfile.h>
+#include <qlibrary.h>
+
+#include <qt_os2.h>
+
+//#define QT_QSOUND_DEBUG
+
+// local QT_DEBUG override, must be placed *after* all includes
+#if defined(QT_QSOUND_DEBUG) && !defined(QT_DEBUG)
+#   define QT_DEBUG
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+//#define INCL_MCIOS2
+//#define INCL_MMIOOS2
+//#include <os2me.h>
+
+// The below definitions are stolen from the OS/2 Toolkit 4.5 headers
+// to avoid the requirement of having the Toolkit installed when building Qt
+// and let it directly link to mdm.dll and mmio.dll.
+
+typedef ULONG HMMIO;                  /* Handle to an MMIO object*/
+
+typedef ULONG  FOURCC;
+
+typedef LONG (APIENTRY MMIOPROC)                    /*  Format must       */
+                                ( PVOID pmmioinfo,  /*  appear this       */
+                                  USHORT usMsg,     /*  way for h2inc     */
+                                  LONG lParam1,     /*  to work properly. */
+                                  LONG lParam2 );
+
+typedef MMIOPROC FAR *PMMIOPROC;
+
+typedef struct _MMIOINFO {       /* mmioinfo                    */
+   ULONG       ulFlags;          /* Open flags                  */
+   FOURCC      fccIOProc;        /* FOURCC of the IOProc to use */
+   PMMIOPROC   pIOProc;          /* Function Pointer to IOProc to use */
+   ULONG       ulErrorRet;       /* Extended Error return code  */
+   LONG        cchBuffer;        /* I/O buff size (if used), Fsize if MEM */
+   PCHAR       pchBuffer;        /* Start of I/O buff           */
+   PCHAR       pchNext;          /* Next char to read or write in buff */
+   PCHAR       pchEndRead;       /* Last char in buff can be read + 1  */
+   PCHAR       pchEndWrite;      /* Last char in buff can be written + 1 */
+   LONG        lBufOffset;       /* Offset in buff to pchNext */
+   LONG        lDiskOffset;      /* Disk offset in file       */
+   ULONG       aulInfo[4];       /* IOProc specific fields    */
+   LONG        lLogicalFilePos;  /* Actual file position, buffered or not */
+   ULONG       ulTranslate;      /* Translation field         */
+   FOURCC      fccChildIOProc;   /* FOURCC of Child IOProc    */
+   PVOID       pExtraInfoStruct; /* Pointer to a structure of related data */
+   HMMIO       hmmio;            /* Handle to media element   */
+   } MMIOINFO;
+
+typedef MMIOINFO FAR *PMMIOINFO;
+   
+typedef struct _WAVE_HEADER {                /* waveheader          */
+   USHORT          usFormatTag;              /* Type of wave format */
+   USHORT          usChannels;               /* Number of channels  */
+   ULONG           ulSamplesPerSec;          /* Sampling rate       */
+   ULONG           ulAvgBytesPerSec;         /* Avg bytes per sec   */
+   USHORT          usBlockAlign;             /* Block Alignment in bytes */
+   USHORT          usBitsPerSample;          /* Bits per sample     */
+   } WAVE_HEADER;
+
+typedef struct _XWAV_HEADERINFO {            /* xwaveheader info        */
+   ULONG           ulAudioLengthInMS;        /* Audio data in millisecs */
+   ULONG           ulAudioLengthInBytes;     /* Audio data in bytes     */
+   PVOID           pAdditionalInformation;
+   } XWAV_HEADERINFO;
+
+typedef struct _MMXWAV_HEADER {              /* mmxwaveheader            */
+   WAVE_HEADER     WAVEHeader;               /* Per RIFF WAVE Definition */
+   XWAV_HEADERINFO XWAVHeaderInfo;           /* Extended wave definition */
+   } MMXWAV_HEADER;
+
+typedef struct _MMAUDIOHEADER {              /* mmaudioheader   */
+   ULONG           ulHeaderLength;           /* Length in Bytes */
+   ULONG           ulContentType;            /* Image content   */
+   ULONG           ulMediaType;              /* Media Type      */
+   MMXWAV_HEADER   mmXWAVHeader;             /* header          */
+   } MMAUDIOHEADER;
+
+typedef MMAUDIOHEADER *PMMAUDIOHEADER;
+
+#define MCI_OPEN_TYPE_ID                    0x00001000L
+#define MCI_OPEN_SHAREABLE                  0x00002000L
+#define MCI_OPEN_MMIO                       0x00004000L
+
+typedef struct _MCI_OPEN_PARMS  
+{
+   HWND    hwndCallback;    /* PM window handle for MCI notify message */
+   USHORT  usDeviceID;      /* Device ID returned to user              */
+   USHORT  usReserved0;     /* Reserved                                */
+   PSZ     pszDeviceType;   /* Device name from SYSTEM.INI             */
+   PSZ     pszElementName;  /* Typically a file name or NULL           */
+   PSZ     pszAlias;        /* Optional device alias                   */
+} MCI_OPEN_PARMS;
+typedef MCI_OPEN_PARMS   *PMCI_OPEN_PARMS;
+
+typedef struct _MCI_PLAY_PARMS  
+{
+   HWND    hwndCallback;    /* PM window handle for MCI notify message */
+   ULONG   ulFrom;          /* Play from this position                 */
+   ULONG   ulTo;            /* Play to this position                   */
+} MCI_PLAY_PARMS;
+typedef MCI_PLAY_PARMS   *PMCI_PLAY_PARMS;
+
+#define MMIO_TRANSLATEDATA       0x00000001L /* Translation */
+#define MMIO_TRANSLATEHEADER     0x00000002L /* Translation */
+
+#define MMIO_READ       0x00000004L       /* Open */
+
+#define MMIO_SUCCESS                    0L
+
+#define MMIO_MEDIATYPE_AUDIO        0x00000002L  /* Audio media */
+
+#define MCI_DEVTYPE_WAVEFORM_AUDIO      7
+
+#define MCI_NOTIFY                          0x00000001L
+#define MCI_WAIT                            0x00000002L
+#define MCI_FROM                            0x00000004L
+
+#define MCI_OPEN                        1
+#define MCI_CLOSE                       2
+#define MCI_PLAY                        4
+#define MCI_STOP                        6
+
+#define MCI_NOTIFY_SUCCESSFUL               0x0000
+
+#define MM_MCINOTIFY                        0x0500
+
+#define MCIERR_SUCCESS                   0
+
+// functions resolved by mmio.dll
+
+typedef
+USHORT (APIENTRY *mmioClose_T)( HMMIO hmmio,
+                                USHORT usFlags );
+typedef
+HMMIO (APIENTRY *mmioOpen_T)( PSZ pszFileName,
+                              PMMIOINFO pmmioinfo,
+                              ULONG ulOpenFlags );
+
+typedef
+ULONG (APIENTRY *mmioGetHeader_T)( HMMIO hmmio,
+                                   PVOID pHeader,
+                                   LONG lHeaderLength,
+                                   PLONG plBytesRead,
+                                   ULONG ulReserved,
+                                   ULONG ulFlags );
+
+static mmioClose_T mmioClose = 0;
+static mmioOpen_T mmioOpen = 0;
+static mmioGetHeader_T mmioGetHeader = 0;
+
+// functions resolved by mdm.dll
+
+typedef
+ULONG (APIENTRY *mciSendCommand_T)( USHORT   usDeviceID,
+                                    USHORT   usMessage,
+                                    ULONG    ulParam1,
+                                    PVOID    pParam2,
+                                    USHORT   usUserParm );
+
+static mciSendCommand_T mciSendCommand = 0;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class QAuBucketMMPM;
+
+class QAuServerMMPM : public QAuServer {
+    
+    Q_OBJECT
+
+public:
+
+    QAuServerMMPM( QObject* parent );
+    ~QAuServerMMPM();
+
+    void init( QSound *s );
+    void play( const QString &filename );
+    void play( QSound *s );
+    void stop( QSound *s );
+    bool okay();
+
+private slots:
+
+    void aboutToQuit() { isAboutToQuit = TRUE; } 
+    
+private:    
+
+    HWND hwnd;
+    bool isOk;
+    bool isAboutToQuit;
+    
+    QLibrary mdmLib;
+    QLibrary mmioLib;
+    
+    QIntDict< QAuBucketMMPM > buckets;
+    
+    static const char *ClassName;
+    static MRESULT EXPENTRY WindowProc( HWND hwnd, ULONG msg,
+                                        MPARAM mp1, MPARAM mp2 );
+
+    friend class QAuBucketMMPM;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class QAuBucketMMPM : public QAuBucket {
+    
+public:
+
+    QAuBucketMMPM( QAuServerMMPM *server, QSound *sound );
+    QAuBucketMMPM( QAuServerMMPM *server, const QString &soundFile );
+    ~QAuBucketMMPM();
+
+    void play();
+    void stop();
+    bool okay() { return fileHandle != NULLHANDLE && deviceId != 0; } 
+    
+    QSound *sound() { return snd; }
+    
+    static const char *ClassName;
+    
+private:
+
+    void init( const QString &fileName );
+
+    QAuServerMMPM *srv;
+    QSound *snd;
+    
+#if defined(QT_DEBUG)
+    QCString fileName;
+#endif
+
+    HMMIO fileHandle;
+    USHORT deviceId;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+QAuBucketMMPM::QAuBucketMMPM( QAuServerMMPM *server, QSound *sound ) :
+    srv( server ), snd( sound ), fileHandle( NULLHANDLE ), deviceId( 0 )
+{
+    Q_ASSERT( srv );
+    Q_ASSERT( snd );
+    
+    init( snd->fileName() );
+    if ( okay() )
+        srv->buckets.insert( deviceId, this );
+}
+
+QAuBucketMMPM::QAuBucketMMPM( QAuServerMMPM *server, const QString &fileName ) :
+    srv( server ), snd( NULL ), fileHandle( NULLHANDLE ), deviceId( 0 )
+{
+    Q_ASSERT( srv );
+    
+    init( fileName );
+    if ( okay() )
+        srv->buckets.insert( deviceId, this );
+}
+
+void QAuBucketMMPM::init( const QString &soundFile )
+{
+#if !defined(QT_DEBUG)
+    QCString
+#endif    
+    fileName = QFile::encodeName( soundFile );
+    
+    MMIOINFO mmioinfo = { 0 };
+    mmioinfo.ulTranslate = MMIO_TRANSLATEDATA | MMIO_TRANSLATEHEADER;
+    fileHandle = mmioOpen( fileName.data(), &mmioinfo, MMIO_READ );
+    if ( fileHandle == NULLHANDLE ) {
+#if defined(QT_DEBUG)
+        qDebug( "QAuBucketMMPM: falied to open sound file [%s]",
+                fileName.data() );
+#endif
+        return;
+    }
+    
+    MMAUDIOHEADER mmah;
+    LONG bytesRead = 0;
+    ULONG rc = mmioGetHeader( fileHandle, &mmah, sizeof(mmah), &bytesRead, 0, 0 );
+    if ( rc != MMIO_SUCCESS || mmah.ulMediaType != MMIO_MEDIATYPE_AUDIO ) {
+#if defined(QT_DEBUG)
+        qDebug( "QAuBucketMMPM: [%s] is not a sound file or "
+                "has an unsupported format (rc=%04ld)", fileName.data(), rc );
+#endif
+        return;
+    }
+    
+    MCI_OPEN_PARMS openParams = { 0 };
+    openParams.pszDeviceType = (PSZ) MAKEULONG( MCI_DEVTYPE_WAVEFORM_AUDIO, 0 );
+    openParams.pszElementName = (PSZ) fileHandle;
+    rc = mciSendCommand( 0, MCI_OPEN, MCI_WAIT | MCI_OPEN_MMIO |
+                                      MCI_OPEN_SHAREABLE | MCI_OPEN_TYPE_ID,
+                         &openParams, 0 );                
+    if ( rc != MCIERR_SUCCESS ) {
+#if defined(QT_DEBUG)
+        qDebug( "QAuBucketMMPM: failed to open a device for sound file [%s] "
+                "(rc=%04ld)", fileName.data(), rc );
+#endif
+        return;
+    }
+    
+    deviceId = openParams.usDeviceID;
+}
+
+QAuBucketMMPM::~QAuBucketMMPM()
+{
+#if defined(QT_QSOUND_DEBUG)    
+    qDebug( "~QAuBucketMMPM(): this=%p", this );
+#endif    
+
+    if ( okay() )
+        srv->buckets.remove( deviceId );
+
+    if ( okay() && snd && !srv->isAboutToQuit ) {
+        // in order to guarantee that the device is closed only after all
+        // messages for the particular device ID are delivered to WindowProc()
+        // and that no other device is assigned the same ID until then, we post
+        // a special message containing fileHandle and deviceId to be closed 
+        WinPostMsg( srv->hwnd, WM_USER,
+                    MPFROMLONG( fileHandle ), MPFROMSHORT( deviceId ) );
+    } else {
+        if ( deviceId != 0 )
+            mciSendCommand( deviceId, MCI_CLOSE, MCI_WAIT, NULL, 0 );                
+        if ( fileHandle != NULLHANDLE )            
+            mmioClose( fileHandle, 0 );
+    }
+}
+
+void QAuBucketMMPM::play()
+{
+    MCI_PLAY_PARMS playParams = { 0 };
+    playParams.hwndCallback = srv->hwnd;
+    playParams.ulFrom = 0; // always play from the beginning
+    
+    ULONG rc = mciSendCommand( deviceId, MCI_PLAY, MCI_NOTIFY | MCI_FROM,
+                               &playParams, 0 );                
+
+    if ( rc != MCIERR_SUCCESS ) {
+#if defined(QT_DEBUG)
+        qDebug( "QAuBucketMMPM: failed to play sound file [%s] (rc=%04ld)",
+                fileName.data(), rc );
+#endif
+    }
+}
+
+void QAuBucketMMPM::stop() 
+{
+    ULONG rc = mciSendCommand( deviceId, MCI_STOP, MCI_WAIT, NULL, 0 );                
+
+    if ( rc != MCIERR_SUCCESS ) {
+#if defined(QT_DEBUG)
+        qDebug( "QAuBucketMMPM: failed to stop sound file [%s] (rc=%04ld)",
+                fileName.data(), rc );
+#endif
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+const char *QAuServerMMPM::ClassName = "QAuServerMMPM";
+
+QAuServerMMPM::QAuServerMMPM( QObject* parent ) :
+    QAuServer( parent, "OS/2 MMPM Audio Server" ),
+    isOk( FALSE ), isAboutToQuit( FALSE ),
+    mdmLib( "mdm.dll" ), mmioLib( "mmio.dll" )
+{
+    WinRegisterClass( 0, ClassName, WindowProc, 0, sizeof(PVOID) );
+    
+    hwnd = WinCreateWindow( HWND_OBJECT, ClassName, NULL, 0, 0, 0, 0, 0,
+                            NULL, HWND_BOTTOM, 0,
+                            this, NULL );
+
+    if ( hwnd == NULLHANDLE ) {
+#if defined(QT_DEBUG)
+        qSystemWarning( "QAuServerMMPM: falied to create an object window" );
+#endif
+        return;
+    }
+
+    // resolve functions
+    mmioClose = (mmioClose_T) mmioLib.resolve( "mmioClose" );
+    mmioOpen = (mmioOpen_T) mmioLib.resolve( "mmioOpen" );
+    mmioGetHeader = (mmioGetHeader_T) mmioLib.resolve( "mmioGetHeader" );
+    mciSendCommand = (mciSendCommand_T) mdmLib.resolve( "mciSendCommand" );
+    if ( !mmioClose || !mmioGetHeader || !mmioOpen || !mciSendCommand ) {
+#if defined(QT_DEBUG)
+        qDebug( "QAuServerMMPM: failed to resolve MMPM system functions" );
+#endif
+        return;
+    }
+    
+    // try to open the default waveaudio device to ensure it exists
+    MCI_OPEN_PARMS openParams = { 0 };
+    openParams.pszDeviceType = (PSZ) MAKEULONG( MCI_DEVTYPE_WAVEFORM_AUDIO, 0 );
+    ULONG rc = mciSendCommand( 0, MCI_OPEN, MCI_WAIT |
+                                            MCI_OPEN_SHAREABLE | MCI_OPEN_TYPE_ID,
+                               &openParams, 0 );                
+    if ( rc != MCIERR_SUCCESS ) {
+#if defined(QT_DEBUG)
+        qDebug( "QAuServerMMPM: failed to open the default waveaudio device "
+                "(rc=%04ld)", rc );
+#endif
+        return;
+    }
+    
+    // close the device opened above
+    mciSendCommand( openParams.usDeviceID, MCI_CLOSE, MCI_WAIT, NULL, 0 );                
+    
+    connect( qApp, SIGNAL( aboutToQuit() ), SLOT( aboutToQuit() ) );
+    
+    isOk = TRUE;
+}
+
+QAuServerMMPM::~QAuServerMMPM()
+{
+#if defined(QT_QSOUND_DEBUG)    
+    qDebug( "~QAuServerMMPM(): buckets left: %d", buckets.count() );
+#endif
+
+    // deassociate all remaining buckets from QSound objects and delete them
+    // (note that deleting a bucket will remove it from the dictionary, which
+    // in turn will update all dictionary iterators to point to the next item,
+    // so there is no iterator increment statement below) 
+    QIntDictIterator< QAuBucketMMPM > it( buckets );
+    while ( it.current() ) {
+        QSound *s = it.current()->sound();
+        if ( s ) {
+            // the below call will delete the associated bucket
+            setBucket ( s, 0 );
+        } else {
+            delete it.current();
+        }
+    }
+    
+    Q_ASSERT( buckets.count() == 0 );
+    
+    mmioClose = 0;
+    mmioOpen = 0;
+    mmioGetHeader = 0;
+    mciSendCommand = 0;
+}
+
+void QAuServerMMPM::init( QSound *s )
+{
+    Q_ASSERT( s );
+    
+    if ( !okay() )
+        return;
+    
+    QAuBucketMMPM *b = new QAuBucketMMPM( this, s );
+    if ( b->okay() ) {
+        setBucket( s, b );
+#if defined(QT_QSOUND_DEBUG)    
+        qDebug( "init(): bucket=%p sound=[%s]", b, s->fileName().latin1() );
+#endif        
+    } else {
+        setBucket( s, 0 );
+        // b is deleted in setBucket()
+    }
+}
+
+void QAuServerMMPM::play( const QString &filename )
+{
+    if ( !okay() )
+        return;
+    
+    QAuBucketMMPM *b = new QAuBucketMMPM( this, filename );
+    if ( b->okay() ) {
+#if defined(QT_QSOUND_DEBUG)    
+        qDebug( "play(QString): bucket=%p sound=[%s]", b, filename.latin1() );
+#endif        
+        b->play();
+        // b will be deleted in WindowProc()
+    } else {
+        delete b;
+    }
+}
+
+void QAuServerMMPM::play( QSound *s )
+{
+    Q_ASSERT( s );
+
+    if ( !okay() || !isRelevant( s ) ) {
+        // no MMPM is available or a wrong sound, just decrease loops to zero
+        while ( decLoop( s ) > 0 ) ;
+        return;
+    }
+    
+    QAuBucketMMPM *b = static_cast< QAuBucketMMPM * >( bucket( s ) );
+    if ( b ) {
+#if defined(QT_QSOUND_DEBUG)    
+        qDebug( "play(QSound): bucket=%p sound=[%s]", b, s->fileName().latin1() );
+#endif        
+        b->play();
+    } else {
+        // failed to create a bucket in init(), just decrease loops to zero
+        while ( decLoop( s ) > 0 ) ;
+    }
+}
+
+void QAuServerMMPM::stop( QSound *s )
+{
+    Q_ASSERT( s );
+
+    if ( !okay() || !isRelevant( s ) )
+        return;
+    
+    QAuBucketMMPM *b = static_cast< QAuBucketMMPM * >( bucket( s ) );
+    if ( b )
+        b->stop();
+}
+
+bool QAuServerMMPM::okay()
+{
+    return isOk;
+}
+
+MRESULT EXPENTRY QAuServerMMPM::WindowProc( HWND hwnd, ULONG msg,
+                                            MPARAM mp1, MPARAM mp2 )
+{
+    QAuServerMMPM * that =
+        static_cast< QAuServerMMPM * >( WinQueryWindowPtr( hwnd, 0 ) );
+    
+    switch ( msg ) {
+        case WM_CREATE: {
+            QAuServerMMPM * that = static_cast< QAuServerMMPM * >( mp1 );
+            if ( !that )
+                return (MRESULT) TRUE;
+            WinSetWindowPtr( hwnd, 0, that );
+            return (MRESULT) FALSE;
+        }
+        case WM_DESTROY: {
+            return 0;
+        }
+        case MM_MCINOTIFY: {
+            if ( !that )
+                return 0;
+
+            USHORT code = SHORT1FROMMP( mp1 );
+            USHORT deviceId = SHORT1FROMMP( mp2 );
+#if defined(QT_QSOUND_DEBUG)            
+            qDebug( "MM_MCINOTIFY: code=%04hX deviceId=%04hX", code, deviceId );
+#endif            
+
+            QAuBucketMMPM *b = that->buckets.find( deviceId );
+            if ( !b )
+                return 0;
+#if defined(QT_QSOUND_DEBUG)            
+            qDebug( "MM_MCINOTIFY: bucket=%p", b );
+#endif            
+            
+            QSound *sound = b->sound();
+            if ( sound ) {
+                if ( code == MCI_NOTIFY_SUCCESSFUL ) {
+                    // play the sound until there are no loops left
+                    int loopsLeft = that->decLoop( sound );
+                    if ( loopsLeft != 0 )
+                        b->play();
+                }
+            } else {
+                // delete QSound'less bucket when finished or stopped playing
+                delete b;
+            }
+
+            return 0;
+        }
+        case WM_USER: {
+            HMMIO fileHandle = LONGFROMMP( mp1 );
+            USHORT deviceId = SHORT1FROMMP( mp2 );
+#if defined(QT_QSOUND_DEBUG)            
+            qDebug( "WM_USER: deviceId=%04hX", deviceId );
+#endif            
+            // there should be no buckets with the given ID at this point
+            Q_ASSERT( that->buckets.find( deviceId ) == 0 );
+            mciSendCommand( deviceId, MCI_CLOSE, MCI_WAIT, NULL, 0 );                
+            mmioClose( fileHandle, 0 );
+        }
+    }
+
+    return 0;
+}
+
+QAuServer *qt_new_audio_server()
+{
+    return new QAuServerMMPM( qApp );
+}
+
+#include "qsound_pm.moc"
+
+#endif // QT_NO_SOUND
Index: /trunk/src/kernel/qt_kernel.pri
===================================================================
--- /trunk/src/kernel/qt_kernel.pri	(revision 45)
+++ /trunk/src/kernel/qt_kernel.pri	(revision 46)
@@ -136,4 +136,5 @@
 		  $$KERNEL_CPP/qpainter_pm.cpp \
 		  $$KERNEL_CPP/qregion_pm.cpp \
+		  $$KERNEL_CPP/qsound_pm.cpp \
 		  $$KERNEL_CPP/qthread_pm.cpp \
 		  $$KERNEL_CPP/qwidget_pm.cpp \
@@ -285,10 +286,8 @@
 		$$KERNEL_H/qpolygonscanner.h \
 		$$KERNEL_H/qprinter.h \
-		$$KERNEL_H/qsessionmanager.h \
-		$$KERNEL_H/qsound.h
+		$$KERNEL_H/qsessionmanager.h
 
 	SOURCES -= \
 		$$KERNEL_CPP/qpolygonscanner.cpp \
-		$$KERNEL_CPP/qprinter.cpp \
-		$$KERNEL_CPP/qsound.cpp
+		$$KERNEL_CPP/qprinter.cpp
 }
