diff options
Diffstat (limited to 'soundserver/soundserverv2_impl.cpp')
-rw-r--r-- | soundserver/soundserverv2_impl.cpp | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/soundserver/soundserverv2_impl.cpp b/soundserver/soundserverv2_impl.cpp new file mode 100644 index 0000000..105f858 --- /dev/null +++ b/soundserver/soundserverv2_impl.cpp @@ -0,0 +1,386 @@ + /* + + Copyright (C) 2001 Jeff Tranter + 2001 Stefan Westerfeld + + 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 "artsflow.h" +#include "flowsystem.h" +#include "audiosubsys.h" +#include "connect.h" +#include "debug.h" +#include "soundserverv2_impl.h" +#include "artsversion.h" +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <dirent.h> +#include <errno.h> +#include <fstream> +#include <set> +#include <cstring> +#include <cstdlib> + +#include "config.h" + +using namespace Arts; +using namespace std; + +SoundServerV2_impl::SoundServerV2_impl() + : _sampleStorage(SampleStorage( + MCOPUtils::createFilePath("artsd-samples"),true)) +{ + checkNewObjects(); +} + +std::string SoundServerV2_impl:: audioMethod() { + return AudioSubSystem::the()->audioIO(); +} + +long SoundServerV2_impl:: samplingRate() { + return AudioSubSystem::the()->samplingRate(); +} + +long SoundServerV2_impl:: channels() { + return AudioSubSystem::the()->channels(); +} + +long SoundServerV2_impl:: bits() { + return AudioSubSystem::the()->bits(); +} + +bool SoundServerV2_impl:: fullDuplex() { + return AudioSubSystem::the()->fullDuplex(); +} + +std::string SoundServerV2_impl:: audioDevice() { + return AudioSubSystem::the()->deviceName(); +} + +long SoundServerV2_impl::fragments() { + return AudioSubSystem::the()->fragmentCount(); +} + +long SoundServerV2_impl::fragmentSize() { + return AudioSubSystem::the()->fragmentSize(); +} + +long SoundServerV2_impl::autoSuspendSeconds() { + return autoSuspendTime; +} + +void SoundServerV2_impl::autoSuspendSeconds(long int newValue) { + autoSuspendTime = newValue; +} + +std::string SoundServerV2_impl::version() { + return ARTS_VERSION; +} + +long SoundServerV2_impl::bufferSizeMultiplier() { + return bufferMultiplier; +} + +void SoundServerV2_impl::bufferSizeMultiplier(long newValue) { + bufferMultiplier = newValue; +} + +StereoVolumeControl SoundServerV2_impl::outVolume() { + return _outVolume; +} + +SampleStorage SoundServerV2_impl::sampleStorage() { + return _sampleStorage; +} + +PlayObject SoundServerV2_impl::createPlayObjectForURL(const std::string& url, const std::string& mimetype, bool createBUS) +{ + arts_debug("search playobject, mimetype = %s", mimetype.c_str()); + + TraderQuery query; + query.supports("Interface","Arts::PlayObject"); + query.supports("MimeType", mimetype); + + string objectType; + + vector<TraderOffer> *offers = query.query(); + if(!offers->empty()) + objectType = offers->front().interfaceName(); // first offer + + delete offers; + + /* + * create a PlayObject and connect it + */ + if(!objectType.empty()) + { + arts_debug("creating %s to play file", objectType.c_str()); + + PlayObject result = SubClass(objectType); + if(result.loadMedia(url)) + { + if(createBUS) + { + // TODO: check for existence of left & right streams + Synth_BUS_UPLINK uplink; + uplink.busname("out_soundcard"); + connect(result,"left",uplink,"left"); + connect(result,"right",uplink,"right"); + uplink.start(); + result._node()->start(); + result._addChild(uplink,"uplink"); + return result; + } + else + return result; + } + else arts_warning("couldn't load file %s", url.c_str()); + } + else arts_warning("mimetype %s unsupported", mimetype.c_str()); + + return PlayObject::null(); +} + +PlayObject SoundServerV2_impl::createPlayObjectForStream(InputStream instream, const std::string& mimetype, bool createBUS) +{ + arts_debug("search streamplayobject, mimetype = %s", mimetype.c_str()); + + TraderQuery query; + query.supports("Interface","Arts::StreamPlayObject"); + query.supports("MimeType", mimetype); + + string objectType; + + vector<TraderOffer> *offers = query.query(); + if(!offers->empty()) + objectType = offers->front().interfaceName(); // first offer + + delete offers; + + /* + * create a PlayObject and connect it + */ + if(!objectType.empty()) + { + arts_debug("creating %s to play file", objectType.c_str()); + + StreamPlayObject result = SubClass(objectType); + result.streamMedia(instream); + + if(createBUS) + { + // TODO: check for existence of left & right streams + Synth_BUS_UPLINK uplink; + uplink.busname("out_soundcard"); + connect(result,"left",uplink,"left"); + connect(result,"right",uplink,"right"); + uplink.start(); + result._node()->start(); + result._addChild(uplink,"uplink"); + return result; + } + else + return result; + } + else arts_warning("mimetype %s unsupported for streaming", mimetype.c_str()); + + return PlayObject::null(); +} + +static void clearDirectory(const string& directory) +{ + DIR *dir = opendir(directory.c_str()); + if(!dir) return; + + struct dirent *de; + while((de = readdir(dir)) != 0) + { + string currentEntry = directory + "/" + de->d_name; + + if(de->d_name[0] != '.') + { + unlink(currentEntry.c_str()); + } + } + closedir(dir); +} + +/* copied from mcopidl */ +static void doTypeIndex(string dir, string prefix, ModuleDef& module) +{ + FILE *typeIndex = fopen((dir+"/"+prefix+".mcopclass").c_str(),"w"); + + vector<string> supportedTypes; + + vector<InterfaceDef>::iterator ii; + for(ii = module.interfaces.begin(); ii != module.interfaces.end(); ii++) + supportedTypes.push_back(ii->name); + + vector<TypeDef>::iterator ti; + for(ti = module.types.begin(); ti != module.types.end(); ti++) + supportedTypes.push_back(ti->name); + + string supportedTypesList; + vector<string>::iterator si; + bool first = true; + for(si = supportedTypes.begin(); si != supportedTypes.end(); si++) + { + if(!first) supportedTypesList += ","; + + supportedTypesList += (*si); + first = false; + } + fprintf(typeIndex, "# this file was generated by artsd - do not edit\n"); + fprintf(typeIndex,"Type=%s\n",supportedTypesList.c_str()); + fprintf(typeIndex,"TypeFile=%s.mcoptype\n",prefix.c_str()); + fclose(typeIndex); +} + +void SoundServerV2_impl::checkNewObjects() +{ + const char *home = getenv("HOME"); + arts_return_if_fail(home != 0); + + string dir = home + string("/.mcop/trader-cache"); + string dataVersionFileName = dir + "/cache-data-version"; + + mkdir(home,0755); + mkdir((home+string("/.mcop")).c_str(),0755); + if(mkdir(dir.c_str(),0755) != 0) + { + string why = strerror(errno); + + struct stat st; + stat(dir.c_str(),&st); + if(!S_ISDIR(st.st_mode)) + { + arts_warning("can't create directory %s to fill it with" + " trader data (%s)", dir.c_str(), why.c_str()); + return; + } + } + + TraderQuery query; + query.supports("Interface", "Arts::Loader"); + vector<TraderOffer> *offers = query.query(); + vector<TraderOffer>::iterator i; + + set<string> newDataVersion, cacheDataVersion; + for(i = offers->begin(); i != offers->end(); i++) + { + // TODO: error checking? + Arts::Loader loader = SubClass(i->interfaceName()); + newDataVersion.insert(loader.dataVersion()); + } + + /* change this line if you change the cache update code */ + newDataVersion.insert("Cache-Update-Code-Version:1.0"); + + /* load cache-data-version file */ + { + ifstream infile(dataVersionFileName.c_str()); + + string line; + while(infile >> line) + cacheDataVersion.insert(line); + } + + /* if it differs, rebuild trader cache */ + if(cacheDataVersion != newDataVersion) + { + clearDirectory(dir); + + /* save new cache-data-version file */ + { + ofstream out(dataVersionFileName.c_str()); + + set<string>::iterator i; + for(i = newDataVersion.begin(); i != newDataVersion.end(); i++) + out << *i << endl; + } + rebuildTraderCache(dir, offers); + } + delete offers; +} + +void SoundServerV2_impl::rebuildTraderCache(const string& directory, + vector<TraderOffer> *offers) +{ + vector<TraderOffer>::iterator i; + + for(i = offers->begin(); i != offers->end(); i++) + { + // TODO: error checking? + Arts::Loader loader = SubClass(i->interfaceName()); + + /* put trader-information in ~/.mcop/trader-cache */ + vector<TraderEntry> *entries = loader.traderEntries(); + vector<TraderEntry>::iterator ei; + for(ei = entries->begin(); ei != entries->end(); ei++) + { + const TraderEntry& entry = *ei; + + FILE *traderFile = fopen((directory+"/"+entry.interfaceName+".mcopclass").c_str(),"w"); + fprintf(traderFile, "# this file was generated by artsd - do not edit\n"); + vector<string>::const_iterator li; + for(li = entry.lines.begin(); li != entry.lines.end(); li++) + fprintf(traderFile,"%s\n", li->c_str()); + + fclose(traderFile); + } + delete entries; + + /* put type-information in ~/.mcop/trader-cache */ + vector<ModuleDef> *modules = loader.modules(); + vector<ModuleDef>::iterator mi; + for(mi = modules->begin(); mi != modules->end(); mi++) + { + Arts::ModuleDef& module = *mi; + + Buffer b; + module.writeType(b); + + FILE *typeFile = fopen((directory + "/" + module.moduleName+".arts.mcoptype").c_str(),"w"); + unsigned long towrite = b.size(); + fwrite(b.read(towrite),1,towrite,typeFile); + fclose(typeFile); + + doTypeIndex(directory,module.moduleName+".arts",module); + } + delete modules; + } + Dispatcher::the()->reloadTraderData(); +} + +float SoundServerV2_impl::cpuUsage() +{ + return CPUUsage::the()->usage() * 100.0; +} + + +#ifndef __SUNPRO_CC +/* See bottom of simplesoundserver_impl.cpp for the reason this is here. */ +REGISTER_IMPLEMENTATION(SoundServerV2_impl); +#endif |