diff options
Diffstat (limited to 'soundserver/artscat.cpp')
-rw-r--r-- | soundserver/artscat.cpp | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/soundserver/artscat.cpp b/soundserver/artscat.cpp new file mode 100644 index 0000000..c6818c8 --- /dev/null +++ b/soundserver/artscat.cpp @@ -0,0 +1,244 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + 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 <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <iostream> +#include <cstdlib> + +using namespace std; +using namespace Arts; + +int cfgSamplingRate = 44100; +int cfgBits = 16; +int cfgChannels = 2; +string cfgTitle = "artscat"; + +class Sender : public ByteSoundProducerV2_skel, + public StdSynthModule, + public IONotify +{ +protected: + FILE *pfile; + int pfd; + int packets; + bool waiting; + queue< DataPacket<mcopbyte>* > wqueue; +public: + Sender(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); + } + + ~Sender() + { + if(waiting) Dispatcher::the()->ioManager()->remove(this,IOType::read); + } + + long samplingRate() { return cfgSamplingRate; } + long channels() { return cfgChannels; } + long bits() { return cfgBits; } + bool finished() { return (pfile == 0); } + string title() { return cfgTitle; } + + void streamStart() + { + /* + * start streaming + */ + outdata.setPull(packets, packetCapacity); + } + + enum { packetCapacity = 4096 }; + void handle_eof() + { + /* + * cleanup + */ + outdata.endPull(); + pclose(pfile); + pfile = 0; + pfd = 0; + + /* + * remove all packets from the wqueue + */ + while(!wqueue.empty()) + { + DataPacket<mcopbyte> *packet = wqueue.front(); + packet->size = 0; + packet->send(); + wqueue.pop(); + } + + /* + * go out of the waiting mode + */ + if(waiting) + { + Dispatcher::the()->ioManager()->remove(this,IOType::read); + waiting = false; + } + + /* + * terminate dispatcher to end the program + */ + Dispatcher::the()->terminate(); + } + void request_outdata(DataPacket<mcopbyte> *packet) + { + if(!waiting) + { + packet->size = read(pfd, packet->contents, packetCapacity); + if(packet->size > 0) + { + // got something - done here + packet->send(); + return; + } + Dispatcher::the()->ioManager()->watchFD(pfd,IOType::read,this); + waiting = true; + } + + wqueue.push(packet); + } + + void notifyIO(int,int) + { + assert(waiting); + + DataPacket<mcopbyte> *packet = wqueue.front(); + packet->size = read(pfd, packet->contents, packetCapacity); + assert(packet->size >= 0); + if(packet->size == 0) { + handle_eof(); + return; + } + packet->send(); + + wqueue.pop(); + + if(wqueue.empty()) + { + Dispatcher::the()->ioManager()->remove(this,IOType::read); + waiting = false; + } + } +}; + +static void exitUsage(const char *progname) +{ + fprintf(stderr,"usage: %s [ options ] [ <filename> ]\n",progname); + fprintf(stderr,"-r <samplingrate> set samplingrate to use\n"); + fprintf(stderr,"-b <bits> set number of bits (8 or 16)\n"); + fprintf(stderr,"-c <channels> set number of channels (1 or 2)\n"); + fprintf(stderr,"-t <title> set stream title\n"); + fprintf(stderr,"-v show version\n"); + fprintf(stderr,"-h display this help and exit\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + bool titleSetByUser = false; + int optch; + while((optch = getopt(argc,argv,"r:b:c:t:hv")) > 0) + { + switch(optch) + { + case 'r': + cfgSamplingRate = atoi(optarg); + break; + case 'b': + cfgBits = atoi(optarg); + break; + case 'c': + cfgChannels = atoi(optarg); + break; + case 't': + cfgTitle = optarg; + titleSetByUser = true; + break; + case 'v': + printf("artscat %s\n",ARTS_VERSION); + exit(0); + break; + case 'h': + default: + exitUsage(argc?argv[0]:"artscat"); + break; + } + } + + FILE *infile = stdin; + + if (optind < argc) + { + string filename = argv[optind]; + if(filename != "-") + { + infile = fopen(filename.c_str(),"r"); + if(!infile) + { + cerr << "Can't open file '" << argv[optind] << "'." << endl; + exit(1); + } + if(!titleSetByUser) cfgTitle = filename; + } + } + Dispatcher dispatcher; + SimpleSoundServer server(Reference("global:Arts_SimpleSoundServer")); + + if(server.isNull()) + { + cerr << "Can't connect to sound server" << endl; + return 1; + } + + ByteSoundProducerV2 sender = ByteSoundProducerV2::_from_base(new Sender(infile,server.minStreamBufferTime())); + server.attach(sender); + sender.start(); + dispatcher.run(); + server.detach(sender); +} |