/* Copyright (C) 2000 Stefan Westerfeld stefan@space.twc.de 2001 Matthias Kretz kretz@kde.org 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Permission is also granted to link this program with the Qt library, treating Qt like a library that normally accompanies the operating system kernel, whether or not that is in fact the case. */ #include "soundserver.h" #include "stdsynthmodule.h" #include "artsversion.h" #include "debug.h" #include #include #include #include #include using namespace std; using namespace Arts; int cfgSamplingRate = 44100; int cfgBits = 16; int cfgChannels = 2; class Receiver : public ByteSoundReceiver_skel, public StdSynthModule, public IONotify { protected: FILE *pfile; int pfd; int packets; bool waiting; queue< DataPacket* > wqueue; public: Receiver(FILE *input,float minStreamBufferTime) : pfile(input), waiting(false) { pfd = fileno(pfile); int rc = fcntl(pfd, F_SETFL, O_NONBLOCK); assert(rc != -1); /* * calculate stream buffer parameters */ float streamBufferTime; packets = 7; do { packets++; streamBufferTime = (float)(packets * packetCapacity * 1000) / (float)(samplingRate() * channels() * 2); } while(streamBufferTime < minStreamBufferTime); } ~Receiver() { if(waiting) Dispatcher::the()->ioManager()->remove(this,IOType::write); } long samplingRate() { return cfgSamplingRate; } long channels() { return cfgChannels; } long bits() { return cfgBits; } bool finished() { return (pfile == 0); } string title() { return "artsrec"; } enum { packetCapacity = 4096 }; void process_indata(DataPacket *packet) { if(!waiting) { int size = write( pfd, packet->contents, packet->size ); if( size != packet->size ) { arts_debug( "Not written enough" ); //Dispatcher::the()->ioManager()->watchFD(pfd,IOType::write,this); //waiting = true; } packet->processed(); return; } wqueue.push(packet); } void notifyIO(int,int) { #if 0 assert(waiting); DataPacket *packet = wqueue.front(); packet->size = read(pfd, packet->contents, packetCapacity); assert(packet->size >= 0); if(packet->size == 0) { return; } packet->send(); wqueue.pop(); if(wqueue.empty()) { Dispatcher::the()->ioManager()->remove(this,IOType::write); waiting = false; } #endif } }; static void exitUsage(const char *progname) { fprintf(stderr,"usage: %s [ options ] [ ]\n",progname); fprintf(stderr,"-r set samplingrate to use\n"); fprintf(stderr,"-b set number of bits (8 or 16)\n"); fprintf(stderr,"-c set number of channels (1 or 2)\n"); fprintf(stderr,"-v show version\n"); fprintf(stderr,"-h display this help and exit\n"); exit(1); } int main(int argc, char **argv) { int optch; while((optch = getopt(argc,argv,"r:b:c:hv")) > 0) { switch(optch) { case 'r': cfgSamplingRate = atoi(optarg); break; case 'b': cfgBits = atoi(optarg); break; case 'c': cfgChannels = atoi(optarg); break; case 'v': printf("artsrec %s\n",ARTS_VERSION); exit(0); break; case 'h': default: exitUsage(argc?argv[0]:"artsrec"); break; } } FILE *outfile = stdout; if (optind < argc) { string filename = argv[optind]; if(filename != "-") { outfile = fopen(filename.c_str(),"w"); if(!outfile) { cerr << "Can't open file '" << argv[optind] << "'." << endl; exit(1); } } } Dispatcher dispatcher; SimpleSoundServer server(Reference("global:Arts_SimpleSoundServer")); if(server.isNull()) { cerr << "Can't connect to sound server" << endl; return 1; } ByteSoundReceiver receiver = ByteSoundReceiver::_from_base(new Receiver(outfile,server.minStreamBufferTime())); server.attachRecorder(receiver); receiver.start(); dispatcher.run(); receiver.stop(); server.detachRecorder(receiver); }