/**********************************************************************
** Copyright (C) 2000 Trolltech AS.  All rights reserved.
**
** This file is part of Qtopia Environment.
**
** 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.
**
** 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/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/

#include <qpe/resource.h>
#include <qpe/sound.h>
#include <qpe/qcopenvelope_qws.h>

#include <qsound.h>
#include <qfile.h>

#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>

#include "config.h"
#include <qmessagebox.h>
#ifndef QT_NO_SOUND
static int WAVsoundDuration(const QString& filename)
{
    // bad solution

    // most of this is copied from qsoundqss.cpp

    QFile input(filename);
    if ( !input.open(IO_ReadOnly) )
	return 0;

    struct QRiffChunk {
	char id[4];
	Q_UINT32 size;
	char data[4/*size*/];
    } chunk;

    struct {
        Q_INT16 formatTag;
        Q_INT16 channels;
        Q_INT32 samplesPerSec;
        Q_INT32 avgBytesPerSec;
        Q_INT16 blockAlign;
        Q_INT16 wBitsPerSample;
    } chunkdata;

    int total = 0;

    while(1) {
	// Keep reading chunks...
	const int n = sizeof(chunk)-sizeof(chunk.data);
	if ( input.readBlock((char*)&chunk,n) != n )
	    break;
	if ( qstrncmp(chunk.id,"data",4) == 0 ) {
	    total += chunkdata.avgBytesPerSec ?
		chunk.size * 1000 / chunkdata.avgBytesPerSec : 0;
//qDebug("%d bytes of PCM (%dms)", chunk.size,chunkdata.avgBytesPerSec ?  chunk.size * 1000 / chunkdata.avgBytesPerSec : 0);
	    input.at(input.at()+chunk.size-4);
	} else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) {
	    char d[4];
	    if ( input.readBlock(d,4) != 4 )
		return 0;
	    if ( qstrncmp(d,"WAVE",4) != 0 ) {
		// skip
//qDebug("skip %.4s RIFF chunk",d);
		if ( chunk.size < 10000000 )
		    (void)input.at(input.at()+chunk.size-4);
	    }
	} else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) {
	    if ( input.readBlock((char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) )
		return 0;
#define WAVE_FORMAT_PCM 1
	    if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) {
		//qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag);
		return 0;
	    }
	} else {
//qDebug("skip %.4s chunk",chunk.id);
	    // ignored chunk
	    if ( chunk.size < 10000000 )
		(void)input.at(input.at()+chunk.size);
	}
    }

//qDebug("%dms",total);
    return total;
}

class SoundData : public QSound {
public:
	SoundData ( const QString& name ) :
		QSound ( Resource::findSound ( name )),
		filename ( Resource::findSound ( name ))
	{
		loopsleft=0;    
		ms = WAVsoundDuration(filename);
	}

	void playLoop ( int loopcnt = -1 )
	{
		// needs server support
		loopsleft = loopcnt;

		if ( ms )
			startTimer ( ms > 50 ? ms-50 : 0 ); // 50 for latency
		play ( );
	}

    void timerEvent ( QTimerEvent *e )
    {
		if ( loopsleft >= 0 ) {
			if ( --loopsleft <= 0 ) {
				killTimer ( e-> timerId ( ));
				loopsleft = 0;
				return;
			}
		}	    
		play();
	}
    
	bool isFinished ( ) const
	{
		return ( loopsleft == 0 );
	}

private:
	QString filename;
	int loopsleft;
	int ms;
};

#endif

Sound::Sound(const QString& name)
{
#ifndef QT_NO_SOUND
    d = new SoundData(name);
#endif
}

Sound::~Sound()
{
#ifndef QT_NO_SOUND
    delete d;
#endif
}

void Sound::play()
{
#ifndef QT_NO_SOUND
    d->playLoop(1);
#endif
}

void Sound::playLoop()
{
#ifndef QT_NO_SOUND
    d->killTimers();
    d->playLoop();
#endif
}

void Sound::stop()
{
#ifndef QT_NO_SOUND
    d->killTimers();
#endif
}

bool Sound::isFinished() const
{
#ifndef QT_NO_SOUND
    return d->isFinished();
#else
	return true;
#endif
}

void Sound::soundAlarm()
{
#ifndef QT_NO_COP
    QCopEnvelope( "QPE/TaskBar", "soundAlarm()" );
#endif    
}