author | llornkcor <llornkcor> | 2003-04-04 03:03:38 (UTC) |
---|---|---|
committer | llornkcor <llornkcor> | 2003-04-04 03:03:38 (UTC) |
commit | ce6388c4f44e9e76342a338954fff598372e06f0 (patch) (side-by-side diff) | |
tree | 895c202343fc394335e6effdb535ccb864a587d3 | |
parent | 487971af0c1b70babcc39fd549dc0d8142cd4865 (diff) | |
download | opie-ce6388c4f44e9e76342a338954fff598372e06f0.zip opie-ce6388c4f44e9e76342a338954fff598372e06f0.tar.gz opie-ce6388c4f44e9e76342a338954fff598372e06f0.tar.bz2 |
bitches owe me money. initial commit. zaurus/vercel has sound drivers that doesnt actually change samplerates, so this kinda has problems, currently
-rw-r--r-- | noncore/multimedia/opierec/adpcm.c | 252 | ||||
-rw-r--r-- | noncore/multimedia/opierec/adpcm.h | 19 | ||||
-rw-r--r-- | noncore/multimedia/opierec/device.cpp | 341 | ||||
-rw-r--r-- | noncore/multimedia/opierec/device.h | 45 | ||||
-rw-r--r-- | noncore/multimedia/opierec/helpwindow.cpp | 219 | ||||
-rw-r--r-- | noncore/multimedia/opierec/helpwindow.h | 62 | ||||
-rw-r--r-- | noncore/multimedia/opierec/main.cpp | 22 | ||||
-rw-r--r-- | noncore/multimedia/opierec/opierec-control | 10 | ||||
-rw-r--r-- | noncore/multimedia/opierec/opierec.pro | 12 | ||||
-rw-r--r-- | noncore/multimedia/opierec/pixmaps.h | 294 | ||||
-rw-r--r-- | noncore/multimedia/opierec/qtrec.cpp | 2270 | ||||
-rw-r--r-- | noncore/multimedia/opierec/qtrec.h | 185 | ||||
-rw-r--r-- | noncore/multimedia/opierec/wavFile.cpp | 303 | ||||
-rw-r--r-- | noncore/multimedia/opierec/wavFile.h | 56 |
14 files changed, 4090 insertions, 0 deletions
diff --git a/noncore/multimedia/opierec/adpcm.c b/noncore/multimedia/opierec/adpcm.c new file mode 100644 index 0000000..716fefd --- a/dev/null +++ b/noncore/multimedia/opierec/adpcm.c @@ -0,0 +1,252 @@ +/*********************************************************** +Copyright 1992 by Stichting Mathematisch Centrum, Amsterdam, The +Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + +/* +** Intel/DVI ADPCM coder/decoder. +** +** The algorithm for this coder was taken from the IMA Compatability Project +** proceedings, Vol 2, Number 2; May 1992. +** +** Version 1.2, 18-Dec-92. +** +** Change log: +** - Fixed a stupid bug, where the delta was computed as +** stepsize*code/4 in stead of stepsize*(code+0.5)/4. +** - There was an off-by-one error causing it to pick +** an incorrect delta once in a blue moon. +** - The NODIVMUL define has been removed. Computations are now always done +** using shifts, adds and subtracts. It turned out that, because the standard +** is defined using shift/add/subtract, you needed bits of fixup code +** (because the div/mul simulation using shift/add/sub made some rounding +** errors that real div/mul don't make) and all together the resultant code +** ran slower than just using the shifts all the time. +** - Changed some of the variable names to be more meaningful. +*/ + +#include "adpcm.h" +#include <stdio.h> /*DBG*/ + +#ifndef __STDC__ +#define signed +#endif + +/* Intel ADPCM step variation table */ +static int indexTable[16] = { + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8, +}; + +static int stepsizeTable[89] = { + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 +}; + +void +adpcm_coder(indata, outdata, len, state) + short indata[]; + char outdata[]; + int len; + struct adpcm_state *state; +{ + short *inp; /* Input buffer pointer */ + signed char *outp; /* output buffer pointer */ + int val; /* Current input sample value */ + int sign; /* Current adpcm sign bit */ + int delta; /* Current adpcm output value */ + int diff; /* Difference between val and valprev */ + int step; /* Stepsize */ + int valpred; /* Predicted output value */ + int vpdiff; /* Current change to valpred */ + int index; /* Current step change index */ + int outputbuffer=0; /* place to keep previous 4-bit value */ + int bufferstep; /* toggle between outputbuffer/output */ + + outp = (signed char *)outdata; + inp = indata; + + valpred = state->valprev; + index = state->index; + step = stepsizeTable[index]; + + bufferstep = 1; + + for ( ; len > 0 ; len-- ) { + val = *inp++; + + /* Step 1 - compute difference with previous value */ + diff = val - valpred; + sign = (diff < 0) ? 8 : 0; + if ( sign ) diff = (-diff); + + /* Step 2 - Divide and clamp */ + /* Note: + ** This code *approximately* computes: + ** delta = diff*4/step; + ** vpdiff = (delta+0.5)*step/4; + ** but in shift step bits are dropped. The net result of this is + ** that even if you have fast mul/div hardware you cannot put it to + ** good use since the fixup would be too expensive. + */ + delta = 0; + vpdiff = (step >> 3); + + if ( diff >= step ) { + delta = 4; + diff -= step; + vpdiff += step; + } + step >>= 1; + if ( diff >= step ) { + delta |= 2; + diff -= step; + vpdiff += step; + } + step >>= 1; + if ( diff >= step ) { + delta |= 1; + vpdiff += step; + } + + /* Step 3 - Update previous value */ + if ( sign ) + valpred -= vpdiff; + else + valpred += vpdiff; + + /* Step 4 - Clamp previous value to 16 bits */ + if ( valpred > 32767 ) + valpred = 32767; + else if ( valpred < -32768 ) + valpred = -32768; + + /* Step 5 - Assemble value, update index and step values */ + delta |= sign; + + index += indexTable[delta]; + if ( index < 0 ) index = 0; + if ( index > 88 ) index = 88; + step = stepsizeTable[index]; + + /* Step 6 - Output value */ + if ( bufferstep ) { + outputbuffer = (delta << 4) & 0xf0; + } else { + *outp++ = (delta & 0x0f) | outputbuffer; + } + bufferstep = !bufferstep; + } + + /* Output last step, if needed */ + if ( !bufferstep ) + *outp++ = outputbuffer; + + state->valprev = valpred; + state->index = index; +} + +void +adpcm_decoder(indata, outdata, len, state) + char indata[]; + short outdata[]; + int len; + struct adpcm_state *state; +{ + signed char *inp; /* Input buffer pointer */ + short *outp; /* output buffer pointer */ + int sign; /* Current adpcm sign bit */ + int delta; /* Current adpcm output value */ + int step; /* Stepsize */ + int valpred; /* Predicted value */ + int vpdiff; /* Current change to valpred */ + int index; /* Current step change index */ + int inputbuffer=0; /* place to keep next 4-bit value */ + int bufferstep=0; /* toggle between inputbuffer/input */ + + outp = outdata; + inp = (signed char *)indata; + + valpred = state->valprev; + index = state->index; + step = stepsizeTable[index]; + + bufferstep = 0; + + for ( ; len > 0 ; len-- ) { + + /* Step 1 - get the delta value */ + if ( bufferstep ) { + delta = inputbuffer & 0xf; + } else { + inputbuffer = *inp++; + delta = (inputbuffer >> 4) & 0xf; + } + bufferstep = !bufferstep; + + /* Step 2 - Find new index value (for later) */ + index += indexTable[delta]; + if ( index < 0 ) index = 0; + if ( index > 88 ) index = 88; + + /* Step 3 - Separate sign and magnitude */ + sign = delta & 8; + delta = delta & 7; + + /* Step 4 - Compute difference and new predicted value */ + /* + ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment + ** in adpcm_coder. + */ + vpdiff = step >> 3; + if ( delta & 4 ) vpdiff += step; + if ( delta & 2 ) vpdiff += step>>1; + if ( delta & 1 ) vpdiff += step>>2; + + if ( sign ) + valpred -= vpdiff; + else + valpred += vpdiff; + + /* Step 5 - clamp output value */ + if ( valpred > 32767 ) + valpred = 32767; + else if ( valpred < -32768 ) + valpred = -32768; + + /* Step 6 - Update step value */ + step = stepsizeTable[index]; + + /* Step 7 - Output value */ + *outp++ = valpred; + } + + state->valprev = valpred; + state->index = index; +} diff --git a/noncore/multimedia/opierec/adpcm.h b/noncore/multimedia/opierec/adpcm.h new file mode 100644 index 0000000..9c17ffa --- a/dev/null +++ b/noncore/multimedia/opierec/adpcm.h @@ -0,0 +1,19 @@ +/* +** adpcm.h - include file for adpcm coder. +** +** Version 1.0, 7-Jul-92. +*/ + +struct adpcm_state { + short valprev; /* Previous output value */ + char index; /* Index into stepsize table */ +}; + +#ifdef __STDC__ +#define ARGS(x) x +#else +#define ARGS(x) () +#endif + +void adpcm_coder ARGS((short [], char [], int, struct adpcm_state *)); +void adpcm_decoder ARGS((char [], short [], int, struct adpcm_state *)); diff --git a/noncore/multimedia/opierec/device.cpp b/noncore/multimedia/opierec/device.cpp new file mode 100644 index 0000000..c2029b7 --- a/dev/null +++ b/noncore/multimedia/opierec/device.cpp @@ -0,0 +1,341 @@ +// device.cpp + +#include "device.h" +#include "qtrec.h" + +#include <qpe/qpeapplication.h> +#include <qpe/config.h> +#include <qpe/qcopenvelope_qws.h> + +#include <qslider.h> +#include <qmessagebox.h> + +#include <qfile.h> +#include <qtextstream.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/soundcard.h> +#include <unistd.h> +#include<sys/wait.h> +// #include <sys/stat.h> +// #include <sys/time.h> +// #include <sys/types.h> +#include <unistd.h> +#include <errno.h> + +//extern QtRec *qperec; + +Device::Device( QObject * parent, const char * dsp, const char * mixr, bool record ) + : QObject( parent) +{ + dspstr = (char *)dsp; + mixstr = (char *)mixr; + + devForm=-1; + devCh=-1; + devRate=-1; + + if( !record){ //playing + qDebug("setting up DSP for playing"); + flags = O_WRONLY; + } else { //recording + qDebug("setting up DSP for recording"); + flags = O_RDWR; +// flags = O_RDONLY; + selectMicInput(); + } +} + +bool Device::openDsp() { + if( openDevice( flags) == -1) { + perror("<<<<<<<<<<<<<<ioctl(\"Open device\")"); + return false; + } + return true; +} + +int Device::getOutVolume( ) { + unsigned int volume; + int mixerHandle = open( mixstr, O_RDWR ); + if ( mixerHandle >= 0 ) { + if(ioctl( mixerHandle, MIXER_READ(SOUND_MIXER_VOLUME), &volume )==-1) + perror("<<<<<<<<<<<<<<ioctl(\"MIXER_READ\")"); + ::close( mixerHandle ); + } else + perror("open(\"/dev/mixer\")"); + printf("<<<<<<<<<<<<<<<<<<<<output volume %d\n",volume); + + Config cfg("qpe"); + cfg.setGroup("Volume"); + + return cfg.readNumEntry("VolumePercent"); +} + +int Device::getInVolume() { + unsigned int volume=0; + int mixerHandle = ::open( mixstr, O_RDWR ); + if ( mixerHandle >= 0 ) { + if(ioctl( mixerHandle, MIXER_READ(SOUND_MIXER_MIC), &volume )==-1) + perror("<<<<<<<<<<<<<<<ioctl(\"MIXER_READ\")"); + ::close( mixerHandle ); + } else + perror("open(\"/dev/mixer\")"); + printf("<<<<<<<<<<<<<<input volume %d\n", volume ); + Config cfg("qpe"); + cfg.setGroup("Volume"); + + return cfg.readNumEntry("Mic"); +} + +void Device::changedOutVolume(int vol) { + int level = (vol << 8) + vol; + int fd = 0; + if ((fd = open("/dev/mixer", O_RDWR))>=0) { + if(ioctl(fd, MIXER_WRITE(SOUND_MIXER_VOLUME), &level) == -1) + perror("ioctl(\"MIXER_IN_WRITE\")"); + + Config cfg("qpe"); + cfg.setGroup("Volume"); + cfg.writeEntry("VolumePercent", QString::number( vol )); + QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << false; + } + ::close(fd); +} + +void Device::changedInVolume(int vol ) { + int level = (vol << 8) + vol; + int fd = 0; + if ((fd = open("/dev/mixer", O_RDWR))>=0) { + if(ioctl(fd, MIXER_WRITE(SOUND_MIXER_MIC), &level) == -1) + perror("ioctl(\"MIXER_IN_WRITE\")"); + Config cfg("qpe"); + cfg.setGroup("Volume"); + cfg.writeEntry("Mic", QString::number(vol )); + QCopEnvelope( "QPE/System", "micChange(bool)" ) << false; + } + ::close(fd); +} + +bool Device::selectMicInput() { +/* + int md=0; + int info=MIXER_WRITE(SOUND_MIXER_MIC); + md = ::open( "/dev/mixer", O_RDWR ); + if ( md == -1) + perror("open(\"/dev/mixer\")"); + else { + if( ioctl( md, SOUND_MIXER_WRITE_RECSRC, &info) == -1) + perror("ioctl(\"SOUND_MIXER_WRITE_RECSRC\")"); + ::close(md); + return false; + } + ::close(md); +*/ + return true; +} + +int Device::openDevice( int flags) { +/* pid_t pid; + int status; + int pipefd[2]; + char message[20]; + if (pipe(pipefd) == -1){ + perror ("Error creating pipe"); +exit(1); + } + switch (pid = fork()) { + case -1: + perror("The fork failed!"); + break; + case 0: { + */ + if (( sd = ::open( dspstr, flags)) == -1) { + perror("open(\"/dev/dsp\")"); + QString errorMsg="Could not open audio device\n /dev/dsp\n" + +(QString)strerror(errno); + qDebug(errorMsg); + return -1; + } + + int mixerHandle=0; + /* Set the input dsp device and its input gain the weird Zaurus way */ + if (( mixerHandle = open("/dev/mixer1",O_RDWR))<0) { + perror("open(\"/dev/mixer1\")"); + } + + if(ioctl(sd,SNDCTL_DSP_RESET,0)<0){ + perror("ioctl RESET"); + } +// sprintf(message, "%d", sd); + +/* QFile f1("/pid"); + f1.open(IO_WriteOnly ); + f1.writeBlock(message, strlen(message)); + f1.close(); + */ + /* close(pipefd[0]); + write(pipefd[1], message, sizeof(message)); + close(pipefd[1]); + // qDebug("%d",soundDevice->sd ); + _exit(0); + } + default: + // pid greater than zero is parent getting the child's pid + printf("Child's pid is %d\n",pid); + QString s; + close(pipefd[1]); + read(pipefd[0], message, sizeof(message)); + s = message; + close(pipefd[0]); + +// while(wait(NULL)!=pid) + // ; + printf("child %ld terminated normally, return status is zero\n", (long) pid); + */ + // filePara.sd=(long) pid; + /* QFile f2("/pid"); + f2.open(IO_ReadOnly); + QTextStream t(&f2); + // for(int f=0; f < t.atEnd() ;f++) { + s = t.readLine(); + // } + */ +// bool ok; +// sd = s.toInt(&ok, 10); +// qDebug("<<<<<<<<<<<<<>>>>>>>>>>>>"+s); + +// f2.close(); +// } +::close(mixerHandle ); + qDebug("open device %s", dspstr); + qDebug("success! %d",sd); + return sd; +} + +bool Device::closeDevice( bool b) { +// if(b) {//close now +// if (ioctl( sd, SNDCTL_DSP_RESET, 0) == -1) { +// perror("ioctl(\"SNDCTL_DSP_RESET\")"); +// } +// } else { //let play +// if (ioctl( sd, SNDCTL_DSP_SYNC, 0) == -1) { +// perror("ioctl(\"SNDCTL_DSP_SYNC\")"); +// } +// } + + ::close( sd); //close sound device +// sdfd=0; + // sd=0; + qDebug("closed dsp"); + return true; +} + +bool Device::setDeviceFormat( int form) { + qDebug("set device res %d %d", form, sd); + if (ioctl( sd, SNDCTL_DSP_SETFMT, &form)==-1) { //set format + perror("ioctl(\"SNDCTL_DSP_SETFMT\")"); + return false; + } + devRes=form; + return true; +} + +bool Device::setDeviceChannels( int ch) { + qDebug("set channels %d %d", ch, sd); + if (ioctl( sd, SNDCTL_DSP_CHANNELS, &ch)==-1) { + perror("ioctl(\"SNDCTL_DSP_CHANNELS\")"); + return false; + } + devCh=ch; + return true; +} + +bool Device::setDeviceRate( int rate) { + qDebug("set rate %d %d", rate, sd); + if (ioctl( sd, SNDCTL_DSP_SPEED, &rate) == -1) { + perror("ioctl(\"SNDCTL_DSP_SPEED\")"); + return false; + } + + devRate=rate; + + return true; +} + +int Device::getRes() { + return devRes; +} + +int Device::getFormat() { + return devForm; +} + +int Device::getRate() { + return devRate; +} + +int Device::getChannels() { + return devCh; +} + +int Device::getDeviceFormat() { + return 0; +} + + +int Device::getDeviceRate() { + int dRate=0; + if (ioctl( sd, SOUND_PCM_READ_RATE, &dRate) == -1) { + perror("ioctl(\"SNDCTL_PCM_READ_RATE\")"); + } + return dRate; + +} + +int Device::getDeviceBits() { + int dBits=0; +#ifndef QT_QWS_EBX // zaurus doesnt have this + if (ioctl( sd, SOUND_PCM_READ_BITS, &dBits) == -1) { + perror("ioctl(\"SNDCTL_PCM_READ_BITS\")"); + } +#endif + return dBits; +} + +int Device::getDeviceChannels() { + int dCh=0; + if (ioctl( sd, SOUND_PCM_READ_CHANNELS, &dCh) == -1) { + perror("ioctl(\"SNDCTL_PCM_READ_CHANNELS\")"); + } + return dCh; +} + +int Device::getDeviceFragSize() { + int frag_size; + + if (ioctl( sd, SNDCTL_DSP_GETBLKSIZE, &frag_size) == -1) { + qDebug("no fragsize"); + } else + qDebug("driver says frag size is %d", frag_size); + return frag_size; +} + +bool Device::setFragSize(int frag) { + if (ioctl(sd, SNDCTL_DSP_SETFRAGMENT, &frag)) { + perror("ioctl(\"SNDCTL_DSP_SETFRAGMENT\")"); + return false; + } + return true; +} + +bool Device::reset() { + closeDevice(true); + openDsp(); + if (ioctl( sd, SNDCTL_DSP_RESET, 0) == -1) { + perror("ioctl(\"SNDCTL_DSP_RESET\")"); + return false; + } + return true; +} diff --git a/noncore/multimedia/opierec/device.h b/noncore/multimedia/opierec/device.h new file mode 100644 index 0000000..c9a7491 --- a/dev/null +++ b/noncore/multimedia/opierec/device.h @@ -0,0 +1,45 @@ + +#ifndef DEVICE_H +#define DEVICE_H +#include <qobject.h> +#include <sys/soundcard.h> + +class Device : public QObject { + Q_OBJECT +public: + Device( QObject * parent=0, const char * dspStr=0, const char * mixerStr=0, bool record=false ); + ~Device() {}; + bool closeDevice( bool); + int getChannels(); + int getFormat(); + int getInVolume(); + int getOutVolume(); + int getRate(); + int getRes(); + int sd; //sound descriptor + void changedInVolume(int); + void changedOutVolume(int); + bool openDsp(); + int getDeviceFormat(); + int getDeviceRate(); + int getDeviceBits(); + int getDeviceChannels(); + int getDeviceFragSize(); + bool setFragSize(int); + bool setDeviceChannels(int); + bool setDeviceRate(int); + bool setDeviceFormat(int); +bool reset(); + +private: + int devRes, devCh, devRate, devForm, flags; + char *dspstr, *mixstr; + bool selectMicInput(); + int openDevice( int ); +private slots: + +protected: + +}; + +#endif diff --git a/noncore/multimedia/opierec/helpwindow.cpp b/noncore/multimedia/opierec/helpwindow.cpp new file mode 100644 index 0000000..0c4ac78 --- a/dev/null +++ b/noncore/multimedia/opierec/helpwindow.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** $Id$ +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of an example program for Qt. This example +** program may be used, distributed and modified without limitation. +** +*****************************************************************************/ + +#include "helpwindow.h" +#include <qstatusbar.h> +#include <qstringlist.h> +#include <qlayout.h> + +#include <qpe/qpemenubar.h> +#include <qpe/qpetoolbar.h> +#include <qpe/resource.h> + +#include <qaction.h> +#include <qpixmap.h> +#include <qpopupmenu.h> +#include <qmenubar.h> +#include <qtoolbutton.h> +#include <qiconset.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qstylesheet.h> +#include <qmessagebox.h> +#include <qfiledialog.h> +#include <qapplication.h> +#include <qcombobox.h> +#include <qevent.h> +#include <qlineedit.h> +#include <qobjectlist.h> +#include <qfileinfo.h> +#include <qfile.h> +#include <qdatastream.h> +#include <qprinter.h> +#include <qsimplerichtext.h> +#include <qpaintdevicemetrics.h> + +#include <ctype.h> + +HelpWindow::HelpWindow( const QString& home_, const QString& _path, QWidget* parent, const char *name ) + : QMainWindow( parent, name, WDestructiveClose ), pathCombo( 0 ), selectedURL() +{ + QGridLayout *layout = new QGridLayout( this ); + layout->setSpacing( 2); + layout->setMargin( 2); + qDebug(_path); + browser = new QTextBrowser( this ); + QStringList Strlist; + Strlist.append( home_); + browser->mimeSourceFactory()->setFilePath( Strlist ); + browser->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + + connect( browser, SIGNAL( textChanged() ), this, SLOT( textChanged() ) ); + + if ( !home_.isEmpty() ) + browser->setSource( home_ ); + QPEToolBar *toolbar = new QPEToolBar( this ); + + QAction *a = new QAction( tr( "Backward" ), Resource::loadPixmap( "back" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), browser, SLOT( backward() ) ); + a->addTo( toolbar ); + + a = new QAction( tr( "Forward" ), Resource::loadPixmap( "forward" ), QString::null, 0, this, 0 ); + connect( a, SIGNAL( activated() ), browser, SLOT( forward() ) ); + a->addTo( toolbar ); + + + layout->addMultiCellWidget( toolbar, 0, 0, 0, 0); + + layout->addMultiCellWidget( browser, 1, 2, 0, 2); + + browser->setFocus(); +} + + +void HelpWindow::setBackwardAvailable( bool b) +{ + menuBar()->setItemEnabled( backwardId, b); +} + +void HelpWindow::setForwardAvailable( bool b) +{ + menuBar()->setItemEnabled( forwardId, b); +} + + +void HelpWindow::textChanged() +{ + if ( browser->documentTitle().isNull() ) { + setCaption( "QpeRec - Helpviewer - " + browser->context() ); + selectedURL = browser->context(); + } + else { + setCaption( "QpeRec - Helpviewer - " + browser->documentTitle() ) ; + selectedURL = browser->documentTitle(); + } + +// if ( !selectedURL.isEmpty() && pathCombo ) { +// bool exists = FALSE; +// int i; +// for ( i = 0; i < pathCombo->count(); ++i ) { +// if ( pathCombo->text( i ) == selectedURL ) { +// exists = TRUE; +// break; +// } +// } +// if ( !exists ) { +// pathCombo->insertItem( selectedURL, 0 ); +// pathCombo->setCurrentItem( 0 ); +// mHistory[ hist->insertItem( selectedURL ) ] = selectedURL; +// } else +// pathCombo->setCurrentItem( i ); +// selectedURL = QString::null; +// } +} + +HelpWindow::~HelpWindow() +{ + history.clear(); + QMap<int, QString>::Iterator it = mHistory.begin(); + for ( ; it != mHistory.end(); ++it ) + history.append( *it ); + + QFile f( QDir::currentDirPath() + "/.history" ); + f.open( IO_WriteOnly ); + QDataStream s( &f ); + s << history; + f.close(); + + bookmarks.clear(); + QMap<int, QString>::Iterator it2 = mBookmarks.begin(); + for ( ; it2 != mBookmarks.end(); ++it2 ) + bookmarks.append( *it2 ); + + QFile f2( QDir::currentDirPath() + "/.bookmarks" ); + f2.open( IO_WriteOnly ); + QDataStream s2( &f2 ); + s2 << bookmarks; + f2.close(); +} + +void HelpWindow::openFile() +{ +#ifndef QT_NO_FILEDIALOG +#endif +} + +void HelpWindow::newWindow() +{ + ( new HelpWindow(browser->source(), "qbrowser") )->show(); +} + +void HelpWindow::print() +{ +#ifndef QT_NO_PRINTER +#endif +} + +void HelpWindow::pathSelected( const QString &_path ) +{ + browser->setSource( _path ); + QMap<int, QString>::Iterator it = mHistory.begin(); + bool exists = FALSE; + for ( ; it != mHistory.end(); ++it ) { + if ( *it == _path ) { + exists = TRUE; + break; + } + } + if ( !exists ) + mHistory[ hist->insertItem( _path ) ] = _path; +} + +void HelpWindow::readHistory() +{ + if ( QFile::exists( QDir::currentDirPath() + "/.history" ) ) { + QFile f( QDir::currentDirPath() + "/.history" ); + f.open( IO_ReadOnly ); + QDataStream s( &f ); + s >> history; + f.close(); + while ( history.count() > 20 ) + history.remove( history.begin() ); + } +} + +void HelpWindow::readBookmarks() +{ + if ( QFile::exists( QDir::currentDirPath() + "/.bookmarks" ) ) { + QFile f( QDir::currentDirPath() + "/.bookmarks" ); + f.open( IO_ReadOnly ); + QDataStream s( &f ); + s >> bookmarks; + f.close(); + } +} + +void HelpWindow::histChosen( int i ) +{ + if ( mHistory.contains( i ) ) + browser->setSource( mHistory[ i ] ); +} + +void HelpWindow::bookmChosen( int i ) +{ + if ( mBookmarks.contains( i ) ) + browser->setSource( mBookmarks[ i ] ); +} + +void HelpWindow::addBookmark() +{ + mBookmarks[ bookm->insertItem( caption() ) ] = caption(); +} + diff --git a/noncore/multimedia/opierec/helpwindow.h b/noncore/multimedia/opierec/helpwindow.h new file mode 100644 index 0000000..76b672a --- a/dev/null +++ b/noncore/multimedia/opierec/helpwindow.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** $Id$ +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of an example program for Qt. This example +** program may be used, distributed and modified without limitation. +** +*****************************************************************************/ + +#ifndef HELPWINDOW_H +#define HELPWINDOW_H + +#include <qmainwindow.h> +#include <qtextbrowser.h> +#include <qstringlist.h> +#include <qmap.h> +#include <qdir.h> +#include <qevent.h> + +class QComboBox; +class QPopupMenu; + +class HelpWindow : public QMainWindow +{ + Q_OBJECT +public: + HelpWindow( const QString& home_, const QString& path, QWidget* parent = 0, const char *name=0 ); + ~HelpWindow(); + +private slots: + + void addBookmark(); + void bookmChosen( int ); + void histChosen( int ); + void newWindow(); + void openFile(); + void pathSelected( const QString & ); + void print(); + void setBackwardAvailable( bool ); + void setForwardAvailable( bool ); + void textChanged(); +private: + QTextBrowser* browser; + QComboBox *pathCombo; + int backwardId, forwardId; + QString selectedURL; + QStringList history, bookmarks; + QMap<int, QString> mHistory, mBookmarks; + QPopupMenu *hist, *bookm; + + void readHistory(); + void readBookmarks(); + +}; + + + + + +#endif + diff --git a/noncore/multimedia/opierec/main.cpp b/noncore/multimedia/opierec/main.cpp new file mode 100644 index 0000000..5f7c02f --- a/dev/null +++ b/noncore/multimedia/opierec/main.cpp @@ -0,0 +1,22 @@ +/*************************************************************************** + main.cpp - main routine + ***************************************************************************/ +//// main.cpp +//// copyright 2001, 2002, by L. J. Potter <ljp@llornkcor.com> +/*************************************************************************** + * 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 "qtrec.h" +#include <qpe/qpeapplication.h> + +int main(int argc, char* argv[]) { + QPEApplication a(argc, argv); + QtRec qtrec; + a.showMainWidget( &qtrec); + return a.exec(); +} + + diff --git a/noncore/multimedia/opierec/opierec-control b/noncore/multimedia/opierec/opierec-control new file mode 100644 index 0000000..e8396ae --- a/dev/null +++ b/noncore/multimedia/opierec/opierec-control @@ -0,0 +1,10 @@ +Package: opierec +Files: bin/opierec pics/opierec apps/Applications/opierec.desktop +Priority: optional +Section: multimedia/applications +Maintainer: L.J. Potter <ljp@llornkcor.com> +Architecture: arm +Version: 1.5-2 +Depends: opie ($QPE_VERSION) +Description: audio sampling recorder + A simple audio recording/playing application. diff --git a/noncore/multimedia/opierec/opierec.pro b/noncore/multimedia/opierec/opierec.pro new file mode 100644 index 0000000..1788907 --- a/dev/null +++ b/noncore/multimedia/opierec/opierec.pro @@ -0,0 +1,12 @@ +TEMPLATE = app +CONFIG = qt warn_on debug +#CONFIG = qt warn_on release +HEADERS = adpcm.h pixmaps.h helpwindow.h qtrec.h device.h wavFile.h +SOURCES = adpcm.c helpwindow.cpp main.cpp qtrec.cpp device.cpp wavFile.cpp +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe -lpthread +INTERFACES = +TARGET = opierec +DESTDIR = $(OPIEDIR)/bin +#TMAKE_CXXFLAGS += -DQT_QWS_VERCEL_IDR -DQWS -fno-exceptions -fno-rtti diff --git a/noncore/multimedia/opierec/pixmaps.h b/noncore/multimedia/opierec/pixmaps.h new file mode 100644 index 0000000..eddddb9 --- a/dev/null +++ b/noncore/multimedia/opierec/pixmaps.h @@ -0,0 +1,294 @@ +/**************************************************************************** +** Created: Thu Jan 17 11:19:45 2002 +copyright 2002 by L.J. Potter ljp@llornkcor.com +****************************************************************************/ +#ifndef PIXMAPS_H +#define PIXMAPS_H + +/* XPM */ +static const char * image0_data[] = { + + //static char * Qperec16x16_xpm[] = { + "16 16 140 2", + " c None", + ". c #FF1600", + "+ c #FF1200", + "@ c #A2D100", + "# c #C1A400", + "$ c #9CDA00", + "% c #FF7B00", + "& c #FF7F00", + "* c #FD7E00", + "= c #D36600", + "- c #B45600", + "; c #FF7A00", + "> c #F97C00", + ", c #F77B00", + "' c #CC6200", + ") c #B85A00", + "! c #A46000", + "~ c #A36000", + "{ c #F59000", + "] c #E48500", + "^ c #AD6500", + "/ c #FFBA00", + "( c #DEA300", + "_ c #A97900", + ": c #A67600", + "< c #FBB700", + "[ c #E3A600", + "} c #AD7E00", + "| c #B48000", + "1 c #BE8900", + "2 c #907700", + "3 c #7F6800", + "4 c #7A6400", + "5 c #F3C700", + "6 c #000000", + "7 c #937800", + "8 c #5F4E00", + "9 c #A48600", + "0 c #FEF600", + "a c #FEF200", + "b c #F4E800", + "c c #F0E800", + "d c #E1DB00", + "e c #8F8900", + "f c #B0A700", + "g c #FCF400", + "h c #948B00", + "i c #948D00", + "j c #D3CD00", + "k c #B5B000", + "l c #BBB100", + "m c #AAA300", + "n c #7A8400", + "o c #778100", + "p c #656C00", + "q c #7B8500", + "r c #A5B300", + "s c #6E7800", + "t c #737D00", + "u c #3A3F00", + "v c #717B00", + "w c #586000", + "x c #919D00", + "y c #606900", + "z c #B3F700", + "A c #9DD900", + "B c #87BA00", + "C c #9CD800", + "D c #83B400", + "E c #A1DF00", + "F c #B2F700", + "G c #7EAE00", + "H c #92CA00", + "I c #9DD800", + "J c #94CC00", + "K c #63A600", + "L c #467500", + "M c #385E00", + "N c #457400", + "O c #365B00", + "P c #467400", + "Q c #599500", + "R c #457300", + "S c #447300", + "T c #315300", + "U c #487800", + "V c #335600", + "W c #3C6400", + "X c #35C678", + "Y c #31B86F", + "Z c #2DAB64", + "` c #2EAA67", + " . c #238551", + ".. c #2DAA66", + "+. c #238450", + "@. c #2DA865", + "#. c #30B46C", + "$. c #29985C", + "%. c #2A9E60", + "&. c #23824F", + "*. c #2CA461", + "=. c #22804D", + "-. c #2BA160", + ";. c #2A9C5E", + ">. c #0036EE", + ",. c #002EC7", + "'. c #0024A4", + "). c #002DC4", + "!. c #002295", + "~. c #002DC1", + "{. c #002093", + "]. c #002BC0", + "^. c #0030D4", + "/. c #002293", + "(. c #0029B5", + "_. c #00218E", + ":. c #00208C", + "<. c #0028B4", + "[. c #0028B0", + "}. c #4F00E8", + "|. c #4200C3", + "1. c #320093", + "2. c #320091", + "3. c #4100C3", + "4. c #4200C4", + "5. c #4600CC", + "6. c #330095", + "7. c #3C00AF", + "8. c #3C00B0", + "9. c #330096", + "0. c #3D00B4", + "a. c #5300AA", + "b. c #3E0080", + "c. c #4F00A1", + "d. c #4E00A0", + "e. c #4E00A1", + "f. c #5100A5", + "g. c #490097", + "h. c #4A0098", + "i. c #4A009A", + " . . + ", + " ", + "@ @ # # $ # # ", + " ", + "% % & * = - ; > , ' ) ", + " ! ~ { ] ^ ", + "/ / / ( _ : < / [ } | 1 ", + " 2 3 4 5 6 7 8 9 ", + "0 0 a b c d e f g 0 h i j k l m ", + " n o p q r s t u v w x y ", + "z z z A B C D A E F B G H G I J ", + " K L M N O P Q R S T U V L W ", + "X Y Z ` ...+.@.#.$.%.&.*.=.-.;.", + ">.,.'.).!.~.{.].^./.(._.(.:.<.[.", + "}.|.1.|.2.3.2.4.5.6.7.6.8.9.8.0.", + " a.b.c.b.d.b.e.f. g. h. i. "}; + + +// stop button default +static const char* const image3_data[] = { + "22 22 4 1", + ". c None", + "# c #000000", + "c c #7b797b", + "b c #ff0000", + "a c #ff9194", + "......................", + "......................", + "......................", + "......................", + "......................", + "........#######.......", + ".......#aaaabbb#......", + "......#aabbbbbbb#.....", + ".....#aabbbbbbbbb#....", + ".....#abbbbbbbbbb#c...", + ".....#abbbbbbbbbb#c...", + ".....#abbbbbbbbbb#c...", + ".....#abbbbbbbbbb#c...", + ".....#bbbbbbbbbbb#c...", + ".....#bbbbbbbbbbb#c...", + "......#bbbbbbbbb#cc...", + ".......#bbbbbbb#cc....", + "........#######cc.....", + ".........ccccccc......", + "......................", + "......................", + "......................"}; + +// play button +static const char* const image4_data[] = { + "22 22 5 1", + ". c None", + "# c #000000", + "c c #838183", + "b c #00ff00", + "a c #ffffff", + "......................", + "......................", + "......................", + "......................", + "......................", + "............#.........", + "............##........", + "............#a#.......", + ".....########aa#......", + ".....#aaaaaaabaa#.....", + ".....#bbbbbbbbbaa#....", + ".....#bbbbbbbbba#.....", + ".....########ba#c.....", + ".....ccccccc#a#c......", + "...........c##c.......", + "...........c#c........", + "...........cc.........", + "...........c..........", + "......................", + "......................", + "......................", + "......................"}; + +static const char* const image5_data[] = { + "22 22 5 1", + ". c None", + "# c #000000", + "c c #838183", + "b c #c5c2c5", + "a c #ffffff", + "......................", + "......................", + "......................", + "......................", + "......................", + "............#.....#...", + "............##....#...", + "............#a#...#...", + ".....########aa#..#...", + ".....#aaaaaaabaa#.#...", + ".....#bbbbbbbbbaa##...", + ".....#bbbbbbbbba#.#...", + ".....########ba#c.#...", + ".....ccccccc#a#c..#...", + "...........c##c...#...", + "...........c#c....#...", + "...........cc.........", + "...........c..........", + "......................", + "......................", + "......................", + "......................"}; + +// record button default +static const char* const image6_data[] = { + "22 22 5 1", + ". c None", + "# c #000000", + "c c #ff0000", + "b c #7b797b", + "a c #ff9194", + "......................", + "......................", + "......................", + "......................", + "......................", + "......#########.......", + ".....#.aaaaaaaa#......", + ".....#acccccccb#b.....", + ".....#acccccccb#b.....", + ".....#acccccccb#b.....", + ".....#acccccccb#b.....", + ".....#acccccccb#b.....", + ".....#acccccccb#b.....", + ".....#acccccccb#b.....", + ".....#abbbbbbbb#b.....", + "......#########.b.....", + "......bbbbbbbbbb......", + "......................", + "......................", + "......................", + "......................", + "......................"}; + +#endif diff --git a/noncore/multimedia/opierec/qtrec.cpp b/noncore/multimedia/opierec/qtrec.cpp new file mode 100644 index 0000000..4223d93 --- a/dev/null +++ b/noncore/multimedia/opierec/qtrec.cpp @@ -0,0 +1,2270 @@ +/**************************************************************************** + // qtrec.cpp + Created: Thu Jan 17 11:19:58 2002 + copyright 2002 by L.J. Potter <ljp@llornkcor.com> +****************************************************************************/ + +#define DEV_VERSION + +#include "pixmaps.h" +#include "qtrec.h" +#include "helpwindow.h" +#include "device.h" +#include "wavFile.h" + +#include <pthread.h> + +extern "C" { +#include "adpcm.h" +} + +#include <sys/soundcard.h> + +// #if defined (QTOPIA_INTERNAL_FSLP) +// #include <qpe/lnkproperties.h> +// #endif + +#include <qpe/applnk.h> +#include <qpe/config.h> +#include <qpe/ir.h> +#include <qpe/qcopenvelope_qws.h> +#include <qpe/qpeapplication.h> +#include <qpe/resource.h> +#include <qpe/storage.h> + +#include <qlineedit.h> +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qcursor.h> +//#include <qdatetime.h> +#include <qdir.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qgroupbox.h> +#include <qiconview.h> +#include <qimage.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qlistview.h> +#include <qmessagebox.h> +#include <qpixmap.h> +#include <qpopupmenu.h> +#include <qpushbutton.h> +#include <qregexp.h> +#include <qslider.h> +#include <qtabwidget.h> +#include <qtimer.h> +#include <qvariant.h> + +#include <errno.h> +#include <fcntl.h> +#include <math.h> +#include <mntent.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/soundcard.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/vfs.h> +#include <unistd.h> +#include<sys/wait.h> +#include <sys/signal.h> + +//#define ZAURUS 0 +struct adpcm_state encoder_state; +struct adpcm_state decoder_state; + +long findPeak(long input ); +//char deviceRates[]; + +typedef struct { + int sampleRate; + /* int fragSize; */ + /* int blockSize; */ + int resolution; //bitrate + int channels; //number of channels + int fd; //file descriptor + int sd; //sound device descriptor + int numberSamples; //total number of samples + int SecondsToRecord; // number of seconds that should be recorded + float numberOfRecordedSeconds; //total number of samples recorded + int samplesToRecord; //number of samples to be recorded + int inVol; //input volume + int outVol; //output volume + int format; //wavfile format PCM.. ADPCM + const char *fileName; //name of fiel to be played/recorded +} fileParameters; + +fileParameters filePara; + +bool monitoring, recording; +bool stopped; +QLabel *timeLabel; +QSlider *timeSlider; +int sd; + +#if defined(QT_QWS_EBX) +#define DSPSTROUT "/dev/dsp" +#define DSPSTRIN "/dev/dsp1" +#define DSPSTRMIXEROUT "/dev/mixer" +#define DSPSTRMIXERIN "/dev/mixer1" +#else +#define DSPSTROUT "/dev/dsp" +#define DSPSTRIN "/dev/dsp" +#define DSPSTRMIXERIN "/dev/mixer" +#define DSPSTRMIXEROUT "/dev/mixer" +#endif + +// threaded recording +void quickRec() { +//void QtRec::quickRec() { + + qDebug("%d", + filePara.numberSamples/filePara.sampleRate * filePara.channels); + qDebug("samples %d, rate %d, channels %d", + filePara.numberSamples, filePara.sampleRate, filePara.channels); + + int total = 0; // Total number of bytes read in so far. + int bytesWritten, number; + + count_info info; + + bytesWritten=0; + number=0; + QString num, timeString; + int level=0; + int threshold=0; + // if(limit != 0) + // t->start( ( limit +.3) , true); + + recording = true; + //rate=filePara.sampleRate; + int bits = filePara.resolution; + qDebug("bits %d", bits); +// if( filePara.format==WAVE_FORMAT_DVI_ADPCM) +// else + audio_buf_info inInfo; + ioctl( filePara.fd, SNDCTL_DSP_GETISPACE, &inInfo); + qDebug("ispace is frags %d, total %d", inInfo.fragments, inInfo.fragstotal); + + if( filePara.resolution == 16 ) { //AFMT_S16_LE) + qDebug("AFMT_S16_LE size %d", filePara.SecondsToRecord); + qDebug("samples to record %d", filePara.samplesToRecord); + qDebug("%d", filePara.sd); + level=7; + threshold=0; + timeString.sprintf("%.2f", filePara.numberOfRecordedSeconds); + timeLabel->setText( timeString+ " seconds"); + + if( filePara.format==WAVE_FORMAT_DVI_ADPCM) { + qDebug("start recording WAVE_FORMAT_DVI_ADPCM"); + // <<<<<<<<<<<<<<<<<<<<<<<<<<< WAVE_FORMAT_DVI_ADPCM >>>>>>>>>>>>>>>>>>>>>> + char abuf[BUFSIZE/2]; + short sbuf[BUFSIZE]; + short sbuf2[BUFSIZE]; + memset( abuf,0,BUFSIZE/2); + memset( sbuf,0,BUFSIZE); + memset( sbuf2,0,BUFSIZE); + + for(;;) { + if (stopped) { + qDebug("quickRec:: stopped"); + break; // stop if playing was set to false +// return; + } + + number=::read( filePara.sd, sbuf, BUFSIZE); + + if(number <= 0) { + perror("recording error "); + qDebug( "%s %d", filePara.fileName, number); + // errorStop(); + recording=stopped=false; +// QMessageBox::message("Note", +// "Error recording to file\n%s", +// filePara.fileName); + return; + } + //if(stereo == 2) { +// adpcm_coder( sbuf2, abuf, number/2, &encoder_state); + adpcm_coder( sbuf, abuf, number/2, &encoder_state); + + bytesWritten = ::write( filePara.fd , abuf, number/4); + + long peak; + for (int i = 0; i < number; i++) + { //since Z is mono do normally + peak = findPeak((long)sbuf[i]); + printf("peak %ld\r",peak); + fflush(stdout); + } + + + //------------->>>> out to file + // if(filePara.channels==1) + // total += bytesWritten/2; //mono + // else + total += bytesWritten; + filePara.numberSamples = total; +// if( total >= filePara.samplesToRecord) +// timeSlider->setValue(0); +// else if( filePara.SecondsToRecord !=0) + timeSlider->setValue( total); + + filePara.numberOfRecordedSeconds = (float)total / (float)filePara.sampleRate * (float)2; + +// printf("Writing number %d, bytes %d,total %d, sample rate %d, secs %.2f \n", +// number, +// bytesWritten , +// total, +// filePara.sampleRate, +// filePara.numberOfRecordedSeconds); +// fflush(stdout); + ioctl( filePara.sd, SNDCTL_DSP_GETIPTR, &info); +// qDebug("%d, %d", info.bytes, (info.bytes / filePara.sampleRate) / 2); + + timeString.sprintf("%.2f", filePara.numberOfRecordedSeconds); + timeLabel->setText( timeString + " seconds"); + + qApp->processEvents(); + if( total >= filePara.samplesToRecord) + break; + } + } else { + // <<<<<<<<<<<<<<<<<<<<<<<<<<< WAVE_FORMAT_PCM >>>>>>>>>>>>>>>>>>>>>> + qDebug("start recording WAVE_FORMAT_PCM"); + short inbuffer[BUFSIZE], outbuffer[BUFSIZE]; + memset( inbuffer,0,BUFSIZE); + memset( outbuffer,0,BUFSIZE); + for(;;) { + if (stopped) { + qDebug("quickRec:: stopped"); + break; // stop if playing was set to false + return; + } + + number=::read( filePara.sd, inbuffer, BUFSIZE); + + if(number <= 0) { + perror("recording error "); + qDebug( filePara.fileName); + recording=stopped=false; + // errorStop(); +// QMessageBox::message("Note","error recording to file\n%s",filePara.fileName); + return;// false; + } +/* for (int i=0;i< number;i++) { //2*i is left channel + +outbuffer[i]=inbuffer[i]>>1; // no clippy, please +}*/ + bytesWritten = ::write( filePara.fd , inbuffer, number); +//------------->>>> out to file + if(bytesWritten < 0) { + // errorStop(); + perror("File writing error "); + return;// false; + } + + // if(filePara.channels==1) + // total += bytesWritten/2; //mono + // else + total += bytesWritten; + long peak; + for (int i = 0; i < number; i++) + { //since Z is mono do normally + peak = findPeak((long)inbuffer[i]); + printf("peak %ld\r",peak); + fflush(stdout); + } + + + filePara.numberSamples = total; + if(filePara.SecondsToRecord !=0) + timeSlider->setValue( total); +// printf("Writing number %d, bytes %d,total %d\r",number, bytesWritten , total); +// fflush(stdout); + + ioctl( filePara.sd, SNDCTL_DSP_GETIPTR, &info); +// qDebug("%d, %d", info.bytes, ( info.bytes / filePara.sampleRate) / 2); + + filePara.numberOfRecordedSeconds = (float)total / (float)filePara.sampleRate / (float)2; + + timeString.sprintf("%.2f", filePara.numberOfRecordedSeconds); + timeLabel->setText( timeString + " seconds"); + + qApp->processEvents(); + if( total >= filePara.samplesToRecord) + break; + } + } //end main loop + + } else { // <<<<<<<<<<<<<<<<<<<<<<< format = AFMT_U8; + unsigned char unsigned_inbuffer[BUFSIZE], unsigned_outbuffer[BUFSIZE]; + memset( unsigned_inbuffer, 0, BUFSIZE); + memset( unsigned_outbuffer, 0, BUFSIZE); + + for(;;) { + if (stopped) { + qDebug("quickRec:: stopped"); + break; // stop if playing was set to false + } + number=::read( filePara.sd, unsigned_inbuffer, BUFSIZE); +//-------------<<<< in from device +// val = (data ^ 0x80) << 8; + +//unsigned_outbuffer = (unsigned_inbuffer ^ 0x80) << 8; + +// if(number <= 0) { +// perror("recording error "); +// qDebug(filePara.fileName); +// // errorStop(); +// QMessageBox::message("Note","error recording"); +// return;// false; +// } +// for (int i=0;i< number;i++) { //2*i is left channel +// unsigned_outbuffer[i]=unsigned_inbuffer[i]>>1; // no clippy, please +// } + + bytesWritten = ::write( filePara.fd , unsigned_inbuffer, number); + +//------------->>>> out to file + if(bytesWritten < 0) { + recording=stopped=false; + // errorStop(); + QMessageBox::message("Note","There was a problem\nwriting to the file"); + perror("File writing error "); + return;// false; + } + total += bytesWritten; + filePara.numberSamples = total; + // printf("\nWriting number %d, bytes %d,total %d \r",number, bytesWritten , total); + // fflush(stdout); + if(filePara.SecondsToRecord !=0) + timeSlider->setValue( total); + + filePara.numberOfRecordedSeconds = (float)total / (float)filePara.sampleRate; + + timeString.sprintf("%.2f",filePara.numberOfRecordedSeconds); + timeLabel->setText( timeString + " seconds"); + + qApp->processEvents(); + if( total >= filePara.samplesToRecord) + break; + } //end main loop + } +// qDebug("Final %d, %d", filePara.samplesToRecord , filePara.numberOfRecordedSeconds); +} /// END quickRec() + +// threaded play +void playIt() { + +} + + + +/////////////////<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>> +/////////////////<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>> + +QtRec::QtRec( QWidget* parent, const char* name, WFlags fl ) + : QWidget( parent, name, fl ) { + // QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << true; // mute device + // autoMute=TRUE; +// QPEApplication::grabKeyboard(); + +// signal(SIGPIPE, SIG_IGN); + + if ( !name ) + setName( "QpeRec" ); + init(); + initConfig(); + initConnections(); + renameBox = 0; + +// open sound device to get volumes + soundDevice = new Device( this, DSPSTROUT, DSPSTRMIXEROUT, false); + +// soundDevice->setDeviceFormat(AFMT_S16_LE); +// soundDevice->setDeviceChannels(1); +// soundDevice->setDeviceRate( 22050); + + getInVol(); + getOutVol(); + + soundDevice->closeDevice( true); + soundDevice->sd=-1; + soundDevice=0; + wavFile=0; + + if(soundDevice) delete soundDevice; + + initIconView(); + + if(autoMute) + doMute(true); + ListView1->setFocus(); + playing=false; +} + +QtRec::~QtRec() { + +} + +void QtRec::cleanUp() { + + if(!stopped) { + stopped=true; + endRecording(); + } + + ListView1->clear(); + + if(autoMute) + doMute(false); + + if(wavFile) delete wavFile; +// if(soundDevice) delete soundDevice; + +// QPEApplication::grabKeyboard(); +// QPEApplication::ungrabKeyboard(); +} + +void QtRec::init() { + + needsStereoOut=false; + QPixmap image3( ( const char** ) image3_data ); + QPixmap image4( ( const char** ) image4_data ); + QPixmap image6( ( const char** ) image6_data ); + + stopped=true; + setCaption( tr( "QpeRecord " ) + QString::number(VERSION) ); + QGridLayout *layout = new QGridLayout( this ); + layout->setSpacing( 2); + layout->setMargin( 2); + + TabWidget = new QTabWidget( this, "TabWidget" ); + layout->addMultiCellWidget(TabWidget, 0, 7, 0, 7); + // TabWidget->setTabShape(QTabWidget::Triangular); + + ///**********<<<<<<<<<<<<>>>>>>>>>>>>*************** + tab = new QWidget( TabWidget, "tab" ); + + QGridLayout *layout1 = new QGridLayout( tab); + layout1->setSpacing( 2); + layout1->setMargin( 2); + + timeSlider = new QSlider( 0,100,10,0, QSlider::Horizontal, tab, (const char *) "timeSlider" ); + // timeSlider->setFixedWidth(150); + layout1->addMultiCellWidget( timeSlider, 1, 1, 0, 3); +// timeSlider->setTickmarks(QSlider::Above); + + timeLabel = new QLabel( tab, "TimeLabel" ); + layout1->addMultiCellWidget( timeLabel, 0, 0, 0, 3); + + playLabel2 = new QLabel(tab, "PlayLabel2" ); + playLabel2->setText("Play"); + playLabel2->setFixedHeight(18); + layout1->addMultiCellWidget( playLabel2, 0, 0, 4, 4); + + Stop_PushButton = new QPushButton( tab, "Stop_PushButton" ); + layout1->addMultiCellWidget( Stop_PushButton, 1, 1, 4, 4); + Stop_PushButton->setFixedSize(22,22); + Stop_PushButton->setPixmap( image4 ); + + toBeginningButton = new QPushButton( tab, "Beginning_PushButton" ); + layout1->addMultiCellWidget(toBeginningButton, 1, 1, 5, 5); + toBeginningButton->setFixedSize(22,22); + toBeginningButton->setPixmap( Resource::loadPixmap("fastback") ); + + toEndButton = new QPushButton( tab, "End_PushButton" ); + layout1->addMultiCellWidget( toEndButton, 1, 1, 6, 6); + toEndButton->setFixedSize(22,22); + toEndButton->setPixmap( Resource::loadPixmap( "fastforward" ) ); + + QLabel *recLabel2; + recLabel2 = new QLabel( tab, "recLabel2" ); + recLabel2->setText("Rec"); + recLabel2->setFixedHeight(18); + layout1->addMultiCellWidget( recLabel2, 0, 0, 7, 7); + + Rec_PushButton = new QPushButton( tab, "Rec_PushButton" ); + layout1->addMultiCellWidget( Rec_PushButton, 1, 1, 7, 7); + Rec_PushButton->setFixedSize(22,22); + Rec_PushButton->setPixmap( image6 ); + + t = new QTimer( this ); + connect( t, SIGNAL( timeout() ), SLOT( timerBreak() ) ); + + rewindTimer = new QTimer( this ); + connect( rewindTimer, SIGNAL( timeout() ), SLOT( rewindTimerTimeout() ) ); + + forwardTimer = new QTimer( this ); + connect( forwardTimer, SIGNAL( timeout() ), SLOT( forwardTimerTimeout() ) ); + + deleteSoundButton = new QPushButton( tab, "deleteSoundButton" ); + layout1->addMultiCellWidget( deleteSoundButton, 1, 1, 8, 8); + deleteSoundButton->setText( tr( "Delete" ) ); + + ListView1 = new QListView( tab, "IconView1" ); + layout1->addMultiCellWidget( ListView1, 2, 2, 0, 8); + + ListView1->addColumn( tr( "Name" ) ); + ListView1->setColumnWidth(0,140); + ListView1->setSorting( 1, false); + ListView1->addColumn( tr( "Time" ) ); //in seconds + ListView1->setColumnWidth(1,50); + ListView1->addColumn( "Location"); + ListView1->setColumnWidth(2,50); + ListView1->addColumn( "Date"); + ListView1->setColumnWidth(3,63); + + ListView1->setColumnWidthMode(0,QListView::Manual); + ListView1->setColumnAlignment(1,QListView::AlignCenter); + ListView1->setColumnAlignment(2,QListView::AlignRight); + ListView1->setColumnAlignment(3,QListView::AlignLeft); + ListView1->setAllColumnsShowFocus( true ); + QPEApplication::setStylusOperation( ListView1->viewport(),QPEApplication::RightOnHold); + + TabWidget->insertTab( tab, tr( "Files" ) ); + + ///**********<<<<<<<<<<<<>>>>>>>>>>>>*************** + tab_3 = new QWidget( TabWidget, "tab_3" ); + //////////////////////////////////// + + Layout19 = new QHBoxLayout( tab_3); + Layout19->setSpacing( 2 ); + Layout19->setMargin( 0 ); + + Layout18 = new QVBoxLayout(this); + Layout18->setSpacing( 2 ); + Layout18->setMargin( 0 ); + + Layout17 = new QHBoxLayout(this); + Layout17->setSpacing( 2 ); + Layout17->setMargin( 0 ); + + sampleGroup = new QGroupBox( tab_3, "samplegroup" ); + sampleGroup->setTitle( tr( "Sample Rate" ) ); + sampleGroup->setFixedSize( 95,50); + + sampleRateComboBox = new QComboBox( false, sampleGroup, "SampleRateComboBox" ); + sampleRateComboBox->setGeometry( QRect( 10, 20, 80, 25 ) ); +//#ifndef QT_QWS_EBX + sampleRateComboBox->insertItem( tr( "44100")); + sampleRateComboBox->insertItem( tr( "32000")); +//#endif + sampleRateComboBox->insertItem( tr( "22050")); + //#ifndef QT_QWS_VERCEL_IDR + sampleRateComboBox->insertItem( tr( "16000")); + sampleRateComboBox->insertItem( tr( "11025")); + sampleRateComboBox->insertItem( tr( "8000")); + //#endif + + Layout17->addWidget( sampleGroup ); + + sizeGroup= new QGroupBox( tab_3, "sizeGroup" ); + sizeGroup->setTitle( tr( "Limit Size" ) ); + sizeGroup->setFixedSize(80,50); + + sizeLimitCombo = new QComboBox( false, sizeGroup, "sizeLimitCombo" ); + sizeLimitCombo ->setGeometry( QRect( 5, 20, 70, 25 ) ); + sizeLimitCombo->insertItem(tr("Unlimited")); + for(int i=1;i<13; i++) { + sizeLimitCombo->insertItem( QString::number(i*5)); + } + +// sizeLimitCombo->insertItem(tr("5 secs")); +// sizeLimitCombo->insertItem(tr("10 secs")); +// sizeLimitCombo->insertItem(tr("15 secs")); +// sizeLimitCombo->insertItem(tr("20 secs")); + + // Layout18->addWidget( sizeGroup ); + Layout17->addWidget( sizeGroup ); + + Layout18->addLayout( Layout17 ); + + Layout16 = new QHBoxLayout(this); + Layout16->setSpacing( 2 ); + Layout16->setMargin( 0 ); + + dirGroup = new QGroupBox( tab_3, "dirGroup" ); + dirGroup->setTitle( tr( "File Directory" ) ); + dirGroup->setFixedSize(130,50); + + directoryComboBox = new QComboBox( false, dirGroup, "dirGroup" ); + directoryComboBox->setGeometry( QRect( 10, 15, 115, 25 ) ); + + Layout18->addWidget( dirGroup ); + + bitGroup = new QGroupBox( tab_3, "bitGroup" ); + bitGroup->setTitle( tr( "Bit Depth" ) ); + bitGroup->setFixedSize(65,50); + + bitRateComboBox = new QComboBox( false, bitGroup, "BitRateComboBox" ); + bitRateComboBox->insertItem( tr( "16" ) ); + bitRateComboBox->insertItem( tr( "8" ) ); + bitRateComboBox->setGeometry( QRect( 5, 20, 50, 25 ) ); + + Layout18->addWidget( bitGroup ); + + compressionCheckBox = new QCheckBox ( "Wave Compression (smaller files)", tab_3 ); + Layout18->addWidget( compressionCheckBox ); + + autoMuteCheckBox= new QCheckBox ( "auto Mute", tab_3 ); + Layout18->addWidget( autoMuteCheckBox ); + + Layout19->addLayout( Layout18 ); + + QWidget *d = QApplication::desktop(); + int width=d->width(); + int height=d->height(); + + + + if( width < height) { + + tab_5 = new QWidget( TabWidget, "tab_5" ); + + QHBoxLayout *Layout19a; + Layout19a = new QHBoxLayout( tab_5); + Layout19a->setSpacing( 2 ); + Layout19a->setMargin( 0 ); + + + Layout15 = new QVBoxLayout(this); + Layout15->setSpacing( 2 ); + Layout15->setMargin( 0 ); + + Layout15b = new QVBoxLayout(this); + Layout15b->setSpacing( 2 ); + Layout15b->setMargin( 0 ); + + TextLabel2 = new QLabel( tab_5, "InputLabel" ); + TextLabel2->setText( tr( "In")); + TextLabel2->setFixedWidth(35); + Layout15->addWidget( TextLabel2 ); + + TextLabel3 = new QLabel( tab_5, "OutputLabel" ); + TextLabel3->setText( tr( "Out" ) ); + Layout15b->addWidget( TextLabel3 ); + + InputSlider = new QSlider( -100, 0, 10, 0, QSlider::Vertical, tab_5, (const char *) "InputSlider" ); + InputSlider->setTickmarks(QSlider::Both); + Layout15->addWidget( InputSlider); + + OutputSlider = new QSlider( -100,0,10,0, QSlider::Vertical,tab_5,(const char *) "OutputSlider" ); + OutputSlider->setTickmarks(QSlider::Both); + + Layout15b->addWidget( OutputSlider ); + + outMuteCheckBox = new QCheckBox ( "mute", tab_5 ); + Layout15->addWidget( outMuteCheckBox ); + + inMuteCheckBox = new QCheckBox ( "mute", tab_5 ); + inMuteCheckBox-> setFocusPolicy ( QWidget::NoFocus ); + Layout15b->addWidget( inMuteCheckBox ); + + + Layout19a->addLayout( Layout15 ); + Layout19a->addLayout( Layout15b ); + + fillDirectoryCombo(); + + TabWidget->insertTab( tab_3, tr( "Options" ) ); + + TabWidget->insertTab( tab_5, tr( "Volume" ) ); + + } else {// landscape + + // Layout16->addWidget( dirGroup ); + // Layout18->addLayout( Layout16 ); + Layout15 = new QVBoxLayout(this); + Layout15->setSpacing( 2 ); + Layout15->setMargin( 0 ); + + Layout15b = new QVBoxLayout(this); + Layout15b->setSpacing( 2 ); + Layout15b->setMargin( 0 ); + + TextLabel2 = new QLabel( tab_3, "InputLabel" ); + TextLabel2->setText( tr( "In")); + TextLabel2->setFixedWidth(35); + Layout15->addWidget( TextLabel2 ); + + TextLabel3 = new QLabel( tab_3, "OutputLabel" ); + TextLabel3->setText( tr( "Out" ) ); + Layout15b->addWidget( TextLabel3 ); + + InputSlider = new QSlider( -100, 0, 10, 0, QSlider::Vertical, tab_3, (const char *) "InputSlider" ); + // InputSlider->setTickmarks(QSlider::Both); + Layout15->addWidget( InputSlider); + + OutputSlider = new QSlider( -100,0,10,0, QSlider::Vertical,tab_3,(const char *) "OutputSlider" ); + // OutputSlider->setTickmarks(QSlider::Both); + + Layout15b->addWidget( OutputSlider ); + + outMuteCheckBox = new QCheckBox ( "mute", tab_3 ); + Layout15->addWidget( outMuteCheckBox ); + + inMuteCheckBox = new QCheckBox ( "mute", tab_3 ); + inMuteCheckBox-> setFocusPolicy ( QWidget::NoFocus ); + Layout15b->addWidget( inMuteCheckBox ); + + + Layout19->addLayout( Layout15 ); + Layout19->addLayout( Layout15b ); + + fillDirectoryCombo(); + + TabWidget->insertTab( tab_3, tr( "Options" ) ); + + } + + + ///**********<<<<<<<<<<<<>>>>>>>>>>>>*************** + + tab_4 = new QWidget( TabWidget, "tab_4" ); + QGridLayout *layout4 = new QGridLayout( tab_4); + layout4->setSpacing( 2); + layout4->setMargin( 2); + TabWidget->insertTab( tab_4, tr( "Help")); + + ///////////////////////////////////////////// FIXME change to a real helpfile path + QString url="/index.html"; + HelpWindow *help = new HelpWindow( url, ".", tab_4, "qperec_help"); + layout4->addMultiCellWidget( help, 0, 1, 0, 1); + if( !QFile(url).exists()) { + help->hide(); + //help->showMaximized(); + QLabel *helpLabel; + helpLabel = new QLabel( tab_4, "TimeLabel" ); + layout4->addMultiCellWidget( helpLabel, 0, 3, 0, 4 ); + helpLabel->setText( "<B>QpeRec</B><br>" + "Records files in standard wav format<br>" + "or a compressed version<br>" + "For help, please email the author<br>" + "<B>QpeRec</B> is copyright© 2002 by" + " L.J. Potter<br>llornkcor@handhelds.org<BR>" + "and is licensed under the <B>QPL</B>"); + } + ///**********<<<<<<<<<<<<>>>>>>>>>>>>*************** + +} + +void QtRec::initIconView() { + + ListView1->clear(); + Config cfg("QpeRec"); + cfg.setGroup("Sounds"); + QString temp; + QPixmap image0( ( const char** ) image0_data ); + + + int nFiles = cfg.readNumEntry("NumberofFiles",0); + for(int i=1;i<= nFiles;i++) { + + QListViewItem * item; + QString fileS, mediaLocation, fileDate, filePath; + +// temp.sprintf("%d",i); + temp=cfg.readEntry(temp,""); //reads currentFile + filePath = cfg.readEntry(temp,""); //currentFileName + + QFileInfo info(filePath); + fileDate = info.lastModified().toString(); + + fileS = cfg.readEntry( filePath, "0" );// file length in seconds + mediaLocation=getStorage( filePath); + if(info.exists()) { + item = new QListViewItem( ListView1, temp, fileS, mediaLocation, fileDate); + item->setPixmap( 0, image0); + if(currentFileName == filePath) + ListView1->setSelected( item, true); + } + } +} + +void QtRec::initConnections() { + connect( qApp,SIGNAL( aboutToQuit()),SLOT( cleanUp()) ); + + connect( toBeginningButton, SIGNAL( pressed()), this, SLOT( rewindPressed() )); + connect( toBeginningButton, SIGNAL( released()), this, SLOT( rewindReleased() )); + connect( toEndButton, SIGNAL( pressed()), this, SLOT( FastforwardPressed() )); + connect( toEndButton, SIGNAL( released()), this, SLOT( FastforwardReleased() )); + connect( deleteSoundButton, SIGNAL(released()), this, SLOT( deleteSound() )); + connect( Stop_PushButton, SIGNAL(released()), this, SLOT( doPlayBtn() )); + connect( Rec_PushButton, SIGNAL(released()), this, SLOT( newSound() ) ); + connect( TabWidget, SIGNAL( currentChanged( QWidget*)),this, SLOT(thisTab(QWidget*) )); + connect( OutputSlider, SIGNAL(sliderReleased()), this, SLOT( changedOutVolume()) ); + connect( InputSlider, SIGNAL(sliderReleased()), this, SLOT( changedInVolume()) ); + + // connect( OutputSlider, SIGNAL(valueChanged( int)), this, SLOT(changedOutVolume(int)) ); + // connect( InputSlider, SIGNAL(valueChanged( int)), this, SLOT(changedInVolume(int)) ); + + connect( sampleRateComboBox, SIGNAL(activated( int)), this, SLOT( changesamplerateCombo(int)) ); + connect( bitRateComboBox, SIGNAL(activated( int)), this, SLOT( changebitrateCombo(int)) ); + connect( directoryComboBox, SIGNAL(activated( int)), this, SLOT( changeDirCombo(int)) ); + connect( sizeLimitCombo, SIGNAL(activated( int)), this, SLOT( changeSizeLimitCombo(int)) ); + connect( outMuteCheckBox, SIGNAL(toggled( bool)), this, SLOT( doVolMuting(bool)) ); + connect( inMuteCheckBox , SIGNAL(toggled( bool)), this, SLOT( doMicMuting(bool)) ); + connect( ListView1,SIGNAL(doubleClicked( QListViewItem*)),this,SLOT( itClick(QListViewItem*))); + connect( ListView1, SIGNAL( mouseButtonPressed( int, QListViewItem *, const QPoint&, int)), + this,SLOT( listPressed(int, QListViewItem *, const QPoint&, int)) ); + connect( timeSlider, SIGNAL( sliderMoved( int)), this, SLOT( changeTimeSlider(int) )); + connect( timeSlider, SIGNAL( sliderPressed( )), this, SLOT( timeSliderPressed() )); + connect( timeSlider, SIGNAL( sliderReleased( )), this, SLOT( timeSliderReleased() )); + connect( compressionCheckBox, SIGNAL( toggled(bool)),this, SLOT( compressionSelected(bool))); + connect( autoMuteCheckBox, SIGNAL( toggled(bool)),this, SLOT( slotAutoMute(bool))); +} + +void QtRec::initConfig() { + int index, fred, i; + Config cfg("QpeRec"); + cfg.setGroup("Settings"); + + index = cfg.readNumEntry("samplerate",22050); + bool ok; + + for(int ws=0;ws<sampleRateComboBox->count();ws++) { + fred = sampleRateComboBox->text(ws).toInt(&ok, 10); + if(index == fred) { + filePara.sampleRate = fred; + sampleRateComboBox->setCurrentItem(ws); + } + } + + i=cfg.readNumEntry("bitrate",16); + if(i == 16) + bitRateComboBox->setCurrentItem( 0); + else + bitRateComboBox->setCurrentItem( 1); + filePara.resolution = i; + + i=cfg.readNumEntry("sizeLimit", 5 ); + QString temp; +// for(int i=1;i<13; i++) { +// temp = sizeLimitCombo->text(i); + +// sizeLimitCombo->insertItem( QString::number(i*5)+tr(" secs")); +// } + sizeLimitCombo->setCurrentItem((i/5)); + + compressionCheckBox->setChecked( cfg.readBoolEntry("wavCompression",1)); + if( compressionCheckBox->isChecked()) { + bitRateComboBox->setEnabled(false); + bitRateComboBox->setCurrentItem(0); + filePara.resolution=16; + } + + autoMuteCheckBox->setChecked( cfg.readBoolEntry("useAutoMute",0)); + if( autoMuteCheckBox->isChecked()) + slotAutoMute(true); + else + slotAutoMute(false); + + Config cofg( "qpe"); + cofg.setGroup( "Volume"); + outMuteCheckBox->setChecked( cofg.readBoolEntry( "Mute",0)); + inMuteCheckBox->setChecked( cofg.readBoolEntry( "MicMute",0)); +} + +//================ + +void QtRec::stop() { + qDebug("<<<<<<<<<stop()"); + setRecordButton(false); + monitoring=false; + stopped=true; + + if( !recording) + endPlaying(); + else + endRecording(); + timeSlider->setValue(0); + // QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << true; // mute device +} + +void QtRec::doPlayBtn() { + + if(!stopped) { + playLabel2->setText("Play"); + stop(); + } else { + if(ListView1->currentItem() == 0) return; + playLabel2->setText("Stop"); + currentFile = ListView1->currentItem()->text(0); + start(); + } +} + +void QtRec::start() { //play + if(stopped) { + qDebug("start::"); + QPixmap image3( ( const char** ) image3_data ); + Stop_PushButton->setPixmap( image3 ); + Stop_PushButton->setDown(true); + stopped=false; + paused=false; + secCount=1; + + if( openPlayFile()) + if( setupAudio( false)) //recording is false + doPlay(); + } +} + +bool QtRec::rec() { //record + qDebug("rec()"); + if(!stopped) { + qDebug("rec:: !stopped"); + monitoring=true; + return false; + } else { + qDebug("go ahead and record"); + secCount=1; + playLabel2->setText("Stop"); + monitoring=false; + setRecordButton(true); + stopped=false; + + if( setupAudio( true)) + if(setUpFile()) { + qDebug("Ok to start recording"); + int fileSize=0; + Config cfg("QpeRec"); + cfg.setGroup("Settings"); + qDebug( "<<<<<<<Device bits %d, device rate %d, device channels %d", + soundDevice->getDeviceBits(), + soundDevice->getDeviceRate(), + soundDevice->getDeviceChannels()); + + //filePara.sampleRate = cfg.readNumEntry("samplerate", 22050); + qDebug("sample rate is %d", filePara.sampleRate); + filePara.SecondsToRecord = getCurrentSizeLimit(); + + qDebug("size limit %d sec", filePara.SecondsToRecord); + int diskSize = checkDiskSpace( (const QString &) wavFile->trackName()); + + if( filePara.SecondsToRecord == 0) { + fileSize = diskSize; + } else if( filePara.format==WAVE_FORMAT_PCM) { + qDebug("WAVE_FORMAT_PCM"); + fileSize = (filePara.SecondsToRecord ) * filePara.channels + * filePara.sampleRate *(filePara.resolution/8)+1000; + } else { + qDebug("WAVE_FORMAT_DVI_ADPCM"); + fileSize = ((filePara.SecondsToRecord) * filePara.channels + * filePara.sampleRate *(filePara.resolution/8) )/4+250; + } + + filePara.samplesToRecord = fileSize; + qDebug("filesize should be %d, bits %d, rate %d", + filePara.samplesToRecord, filePara.resolution, filePara.sampleRate); + if(paused) { + paused = false; + } + // else { + qDebug("Setting timeslider %d", filePara.samplesToRecord); + // if(fileSize != 0) + timeSlider->setRange(0, filePara.samplesToRecord); + // } + + if( diskSize < fileSize/1024) { + QMessageBox::warning(this, + tr("Low Disk Space"), + tr("You are running low of\nrecording space\n" + "or a card isn't being recognized")); + stopped = true; //we need to be stopped + stop(); + } else { + QString msg; + msg.sprintf("%d, %d, %d", filePara.sampleRate, filePara.channels, filePara.resolution); +#ifdef DEV_VERSION + setCaption( msg); +#endif + filePara.fileName=currentFile.latin1(); + qDebug("Start recording thread"); + + pthread_t thread1; + pthread_create( &thread1, NULL, (void * (*)(void *))quickRec, NULL/* &*/); +// quickRec(); + toBeginningButton->setEnabled(false); + toEndButton->setEnabled(false); + + startTimer(1000); + } + } //end setUpFile + } //end setupAudio + // _exit( 0); + + // ///* default: +// // /* pid greater than zero is parent getting the child's pid */ +// /* printf("Child's pid is %d\n",pid); +// waitpid( pid, &status, 0); +// printf("Child[%d] exited with status %d\n", pid, status);*/ + // while (wait(NULL) != pid) +// ; +// printf("child %ld terminated normally, return status is zero\n", (long) pid); + // endRecording(); +/* else { //device was not opened + qDebug("Audio device open failed"); + return false; + } + }*/ +// } //end fork +// } +// } + return true; +} +/* + This happens when a tab is selected*/ +void QtRec::thisTab(QWidget* widg) { + if(widg != NULL) { + int index=TabWidget->currentPageIndex(); + + if(index==0) { //file page + } + + if(index ==1) { //control page + fillDirectoryCombo(); +// soundDevice->getOutVol(); +// soundDevice->getInVol(); + } + + if(index==2) { //help page + } + qApp->processEvents(); + update(); + } +} + +void QtRec::getOutVol( ) { + filePara.outVol = soundDevice->getOutVolume(); + qDebug("out vol %d", filePara.outVol); + OutputSlider->setValue( -filePara.outVol); +} + +void QtRec::getInVol() { + filePara.inVol = soundDevice->getInVolume(); + qDebug("in vol %d", filePara.inVol); + InputSlider->setValue( -filePara.inVol); +} + +void QtRec::changedOutVolume() { + soundDevice->changedOutVolume(-OutputSlider->value()); +} + +void QtRec::changedInVolume( ) { + soundDevice->changedInVolume( -InputSlider->value()); +} + + +bool QtRec::setupAudio( bool b) { + bool ok; + int sampleformat, stereo, flags; + char * dspString, *mixerString; + + filePara.resolution = bitRateComboBox->currentText().toInt( &ok,10); //16 + + if( !b){ // we want to play + qDebug("setting up DSP for playing"); + if( filePara.resolution == 16 || compressionCheckBox->isChecked() ) { + sampleformat = AFMT_S16_LE; + filePara.resolution = 16; + } else { + sampleformat = AFMT_U8; + filePara.resolution=8; + } + + stereo = filePara.channels = 1; + flags= O_WRONLY; + dspString = DSPSTROUT; + mixerString = DSPSTRMIXEROUT; + } else { // we want to record + qDebug("setting up DSP for recording"); + + if( !bitRateComboBox->isEnabled() || bitRateComboBox->currentText() == "16") + sampleformat = AFMT_S16_LE; + else + sampleformat = AFMT_U8; + + if( !compressionCheckBox->isChecked()) { + filePara.format=WAVE_FORMAT_PCM; + qDebug("WAVE_FORMAT_PCM"); + } else { + filePara.format=WAVE_FORMAT_DVI_ADPCM; + sampleformat=AFMT_S16_LE; + qDebug("WAVE_FORMAT_DVI_ADPCM"); + } + + stereo = filePara.channels = 1; +// filePara.sampleRate = sampleRateComboBox->currentText().toInt( &ok,10);//44100; + flags= O_RDWR; +// flags= O_RDONLY; + dspString = DSPSTRIN; + mixerString = DSPSTRMIXEROUT; + } + + // if(soundDevice) delete soundDevice; + qDebug("<<<<<<<<<<<<<<<<<<<open dsp %d %d %d", filePara.sampleRate, filePara.channels, sampleformat); + soundDevice = new Device( this, dspString, mixerString, b); +// soundDevice->openDsp(); + soundDevice->reset(); + + qDebug("device has been made %d", soundDevice->sd); + + ////////////////// <<<<<<<<<<<<>>>>>>>>>>>> + soundDevice->setDeviceFormat( sampleformat); + soundDevice->setDeviceChannels( filePara.channels); + soundDevice->setDeviceRate( filePara.sampleRate); + soundDevice->getDeviceFragSize(); +#ifdef QT_QWS_EBX + int frag = FRAGSIZE; + soundDevice->setFragSize( frag); + soundDevice->getDeviceFragSize(); +#endif + ///////////////// + filePara.sd = soundDevice->sd; + + if ( filePara.sd == -1) { + + monitoring=false; + stopped=true; + update(); + setCaption( tr( "QpeRecord " ) + QString::number(VERSION) ); + stopped=true; + return false; + } + if(autoMute) + doMute(false); + + return true; +} + + +bool QtRec::setUpFile() { //setup file for recording + qDebug("Setting up wavfile"); +// if(wavFile) delete wavFile; + wavFile = new WavFile( this, (const QString &)"", + true, + filePara.sampleRate, + filePara.channels, + filePara.resolution, + filePara.format); + + filePara.fd = wavFile->wavHandle(); + if(filePara.fd == -1) { + return false; + } else { + filePara.channels=1; + } + return true; +} + +/// <<<<<<<<<<<<<<<< PLAY >>>>>>>>>>>>>>>>>>> +bool QtRec::doPlay() { + +// pthread_t thread2; +// pthread_create( &thread2, NULL, (void * (*)(void *))playIt, NULL/* &*/); + + // qDebug("doPlay file %d", filePara.fd); + int bytesWritten, number; + recording = false; +// int number=0; + if( !paused) { + qDebug("new"); + total=0; + bytesWritten=0; + filePara.numberOfRecordedSeconds = 0; + } else { + paused = false; + secCount = (int)filePara.numberOfRecordedSeconds; + } + playing=true; + number=0; + + QString num; +// block=BUFSIZE; + qDebug("Play number of samples %d", filePara.numberSamples); + timeSlider->setRange(0, filePara.numberSamples); + timeString.sprintf("%.2f", filePara.numberOfRecordedSeconds); + timeLabel->setText( timeString+ tr(" seconds")); + + if( filePara.format==WAVE_FORMAT_DVI_ADPCM) { + qDebug("WAVE_FORMAT_DVI_ADPCM"); + } else { + qDebug("WAVE_FORMAT_PCM"); + } + QString msg; + msg.sprintf("%d, %d, %d", filePara.sampleRate, filePara.channels, filePara.resolution); +#ifdef DEV_VERSION + setCaption( msg); +#endif + if( filePara.resolution == 16 ) { //AFMT_S16_LE) { + qDebug("16 bit"); + + startTimer(1000); + + if( filePara.format==WAVE_FORMAT_DVI_ADPCM) { + char abuf[BUFSIZE/2]; + short sbuf[BUFSIZE]; + short sbuf2[BUFSIZE*2]; + memset( abuf, 0, BUFSIZE / 2); + memset( sbuf, 0, BUFSIZE); + memset( sbuf2, 0, BUFSIZE * 2); +// <<<<<<<<<<<<<<<<<<<<<<<<<<< WAVE_FORMAT_DVI_ADPCM >>>>>>>>>>>>>>>>>>>>>> + for(;;) { // play loop + if (stopped) + break; // stop if playing was set to false + + + number=::read( filePara.fd, abuf, BUFSIZE/2); + adpcm_decoder( abuf, sbuf, number*2, &decoder_state); + +// for (int i=0;i< number * 2; 2 * i++) { //2*i is left channel +// sbuf2[i+1]=sbuf2[i]=sbuf[i]; +// } + + bytesWritten = write ( filePara.sd, sbuf, number*4); + // if(filePara.channels==1) + // total += bytesWritten/2; //mono + // else + total += bytesWritten; + timeSlider->setValue( total / 4); + + filePara.numberOfRecordedSeconds = (float)total / (float)filePara.sampleRate / 2; + + timeString.sprintf("%.2f", filePara.numberOfRecordedSeconds); +// if(filePara.numberOfRecordedSeconds>1) + timeLabel->setText( timeString+ tr(" seconds")); +// printf("playing number %d, bytes %d, total %d\n",number, bytesWritten, total/4); +// printf("playing number %d, bytes %d, total %d totalsamples %d number recorded seconds %.2f\r", +// number, bytesWritten, total/4, filePara.numberSamples, filePara.numberOfRecordedSeconds); +// fflush(stdout); + + qApp->processEvents(); + + if( bytesWritten <= 0 ){//|| secCount > filePara.numberOfRecordedSeconds ) { + stopped = true; + endPlaying(); + } + } + } else { + // <<<<<<<<<<<<<<<<<<<<<<<<<<< WAVE_FORMAT_PCM >>>>>>>>>>>>>>>>>>>>>> + short inbuffer[BUFSIZE], outbuffer[BUFSIZE]; + memset( inbuffer, 0, BUFSIZE); + memset( outbuffer, 0, BUFSIZE); + + for(;;) { // play loop + if (stopped) + break; // stop if playing was set to false + number=::read( filePara.fd, inbuffer, BUFSIZE); +// for (int i=0;i< number * 2; 2 * i++) { //2*i is left channel +// // for (int i=0;i< number ; i++) { //2*i is left channel +// outbuffer[i+1]= outbuffer[i]=inbuffer[i]; +// } + + bytesWritten = ::write( filePara.sd, inbuffer, number); + //-------------->>>> out to device + // total+=bytesWritten; + // if(filePara.channels==1) + // total += bytesWritten/2; //mono + // else + total += bytesWritten; + + timeSlider->setValue( total); + filePara.numberOfRecordedSeconds = (float)total / (float)filePara.sampleRate / (float)2; + + timeString.sprintf("%.2f",filePara.numberOfRecordedSeconds); + timeLabel->setText( timeString + tr(" seconds")); + + qApp->processEvents(); + + if( bytesWritten <= 0 && secCount > filePara.numberOfRecordedSeconds ) { + stopped = true; + endPlaying(); + } + } +// printf("\nplaying number %d, bytes %d, total %d\r",number, bytesWritten, total); +// fflush(stdout); + } //end loop + } else { /////////////////////////////// format = AFMT_U8; + unsigned char unsigned_inbuffer[BUFSIZE], unsigned_outbuffer[BUFSIZE]; + memset( unsigned_inbuffer,0,BUFSIZE); + for(;;) { // main loop + if (stopped) + break; // stop if playing was set to false + number=::read( filePara.fd, unsigned_inbuffer, BUFSIZE); +//data = (val >> 8) ^ 0x80; + // unsigned_outbuffer = (unsigned_inbuffer >> 8) ^ 0x80; + bytesWritten = write ( filePara.sd, unsigned_inbuffer, number); + total+=bytesWritten; + + timeSlider->setValue( total); + + filePara.numberOfRecordedSeconds=(float)total/(float)filePara.sampleRate; + timeString.sprintf("%.2f",filePara.numberOfRecordedSeconds); + timeLabel->setText( timeString + tr(" seconds")); + qApp->processEvents(); + + if( bytesWritten <= 0 && secCount > filePara.numberOfRecordedSeconds ) { + stopped = true; + endPlaying(); + } + // printf("Writing number %d, bytes %d, total %d, numberSamples %d\r",number, bytesWritten , total, filePara.numberSamples); + // fflush(stdout); + } + } + +// qDebug("\nstopped or paused %d", total/4); + if(!paused && !stopped) { + stopped = true; +// endPlaying(); + endPlaying(); + } + return true; +} + + +void QtRec::changebitrateCombo(int i) { + Config cfg("QpeRec"); + cfg.setGroup("Settings"); + int bits=0; + if(i==0) { bits=16; } + else { bits=8; } + cfg.writeEntry("bitrate", bits); + filePara.resolution=bits; + cfg.write(); +} + +void QtRec::changesamplerateCombo(int i) { + Config cfg("QpeRec"); + cfg.setGroup("Settings"); + int rate=0; + bool ok; + rate = sampleRateComboBox->text(i).toInt(&ok, 10); + cfg.writeEntry("samplerate",rate); + filePara.sampleRate=rate; +/* soundDevice = new Device( this, DSPSTROUT, DSPSTRMIXER, false); + soundDevice->openDsp();*/ +// +// soundDevice->setDeviceFormat(AFMT_S16_LE); +// soundDevice->setDeviceChannels(filePara.channels); +// soundDevice->setDeviceRate(filePara.sampleRate); +// +// soundDevice->closeDevice( true); +// soundDevice=0; +// delete soundDevice; + qDebug("Change sample rate %d", rate); + cfg.write(); + +} + + +void QtRec::changeDirCombo(int index) { + Config cfg("QpeRec"); + cfg.setGroup("Settings"); + QString sName = directoryComboBox->text(index); + + StorageInfo storageInfo; + const QList<FileSystem> &fs = storageInfo.fileSystems(); + QListIterator<FileSystem> it ( fs ); + QString storage; + for( ; it.current(); ++it ){ + if( sName == (*it)->name()+" "+ (*it)->path() || + (*it)->name() == sName ) { + const QString path = (*it)->path(); + recDir = path; + cfg.writeEntry("directory", recDir); + qDebug("new rec dir "+recDir); + } + } + cfg.write(); +} + + +void QtRec::changeSizeLimitCombo(int) { + Config cfg("QpeRec"); + cfg.setGroup("Settings"); + cfg.writeEntry("sizeLimit", getCurrentSizeLimit() ); + cfg.write(); +} + +void QtRec::newSound() { + qDebug("<<<<<<<<<new sound"); + + if( !rec()) { + qDebug("rec() failed"); + endRecording(); + deleteSound(); + } + +} + +void QtRec::itClick(QListViewItem *item) { + currentFile=item->text(0); + setCaption("QpeRecord "+currentFile); +} + +void QtRec::deleteSound() { + Config cfg("QpeRec"); + cfg.setGroup("Sounds"); + if( ListView1->currentItem() == NULL) + return; +#ifndef DEV_VERSION + switch ( QMessageBox::warning(this,tr("Delete"), + tr("Do you really want to <font size=+2><B>DELETE</B></font>\nthe selected file?"), + tr("Yes"),tr("No"),0,1,1) ) { + case 0: +#endif + { + QString file = ListView1->currentItem()->text(0); + // qDebug("Filename to find is "+file); + QString fileName; + fileName = cfg.readEntry( file, ""); + QFile f(fileName); + // qDebug("fileName is "+fileName); + if(f.exists()) + if( !f.remove()) + QMessageBox::message(tr("Error"),tr("Could not remove file.")); + + int nFiles = cfg.readNumEntry("NumberofFiles",0); + bool found=false; + for(int i=0;i<nFiles+1;i++) { + // qDebug(cfg.readEntry(QString::number(i))); + + if( cfg.readEntry( QString::number(i),"").find( file,0,true) != -1) { + found = true; +// qDebug( cfg.readEntry(QString::number(i))+"\n" +cfg.readEntry(QString::number(i+1)) ); + cfg.writeEntry( QString::number(i), cfg.readEntry( QString::number(i+1),"")); + } + if(found) + cfg.writeEntry( QString::number(i), cfg.readEntry( QString::number(i+1),"")); + } + + cfg.removeEntry(cfg.readEntry(file)); + cfg.removeEntry( file); + // cfg.removeEntry( QString::number(nFiles)); + cfg.writeEntry("NumberofFiles", nFiles-1); + cfg.write(); + + ListView1->takeItem( ListView1->currentItem() ); + // ListView1->takeItem( ListView1->itemAt(nFiles) ); + delete ListView1->currentItem(); + + ListView1->clear(); + ListView1->setSelected(ListView1->firstChild(), true); + initIconView(); + update(); + } +#ifndef DEV_VERSION + }; +#endif + setCaption( tr( "QpeRecord " ) + QString::number(VERSION) ); + +} + +void QtRec::keyPressEvent( QKeyEvent *e) { + + switch ( e->key() ) { + /* + vercel keys-> + right side + 0 + 1 0x1030 Key_F1 + 2 0x1031 Key_F2 + 3 0x1032 Key_F3 + 4 0x1016 Key_PageUp + 5 0x1017 Key_PageDown + 6 + --------------- + left side + Up 0x1013 Key_Up + Down 0x1015 Key_Down + Left 0x1012 Key_Left + Right 0x1014 Key_Right + 0x1010 Key_Home + + */ + // case Key_F1: + // if(stopped && !recording) + // newSound(); + // else + // stop(); + // break; + // case Key_F2: { + // if( !e->isAutoRepeat()) + // rewindPressed(); + // } + // break; + // case Key_F3: { + // if( !e->isAutoRepeat()) + // FastforwardPressed(); + // } + // break; + + ////////////////////////////// Zaurus keys + case Key_F9: //activity + break; + case Key_F10: //contacts + break; + case Key_F11: //menu + break; + case Key_F12: //home + break; + case Key_F13: //mail + break; + case Key_Space: + break; + case Key_Delete: + break; + case Key_Up: + // stop(); + break; + case Key_Down: + // newSound(); + break; + case Key_Left: { + qDebug("rewinding"); + if( !e->isAutoRepeat()) + rewindPressed(); + } + break; + case Key_Right: { + if( !e->isAutoRepeat()) + FastforwardPressed(); + } + break; + } +} + +void QtRec::keyReleaseEvent( QKeyEvent *e) { + switch ( e->key() ) { + // case Key_F1: + // if(stopped && !recording) + // newSound(); + // else + // stop(); + // break; + // case Key_F2: + // rewindReleased(); + // break; + // case Key_F3: + // FastforwardReleased(); + // break; + + ////////////////////////////// Zaurus keys + case Key_F9: //activity + break; + case Key_F10: //contacts + break; + case Key_F11: //menu + break; + case Key_F12: //home + if(stopped) + doPlayBtn(); + else + stop(); + break; + case Key_F13: //mail + break; + case Key_Space: + if(stopped && !recording) + newSound(); + else + stop(); + break; + case Key_Delete: + deleteSound(); + break; + case Key_Up: + // stop(); + qDebug("Up"); + break; + case Key_Down: + // start(); + // qDebug("Down"); + // newSound(); + break; + case Key_Left: + qDebug("Left"); + rewindReleased(); + break; + case Key_Right: + qDebug("Right"); + FastforwardReleased(); + break; + } +} + +void QtRec::endRecording() { + qDebug("endRecording"); + setRecordButton(false); + timeSlider->setValue(0); + toBeginningButton->setEnabled(true); + toEndButton->setEnabled(true); + + monitoring=false; + + killTimers(); + + if(autoMute) + doMute(true); + + soundDevice->closeDevice( true); + + recording = false; + stopped=true; + t->stop(); + + if( wavFile->track.isOpen()) { + wavFile->adjustHeaders( filePara.fd, filePara.numberSamples); + // soundDevice->sd=-1; + filePara.numberSamples=0; + // filePara.sd=-1; + wavFile->closeFile(); + filePara.fd=0; + + if(wavFile->isTempFile()) { +// move tmp file to regular file + QString cmd; + cmd.sprintf("mv "+ wavFile->trackName() + " " + wavFile->currentFileName); + qDebug("moving tmp file to "+currentFileName); + system(cmd.latin1()); + } + + qDebug("Just moved "+wavFile->currentFileName); + Config cfg("QpeRec"); + cfg.setGroup("Sounds"); + + int nFiles = cfg.readNumEntry( "NumberofFiles",0); + + currentFile = QFileInfo(wavFile->currentFileName).fileName(); + currentFile=currentFile.left(currentFile.length()-4); + + cfg.writeEntry( "NumberofFiles",nFiles+1); + cfg.writeEntry( QString::number( nFiles+1), currentFile); + cfg.writeEntry( currentFile, wavFile->currentFileName); + + QString time; + time.sprintf("%.2f", filePara.numberOfRecordedSeconds); + cfg.writeEntry( wavFile->currentFileName, time ); + qDebug("writing config numberOfRecordedSeconds "+time); + + cfg.write(); + qDebug("finished recording"); + timeLabel->setText(""); + } + + if(soundDevice) delete soundDevice; + + initIconView(); + selectItemByName(currentFile); +} + +void QtRec::endPlaying() { + + qDebug("end playing"); + setRecordButton(false); + + toBeginningButton->setEnabled(true); + toEndButton->setEnabled(true); + + if(autoMute) + doMute(true); + + soundDevice->closeDevice( false); + soundDevice->sd=-1; + // if(soundDevice) delete soundDevice; + qDebug("file and sound device closed"); + stopped=true; + recording=false; + playing=false; + timeLabel->setText(""); + monitoring=false; + total = 0; + filePara.numberSamples=0; + filePara.sd=-1; + wavFile->closeFile(); + filePara.fd=0; +// if(wavFile) delete wavFile; //this crashes + + qDebug("track closed"); + timeSlider->setValue(0); + + if(soundDevice) delete soundDevice; + +} + +bool QtRec::openPlayFile() { + + qApp->processEvents(); + if( currentFile.isEmpty()) { + QMessageBox::message(tr("Qperec"),tr("Please select file to play")); + endPlaying(); + return false; + } + QString currentFileName; + Config cfg("QpeRec"); + cfg.setGroup("Sounds"); + int nFiles = cfg.readNumEntry("NumberofFiles",0); + for(int i=0;i<nFiles+1;i++) { //look for file + if( cfg.readEntry( QString::number(i),"").find( currentFile,0,true) != -1) { + currentFileName=cfg.readEntry( currentFile, "" ); + qDebug("opening for play: "+currentFileName); + } + } + wavFile = new WavFile(this, + currentFileName, + false); + filePara.fd = wavFile->wavHandle(); + if(filePara.fd == -1) { + // if(!track.open(IO_ReadOnly)) { + QString errorMsg=(QString)strerror(errno); + monitoring=false; + setCaption( tr( "QpeRecord " ) + QString::number(VERSION) ); + QMessageBox::message(tr("Note"),tr("Could not open audio file.\n") + +errorMsg+"\n"+currentFile); + return false; + } else { + filePara.numberSamples=wavFile->getNumberSamples(); + filePara.format = wavFile->getFormat(); + // qDebug("file %d, samples %f", filePara.fd, filePara.numberSamples); + filePara.sampleRate= wavFile->getSampleRate(); + filePara.resolution=wavFile->getResolution(); + timeSlider->setPageStep(1); + monitoring=true; + timeSlider->setRange(0, filePara.numberSamples ); + filePara.numberOfRecordedSeconds=(float) filePara.numberSamples / (float)filePara.sampleRate * (float)2; + } + + return true; +} + +void QtRec::listPressed( int mouse, QListViewItem *item, const QPoint &, int ) { + if(item == NULL ) + return; + switch (mouse) { + case 1: { + if( renameBox !=0 ) //tricky + cancelRename(); + + currentFile=item->text(0); + setCaption( "QpeRecord "+currentFile); + } + break; + case 2: + showListMenu(item); + ListView1->clearSelection(); + break; + }; +} + +void QtRec::showListMenu(QListViewItem * item) { + if(item == NULL) + return; + QPopupMenu *m = new QPopupMenu(this); + m->insertItem( tr("Play"), this, SLOT( doMenuPlay() )); + if(Ir::supported()) m->insertItem( tr( "Send with Ir" ), this, SLOT( doBeam() )); + m->insertItem( tr( "Rename" ), this, SLOT( doRename() )); + // #if defined (QTOPIA_INTERNAL_FSLP) + // m->insertItem( tr( "Properties" ), this, SLOT( doProperties() )); + // #endif + m->insertSeparator(); + m->insertItem( tr("Delete"), this, SLOT( deleteSound() ) ); + m->exec( QCursor::pos() ); + qApp->processEvents(); +} + +void QtRec::fileBeamFinished( Ir *ir) { + if(ir) + QMessageBox::message( tr("Ir Beam out"), tr("Ir sent.") ,tr("Ok") ); + +} + +void QtRec::doBeam() { + qApp->processEvents(); + if( ListView1->currentItem() == NULL) + return; + Ir ir; + if( ir.supported()) { + QString file = ListView1->currentItem()->text(0); + Config cfg("QpeRec"); + cfg.setGroup("Sounds"); + + int nFiles = cfg.readNumEntry("NumberofFiles",0); + + for(int i=0;i<nFiles+1;i++) { + if( cfg.readEntry( QString::number(i),"").find(file,0,true) != -1) { + QString filePath = cfg.readEntry(file,""); + Ir *file = new Ir(this, "IR"); + connect(file, SIGNAL(done(Ir*)), this, SLOT( fileBeamFinished( Ir * ))); + file->send( filePath, "QpeRec audio file\n"+filePath ); + } + } + } +} + +void QtRec::doMenuPlay() { + qApp->processEvents(); + currentFile = ListView1->currentItem()->text(0); +} + +void QtRec::doRename() { + QRect r = ListView1->itemRect( ListView1->currentItem( )); + r = QRect( ListView1->viewportToContents( r.topLeft() ), r.size() ); + r.setX( ListView1->contentsX() ); + if ( r.width() > ListView1->visibleWidth() ) + r.setWidth( ListView1->visibleWidth() ); + + renameBox = new QLineEdit( ListView1->viewport(), "qt_renamebox" ); + renameBox->setFrame(true); + + renameBox->setText( ListView1->currentItem()->text(0) ); + + renameBox->selectAll(); + renameBox->installEventFilter( this ); + ListView1->addChild( renameBox, r.x(), r.y() ); + renameBox->resize( r.size() ); + ListView1->viewport()->setFocusProxy( renameBox ); + renameBox->setFocus(); + renameBox->show(); + +} + +void QtRec::okRename() { + qDebug("okRename"); + qDebug(renameBox->text()); + QString filename = renameBox->text(); + cancelRename(); + + if( ListView1->currentItem() == NULL) + return; + + Config cfg("QpeRec"); + cfg.setGroup("Sounds"); + + QString file = ListView1->currentItem()->text(0); + + qDebug("filename is " + filename); + + int nFiles = cfg.readNumEntry("NumberofFiles",0); + + for(int i=0;i<nFiles+1;i++) { //look for file + if( cfg.readEntry( QString::number(i),"").find(file,0,true) != -1) { + + QString filePath = cfg.readEntry(file,""); + + cfg.writeEntry( QString::number(i), filename ); + cfg.writeEntry( filename, filePath ); + cfg.removeEntry(file); + cfg.write(); + } + } + + ListView1->takeItem( ListView1->currentItem() ); + delete ListView1->currentItem(); + ListView1->clear(); + initIconView(); + update(); +} + +void QtRec::cancelRename() { + qDebug("cancel rename"); + bool resetFocus = ListView1->viewport()->focusProxy() == renameBox; + delete renameBox; + renameBox = 0; + if ( resetFocus ) { + ListView1->viewport()->setFocusProxy( ListView1 ); + ListView1->setFocus(); + } +} + +bool QtRec::eventFilter( QObject * o, QEvent * e ) { + if ( o->inherits( "QLineEdit" ) ) { + if ( e->type() == QEvent::KeyPress ) { + QKeyEvent *ke = (QKeyEvent*)e; + if ( ke->key() == Key_Return || + ke->key() == Key_Enter ) { + okRename(); + return true; + } else if ( ke->key() == Key_Escape ) { + cancelRename(); + return true; + } + } else if ( e->type() == QEvent::FocusOut ) { + cancelRename(); + return true; + } + } + return QWidget::eventFilter( o, e ); +} + + +int QtRec::getCurrentSizeLimit() { + return sizeLimitCombo->currentItem() * 5; +} + +void QtRec::timerBreak() { + qDebug("timer break"); + stop(); +} + +void QtRec::doVolMuting(bool b) { + Config cfg( "qpe" ); + cfg. setGroup( "Volume" ); + cfg.writeEntry( "Mute",b); + cfg.write(); + QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << b; +} + +void QtRec::doMicMuting(bool b) { + // qDebug("mic mute"); + Config cfg( "qpe" ); + cfg. setGroup( "Volume" ); + cfg.writeEntry( "MicMute",b); + cfg.write(); + QCopEnvelope( "QPE/System", "micChange(bool)" ) << b; +} + +void QtRec::compressionSelected(bool b) { + Config cfg("QpeRec"); + cfg.setGroup("Settings"); + cfg.writeEntry("wavCompression", b); + cfg.writeEntry("bitrate",16); filePara.resolution=16; + cfg.write(); + + if(b) { + bitRateComboBox->setEnabled(false); + bitRateComboBox->setCurrentItem(0); + filePara.resolution=16; + } else{ + bitRateComboBox->setEnabled(true); + } +} + +long QtRec::checkDiskSpace(const QString &path) { + + struct statfs fs; + + if ( !statfs( path.latin1(), &fs ) ) { + + int blkSize = fs.f_bsize; + int availBlks = fs.f_bavail; + + long mult = blkSize / 1024; + long div = 1024 / blkSize; + + if ( !mult ) mult = 1; + if ( !div ) div = 1; + + return availBlks * mult / div; + } + return -1; +} + +// short f_fstyp; /* File system type */ +// long f_bsize; /* Block size */ +// long f_frsize; /* Fragment size */ +// long f_blocks; /* Total number of blocks*/ +// long f_bfree; /* Count of free blocks */ +// long f_files; /* Total number of file nodes */ +// long f_ffree; /* Count of free file nodes */ +// char f_fname[6]; /* Volumename */ +// char f_fpack[6]; /* Pack name */ + +void QtRec::receive( const QCString &msg, const QByteArray & ) { + qDebug("Voicerecord received message "+msg); + +} + + +///////////////////////////// timerEvent +void QtRec::timerEvent( QTimerEvent *e ) { +// qDebug( "%d", secCount ); +#ifdef DEV_VERSION + QString msg; + msg.sprintf("%d, %d, %d", filePara.sampleRate, filePara.channels, filePara.resolution); + setCaption( msg +" :: "+QString::number(secCount)); +#endif + + if( !playing ) { + if(!recording ){ + killTimer(e->timerId()); +///* stopped=true; +// recording=false; +///*/ +// _exit( 0); + } + if(filePara.SecondsToRecord < secCount && filePara.SecondsToRecord !=0) { + killTimer(e->timerId()); + stop(); + } + } +// if( stopped && !paused) { +// if( filePara.numberOfRecordedSeconds < secCount) { +// stopped = true; +// // playing=false; +// killTimer(e->timerId()); +// endPlaying(); +// } +// } +// qApp->processEvents(); + secCount++; +} + +void QtRec::changeTimeSlider(int index) { + if(ListView1->currentItem() == 0 || !wavFile->track.isOpen()) return; + // qDebug("Slider moved to %d",index); + paused = true; + stopped = true; + + sliderPos=index; + + QString timeString; + filePara.numberOfRecordedSeconds=(float)sliderPos/(float)filePara.sampleRate*(float)2; + timeString.sprintf( "%.2f", filePara.numberOfRecordedSeconds); + secCount = (int)filePara.numberOfRecordedSeconds; + timeLabel->setText( timeString+ tr(" seconds")); +} + +void QtRec::timeSliderPressed() { + if(ListView1->currentItem() == 0) return; + // qDebug("slider pressed"); + paused = true; + stopped = true; +} + +void QtRec::timeSliderReleased() { + if(ListView1->currentItem() == 0) return; + sliderPos=timeSlider->value(); + + // qDebug("slider released %d", sliderPos); + stopped = false; + int newPos = lseek( filePara.fd, sliderPos, SEEK_SET); + total = newPos*4; + filePara.numberOfRecordedSeconds=(float)sliderPos/(float)filePara.sampleRate*(float)2; + + doPlay(); +} + +void QtRec::rewindPressed() { + if(ListView1->currentItem() == 0) return; + if( !wavFile->track.isOpen()) { + if( !openPlayFile() ) + return; + else + if( !setupAudio( false)) + return; + } else { + killTimers(); + paused = true; + stopped = true; + rewindTimer->start(50, false); + } +} + +void QtRec::rewindTimerTimeout() { + int sliderValue = timeSlider->value(); + sliderValue = sliderValue-(filePara.numberSamples/100); + // if(toBeginningButton->isDown()) + timeSlider->setValue( sliderValue ) ; + // qDebug("%d", sliderValue); + QString timeString; + filePara.numberOfRecordedSeconds=(float)sliderValue/(float)filePara.sampleRate*(float)2; + timeString.sprintf( "%.2f", filePara.numberOfRecordedSeconds); + timeLabel->setText( timeString+ tr(" seconds")); +} + +void QtRec::rewindReleased() { + rewindTimer->stop(); + if( wavFile->track.isOpen()) { + sliderPos=timeSlider->value(); + stopped = false; + int newPos = lseek( filePara.fd, sliderPos, SEEK_SET); + total = newPos*4; + // qDebug("rewind released %d", total); + startTimer(1000); + doPlay(); + } +} + +void QtRec::FastforwardPressed() { + if(ListView1->currentItem() == 0) return; + if( !wavFile->track.isOpen()) + if( !openPlayFile() ) + return; + else + if( !setupAudio( false)) + return; + killTimers(); + + paused = true; + stopped = true; + forwardTimer->start(50, false); +} + + +void QtRec::forwardTimerTimeout() { + int sliderValue = timeSlider->value(); + sliderValue = sliderValue +(filePara.numberSamples/100); + + // if(toEndButton->isDown()) + timeSlider->setValue(sliderValue); + + QString timeString; + filePara.numberOfRecordedSeconds=(float)sliderValue/(float)filePara.sampleRate*(float)2; + timeString.sprintf( "%.2f", filePara.numberOfRecordedSeconds); + timeLabel->setText( timeString+ tr(" seconds")); +} + +void QtRec::FastforwardReleased() { + forwardTimer->stop(); + if( wavFile->track.isOpen()) { + sliderPos=timeSlider->value(); + stopped = false; + int newPos = lseek( filePara.fd, sliderPos, SEEK_SET); + total = newPos*4; + filePara.numberOfRecordedSeconds=(float)sliderPos/(float)filePara.sampleRate*(float)2; + startTimer(1000); + doPlay(); + } +} + + +QString QtRec::getStorage(const QString &fileName) { + + StorageInfo storageInfo; + const QList<FileSystem> &fs = storageInfo.fileSystems(); + QListIterator<FileSystem> it ( fs ); + QString storage; + for( ; it.current(); ++it ){ + const QString name = (*it)->name(); + const QString path = (*it)->path(); + const QString disk = (*it)->disk(); + if( fileName.find(path,0,true) != -1) + storage=name; + // const QString options = (*it)->options(); + // if( name.find( tr("Internal"),0,true) == -1) { + // storageComboBox->insertItem( name +" -> "+disk); + // qDebug(name); + } + return storage; + // struct mntent *me; + // // if(fileName == "/etc/mtab") { + // FILE *mntfp = setmntent( fileName.latin1(), "r" ); + // if ( mntfp ) { + // while ( (me = getmntent( mntfp )) != 0 ) { + // QString filesystemType = me->mnt_type; + + // } + // } + // endmntent( mntfp ); +} + +void QtRec::setRecordButton(bool b) { + + if(b) { //about to record or play + + Rec_PushButton->setDown(true); + QPixmap image3( ( const char** ) image3_data ); + Stop_PushButton->setPixmap( image3 ); + if(Stop_PushButton->isDown()) + Stop_PushButton->setDown(true); + playLabel2->setText("Stop"); + + } else { //about to stop + + QPixmap image4( ( const char** ) image4_data ); + Stop_PushButton->setPixmap( image4); + if(Stop_PushButton->isDown()) + Stop_PushButton->setDown(false); + playLabel2->setText("Play"); + if(Rec_PushButton->isDown()) + Rec_PushButton->setDown( false); + } +} + +void QtRec::fillDirectoryCombo() { + if( directoryComboBox->count() > 0) + directoryComboBox->clear(); + int index=0; + Config cfg("QpeRec"); + cfg.setGroup("Settings"); + QString dir= cfg.readEntry("directory", "/"); + StorageInfo storageInfo; + const QList<FileSystem> &fs = storageInfo.fileSystems(); + QListIterator<FileSystem> it ( fs ); + QString storage; + for( ; it.current(); ++it ){ + const QString name = (*it)->name(); + const QString path = (*it)->path(); + // directoryComboBox->insertItem(name+" "+path); + directoryComboBox->insertItem(name); + if(path==dir) + directoryComboBox->setCurrentItem(index); + index++; + } +} + +void QtRec::errorStop() { + stopped = true; + wavFile->closeFile(); + killTimers(); +} + +void QtRec::doMute(bool b) { + doVolMuting( b); + doMicMuting( b); +} + +void QtRec::slotAutoMute(bool b) { + autoMute=b; + Config cfg("QpeRec"); + cfg.setGroup("Settings"); + cfg.writeEntry("useAutoMute",b); + doMute(b); + outMuteCheckBox->setChecked( b); + inMuteCheckBox->setChecked( b); +} + +void QtRec::selectItemByName(const QString & name) { + QListViewItemIterator it( ListView1 ); + for ( ; it.current(); ++it ) + if(name == it.current()->text(0)) + ListView1->setCurrentItem(it.current()); +} + + +long findPeak(long input ) { + +// halfLife = time in seconds for output to decay to half value after an impulse + static float output = 0.0; + int halfLife = .25; + float vsf = .0025; + float scalar = pow( 0.5, 1.0/(halfLife * filePara.sampleRate )); + if( input < 0.0 ) + input = -input; // Absolute value. + if ( input >= output ) + { + // When we hit a peak, ride the peak to the top. + output = input; + } + else + { +// Exponential decay of output when signal is low. + output = output * scalar; +// +// When current gets close to 0.0, set current to 0.0 to prevent FP underflow +// which can cause a severe performance degradation due to a flood +// of interrupts. +// + if( output < vsf ) output = 0.0; + } + + return output; +} diff --git a/noncore/multimedia/opierec/qtrec.h b/noncore/multimedia/opierec/qtrec.h new file mode 100644 index 0000000..d0623d0 --- a/dev/null +++ b/noncore/multimedia/opierec/qtrec.h @@ -0,0 +1,185 @@ +/**************************************************************************** + ** Created: Thu Jan 17 11:19:45 2002 +copyright 2002 by L.J. Potter ljp@llornkcor.com +****************************************************************************/ +#ifndef QTREC_H +#define QTREC_H +#define VERSION 20021202 + +#include <qpe/ir.h> + +#include <iostream.h> +#include <qfile.h> +#include <qimage.h> +#include <qlineedit.h> +#include <qpixmap.h> +#include <qvariant.h> +#include <qwidget.h> +#include <stdio.h> +#include <stdlib.h> + +#include "device.h" +#include "wavFile.h" + +class QButtonGroup; +class QCheckBox; +class QComboBox; +class QGridLayout; +class QGroupBox; +class QHBoxLayout; +class QIconView; +class QIconViewItem; +class QLabel; +class QLabel; +class QListView; +class QListViewItem; +class QPushButton; +class QSlider; +class QTabWidget; +class QTimer; +class QVBoxLayout; +class QLineEdit; + +#define MAX_TRACKS 2 +//#define BUFSIZE 4096 +// #define BUFSIZE 8182 //Z default buffer size +#define BUFSIZE 1024 +//#define BUFSIZE 2048 +#define FRAGSIZE 0x7fff000A; + +#define WAVE_FORMAT_DVI_ADPCM (0x0011) +#define WAVE_FORMAT_PCM (0x0001) +//AFMT_IMA_ADPCM + +class QtRec : public QWidget +{ + Q_OBJECT + +public: + QtRec( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~QtRec(); + QSlider *OutputSlider,*InputSlider; + +public slots: +private: +// int fragment; + int fd1; + int secCount; + QString timeString; + + QLineEdit *renameBox; + QGroupBox* GroupBox1; + QString currentFile; + QString date, currentFileName, tmpFileName; + QTimer *t_timer; + bool needsStereoOut, paused, playing; + bool useTmpFile, autoMute; + + bool eventFilter( QObject * , QEvent * ); + void okRename(); + void cancelRename(); + QString getStorage(const QString &); + bool rec(); + int getCurrentSizeLimit(); + long checkDiskSpace(const QString &); + void doMute(bool); + void errorStop(); + void fillDirectoryCombo(); + void getInVol(); + void getOutVol(); + void init(); + void initConfig(); + void initConnections(); + void selectItemByName(const QString &); + void setRecordButton(bool); + void start(); + void stop(); + void timerEvent( QTimerEvent *e ); + +private slots: + + + void FastforwardPressed(); + void FastforwardReleased(); + void changeDirCombo(int); + void changeSizeLimitCombo(int); + void changeTimeSlider(int); + void changebitrateCombo(int); + void changedInVolume(); + void changedOutVolume(); + void changesamplerateCombo(int); + void cleanUp(); + void compressionSelected(bool); + void deleteSound(); + void doBeam(); + void doMenuPlay(); + void doMicMuting(bool); + void doPlayBtn(); + void doRename(); + void doVolMuting(bool); + void forwardTimerTimeout(); + void itClick(QListViewItem *item); + void listPressed(int, QListViewItem *, const QPoint&, int); + void newSound(); + void rewindPressed(); + void rewindReleased(); + void rewindTimerTimeout(); + void slotAutoMute(bool); + void thisTab(QWidget*); + void timeSliderPressed(); + void timeSliderReleased(); + void timerBreak(); +/* void changedOutVolume(int); */ +/* void changedInVolume(int); */ + +protected: + + Device *soundDevice; + WavFile *wavFile; + + QButtonGroup *ButtonGroup1; + QCheckBox *outMuteCheckBox, *inMuteCheckBox, *compressionCheckBox, *autoMuteCheckBox; + QComboBox* sampleRateComboBox, * bitRateComboBox, *directoryComboBox, *sizeLimitCombo; + QHBoxLayout* Layout12; + QHBoxLayout* Layout13; + QHBoxLayout* Layout14; + QHBoxLayout* Layout16; + QHBoxLayout* Layout17; + QHBoxLayout* Layout19; + QIconView *IconView1; + QLabel *NewSoundLabel,*playLabel2; + QLabel *TextLabel3, *TextLabel1, *TextLabel2; + QListView *ListView1; + QPushButton *Stop_PushButton, *Play_PushButton, *Rec_PushButton, *NewSoundButton, *deleteSoundButton, *toBeginningButton, *toEndButton; + QString recDir; + QTabWidget *TabWidget; + QTimer *t, *rewindTimer, *forwardTimer; + QVBoxLayout* Layout15; + QVBoxLayout* Layout15b; + QVBoxLayout* Layout18; + QWidget *tab, *tab_2, *tab_3, *tab_4, *tab_5; + int sliderPos, total; +// short inbuffer[BUFSIZE], outbuffer[BUFSIZE]; +// unsigned short unsigned_inbuffer[BUFSIZE], unsigned_outbuffer[BUFSIZE]; + QGroupBox *sampleGroup, *bitGroup, *dirGroup, *sizeGroup; +/* short inbuffer[65536], outbuffer[65536]; */ +/* unsigned short unsigned_inbuffer[65536], unsigned_outbuffer[65536]; */ + + + bool doPlay(); + bool openPlayFile(); + bool setUpFile(); + bool setupAudio( bool b); + void endPlaying(); + void endRecording(); + void fileBeamFinished( Ir *ir); + void initIconView(); + void keyPressEvent( QKeyEvent *e); + void keyReleaseEvent( QKeyEvent *e); + void receive( const QCString &, const QByteArray & ); + void showListMenu(QListViewItem * ); +// void quickRec(); + +}; + +#endif // QTREC_H diff --git a/noncore/multimedia/opierec/wavFile.cpp b/noncore/multimedia/opierec/wavFile.cpp new file mode 100644 index 0000000..09695aa --- a/dev/null +++ b/noncore/multimedia/opierec/wavFile.cpp @@ -0,0 +1,303 @@ +//wavFile.cpp +#include "wavFile.h" +#include "qtrec.h" + +#include <qdatetime.h> +#include <qstring.h> +#include <qmessagebox.h> +#include <qdir.h> + +#include <qpe/timestring.h> +#include <qpe/config.h> + +#include <errno.h> + +#include <sys/time.h> +#include <sys/types.h> +#include <sys/vfs.h> + +#include <fcntl.h> +#include <math.h> +#include <mntent.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +WavFile::WavFile( QObject * parent,const QString &fileName, bool makeNwFile, int sampleRate, + int channels, int resolution, int format ) + : QObject( parent) +{ +qDebug("new wave file"); + bool b = makeNwFile; + wavSampleRate=sampleRate; + wavFormat=format; + wavChannels=channels; + wavResolution=resolution; + useTmpFile=false; + if( b) { + newFile(); + } else { + openFile(fileName); + } +} + +bool WavFile::newFile() { + + qDebug("Set up new file"); + Config cfg("QpeRec"); + cfg.setGroup("Settings"); + + currentFileName=cfg.readEntry("directory",QDir::homeDirPath()); + QString date; + date = TimeString::dateString( QDateTime::currentDateTime(),false,true); + date.replace(QRegExp("'"),""); + date.replace(QRegExp(" "),"_"); + date.replace(QRegExp(":"),"."); + date.replace(QRegExp(","),""); + + QString currentFile=date; + if(currentFileName.right(1).find("/",0,true) == -1) + currentFileName += "/" + date; + else + currentFileName += date; + currentFileName+=".wav"; + + qDebug("set up file for recording: "+currentFileName); + char *pointer; + + if( currentFileName.find("/mnt",0,true) == -1 + && currentFileName.find("/tmp",0,true) == -1 ) { + // if destination file is most likely in flash (assuming jffs2) + // we have to write to a different filesystem first + + useTmpFile = true; + pointer=tmpnam(NULL); + qDebug("Opening tmp file %s",pointer); + track.setName( pointer); + + } else { //just use regular file.. no moving + + useTmpFile = false; + track.setName( currentFileName); + } + if(!track.open( IO_ReadWrite | IO_Truncate)) { + QString errorMsg=(QString)strerror(errno); + qDebug(errorMsg); + QMessageBox::message("Note", "Error opening file.\n" +errorMsg); + + return false; + } else { + setWavHeader( track.handle() , &hdr); + } +return true; +} + +WavFile::~WavFile() { + + closeFile(); +} + +void WavFile::closeFile() { + if(track.isOpen()) + track.close(); +} + +int WavFile::openFile(const QString ¤tFileName) { + qDebug("open play file "+currentFileName); + closeFile(); + + track.setName(currentFileName); + + if(!track.open(IO_ReadOnly)) { + QString errorMsg=(QString)strerror(errno); + qDebug("<<<<<<<<<<< "+errorMsg+currentFileName); + QMessageBox::message("Note", "Error opening file.\n" +errorMsg); + return -1; + } else { + parseWavHeader( track.handle()); + } + return track.handle(); +} + +bool WavFile::setWavHeader(int fd, wavhdr *hdr) { + + strncpy((*hdr).riffID, "RIFF", 4); // RIFF + strncpy((*hdr).wavID, "WAVE", 4); //WAVE + strncpy((*hdr).fmtID, "fmt ", 4); // fmt + (*hdr).fmtLen = 16; // format length = 16 + + if( wavFormat == WAVE_FORMAT_PCM) { + (*hdr).fmtTag = 1; // PCM + qDebug("set header WAVE_FORMAT_PCM"); + } + else { + (*hdr).fmtTag = WAVE_FORMAT_DVI_ADPCM; //intel ADPCM + qDebug("set header WAVE_FORMAT_DVI_ADPCM"); + } + + // (*hdr).nChannels = 1;//filePara.channels;// ? 2 : 1*/; // channels + (*hdr).nChannels = wavChannels;// ? 2 : 1*/; // channels + + (*hdr).sampleRate = wavSampleRate; //samples per second + (*hdr).avgBytesPerSec = (wavSampleRate)*( wavChannels*(wavResolution/8)); // bytes per second + (*hdr).nBlockAlign = wavChannels*( wavResolution/8); //block align + (*hdr).bitsPerSample = wavResolution; //bits per sample 8, or 16 + + strncpy((*hdr).dataID, "data", 4); + + write( fd,hdr, sizeof(*hdr)); + qDebug("writing header: bitrate%d, samplerate %d, channels %d", + wavResolution, wavSampleRate, wavChannels); + return true; +} + +bool WavFile::adjustHeaders(int fd, int total) { + lseek(fd, 4, SEEK_SET); + int i = total + 36; + write( fd, &i, sizeof(i)); + lseek( fd, 40, SEEK_SET); + write( fd, &total, sizeof(total)); + qDebug("adjusting header %d", total); + return true; +} + +int WavFile::parseWavHeader(int fd) { + qDebug("Parsing wav header"); + char string[4]; + int found; + short fmt; + unsigned short ch, bitrate; + unsigned long samplerrate, longdata; + + if (read(fd, string, 4) < 4) { + qDebug(" Could not read from sound file.\n"); + return -1; + } + if (strncmp(string, "RIFF", 4)) { + qDebug(" not a valid WAV file.\n"); + return -1; + } + lseek(fd, 4, SEEK_CUR); + if (read(fd, string, 4) < 4) { + qDebug("Could not read from sound file.\n"); + return -1; + } + if (strncmp(string, "WAVE", 4)) { + qDebug("not a valid WAV file.\n"); + return -1; + } + found = 0; + + while (!found) { + if (read(fd, string, 4) < 4) { + qDebug("Could not read from sound file.\n"); + return -1; + } + if (strncmp(string, "fmt ", 4)) { + if (read(fd, &longdata, 4) < 4) { + qDebug("Could not read from sound file.\n"); + return -1; + } + lseek(fd, longdata, SEEK_CUR); + } else { + lseek(fd, 4, SEEK_CUR); + if (read(fd, &fmt, 2) < 2) { + qDebug("Could not read format chunk.\n"); + return -1; + } + if (fmt != WAVE_FORMAT_PCM && fmt != WAVE_FORMAT_DVI_ADPCM) { + qDebug("Wave file contains unknown format." + " Unable to continue.\n"); + return -1; + } + wavFormat = fmt; + // compressionFormat=fmt; + qDebug("compressionFormat is %d", fmt); + if (read(fd, &ch, 2) < 2) { + qDebug("Could not read format chunk.\n"); + return -1; + } else { + wavChannels = ch; + qDebug("File has %d channels", ch); + } + if (read(fd, &samplerrate, 4) < 4) { + qDebug("Could not read from format chunk.\n"); + return -1; + } else { + wavSampleRate = samplerrate; + // sampleRate = samplerrate; + qDebug("File has samplerate of %d",(int) samplerrate); + } + lseek(fd, 6, SEEK_CUR); + if (read(fd, &bitrate, 2) < 2) { + qDebug("Could not read format chunk.\n"); + return -1; + } else { + wavResolution=bitrate; + // resolution = bitrate; + qDebug("File has bitrate of %d", bitrate); + } + found++; + } + } + found = 0; + while (!found) { + if (read(fd, string, 4) < 4) { + qDebug("Could not read from sound file.\n"); + return -1; + } + + if (strncmp(string, "data", 4)) { + if (read(fd, &longdata, 4)<4) { + qDebug("Could not read from sound file.\n"); + return -1; + } + + lseek(fd, longdata, SEEK_CUR); + } else { + if (read(fd, &longdata, 4) < 4) { + qDebug("Could not read from sound file.\n"); + return -1; + } else { + wavNumberSamples = longdata; + qDebug("file has length of %d \nlasting %d seconds", longdata, + (( longdata / wavSampleRate) / wavChannels) / ( wavChannels*( wavResolution/8)) ); +// wavSeconds = (( longdata / wavSampleRate) / wavChannels) / ( wavChannels*( wavResolution/8)); + + return longdata; + } + } + } + + lseek(fd, 0, SEEK_SET); + + return 0; +} + +QString WavFile::trackName() { + return track.name(); +} + +int WavFile::wavHandle(){ + return track.handle(); +} + +int WavFile::getFormat() { +return wavFormat; +} + +int WavFile::getResolution() { +return wavResolution; +} + +int WavFile::getSampleRate() { +return wavSampleRate; +} + +int WavFile::getNumberSamples() { +return wavNumberSamples; +} + +bool WavFile::isTempFile() { +return useTmpFile; +} diff --git a/noncore/multimedia/opierec/wavFile.h b/noncore/multimedia/opierec/wavFile.h new file mode 100644 index 0000000..51366ec --- a/dev/null +++ b/noncore/multimedia/opierec/wavFile.h @@ -0,0 +1,56 @@ +//wavFile.h +#ifndef WAVFILE_H +#define WAVFILE_H + +#include <qobject.h> +#include <sys/soundcard.h> +#include <qfile.h> +#include <qstring.h> + +typedef struct { + char riffID[4]; + unsigned long riffLen; + char wavID[4]; + char fmtID[4]; + unsigned long fmtLen; + unsigned short fmtTag; + unsigned short nChannels; + unsigned long sampleRate; + unsigned long avgBytesPerSec; + unsigned short nBlockAlign; + unsigned short bitsPerSample; + char dataID[4]; + unsigned long dataLen; + } wavhdr; + + +class WavFile : public QObject { +Q_OBJECT +public: + WavFile( QObject * parent=0,const QString &fileName=0, bool newFile=true, int sampleRate = 0, + int channels = 0, int resolution = 0, int format=0); + ~WavFile(); + wavhdr hdr; + bool adjustHeaders(int fd, int total); + QString currentFileName; + QString trackName(); + + QFile track; + int wavHandle(); + int getFormat(); + int getResolution(); + int getSampleRate(); + int getNumberSamples(); + bool isTempFile(); + int openFile(const QString &); + bool newFile(); + void closeFile(); + +private: + int wavFormat, wavChannels, wavResolution, wavSampleRate, wavNumberSamples; + bool useTmpFile; + bool setWavHeader(int fd, wavhdr *hdr); + int parseWavHeader(int fd); +}; + +#endif |