Remove ancient trunk folder from svn repository
[synfig.git] / synfig-studio / trunk / src / gtkmm / audiocontainer.cpp
diff --git a/synfig-studio/trunk/src/gtkmm/audiocontainer.cpp b/synfig-studio/trunk/src/gtkmm/audiocontainer.cpp
deleted file mode 100644 (file)
index 70d5dd9..0000000
+++ /dev/null
@@ -1,1429 +0,0 @@
-/* === S Y N F I G ========================================================= */
-/*!    \file audiocontainer.cpp
-**     \brief Audio Container implementation File
-**
-**     $Id$
-**
-**     \legal
-**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**
-**     This package 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 package 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.
-**     \endlegal
-*/
-/* ========================================================================= */
-
-/* === H E A D E R S ======================================================= */
-
-#ifdef USING_PCH
-#      include "pch.h"
-#else
-#ifdef HAVE_CONFIG_H
-#      include <config.h>
-#endif
-
-#include <algorithm>
-#include <sigc++/signal.h>
-
-#include <ETL/stringf>
-#include <ETL/clock>
-//#include <ETL/thread>
-#include <glibmm/thread.h>
-
-#include <synfig/general.h>
-
-#include <glibmm/main.h>
-
-#include "audiocontainer.h"
-
-#include <cstdio>
-#include <sys/stat.h>
-#include <errno.h>
-
-#include <set>
-#include <vector>
-
-#ifdef WITH_FMOD
-#include <fmod.h>
-#endif
-
-#include "general.h"
-
-#endif
-
-/* === U S I N G =========================================================== */
-
-using namespace std;
-using namespace etl;
-using namespace synfig;
-
-/* === M A C R O S ========================================================= */
-#ifdef __WIN32
-#else //linux...
-#define AUDIO_OUTPUT   FSOUND_OUTPUT_OSS
-#endif
-
-/* === G L O B A L S ======================================================= */
-const double delay_factor = 3;
-
-/* === P R O C E D U R E S ================================================= */
-
-/* === M E T H O D S ======================================================= */
-
-/* === E N T R Y P O I N T ================================================= */
-
-//Help constructing stuff
-struct FSOUND_SAMPLE;
-using studio::AudioContainer;
-
-#ifdef WITH_FMOD
-bool build_profile(FSOUND_SAMPLE *sample, double &samplerate, std::vector<char> &samples)
-#else
-bool build_profile(FSOUND_SAMPLE */*sample*/, double &/*samplerate*/, std::vector<char> &/*samples*/)
-#endif
-{
-#ifdef WITH_FMOD
-
-       float sps = samplerate;
-
-       //trivial rejection...
-       if(!sample || sps < 1)
-       {
-               synfig::warning("build_profile: Sample rate was too low or sample was invalid");
-               return false;
-       }
-
-       //lock for all samples and process them into a subset
-       unsigned int mode = FSOUND_Sample_GetMode(sample);
-
-       //make sure that it's 8 bit... I hope this works...
-
-       //sample rate of the actual song...
-       int allsamplerate = 0;
-       FSOUND_Sample_GetDefaults(sample,&allsamplerate,0,0,0);
-
-       //get the size of the sample defaults from the mode
-       int channels = 1;
-       int channelsize = 1; //number of bytes
-
-       if(mode & FSOUND_16BITS) channelsize = 2; //this shouldn't happen
-       if(mode & FSOUND_STEREO) channels = 2;
-
-       //Get the sample information
-       int samplesize = channels*channelsize; //the only two things that increase samplesize
-       int numsamples = FSOUND_Sample_GetLength(sample); //number of samples in the sound
-       int sizeall = samplesize*numsamples; //should be the size of the entire song...
-
-       if(sizeall <= 0)
-       {
-               synfig::warning("ProfileAudio: Sample buffer cannot be size smaller than 1 (%X)",FSOUND_GetError());
-               return false;
-       }
-
-       //be sure that the new sample rate is less than or equal to the original
-       if(sps > allsamplerate) sps = allsamplerate;
-
-       float stride = allsamplerate/(float)sps;
-
-       //down sampling to 8 bit min/max values
-       synfig::warning("About to downsample from %d Hz to %.1f Hz, sample stride: %f", allsamplerate, sps, stride);
-
-       char *sampledata=0,*useless = 0;
-       unsigned int len1,len2;
-       // vector<char> samples;
-       {
-               if(!FSOUND_Sample_Lock(sample,0,sizeall,(void**)&sampledata,(void**)&useless,&len1,&len2))
-               {
-                       synfig::warning("ProfileAudio: Unable to lock the sound buffer... (%X)",FSOUND_GetError());
-                       return false;
-               }
-               synfig::warning("Locked: %X: %d bytes, %X: %d bytes",sampledata,len1,useless,len2);
-
-               if(channelsize == 1)
-               {
-                       //process the data
-                       char *iter = sampledata;
-                       char *end = iter + sizeall;
-
-                       float curaccum = 0;
-                       float numinc = sps/(float)allsamplerate;
-
-                       /* Loop per sample DDA alg.
-                       */
-
-                       int i = 0;
-
-                       //HACK - to prevent if statement inside inner loop
-                       //synfig::warning("wo baby wo baby, inc: %d, stride: %f, size: %d", inc, stride, sizeall);
-                       while(iter < end)
-                       {
-                               int maxs = 0, mins = 0;
-
-                               for(;curaccum < 1; curaccum += numinc)
-                               {
-                                       for(i = 0; iter < end && i < channels; ++i, iter += channelsize)
-                                       {
-                                               maxs = std::max(maxs,(int)*iter);
-                                               mins = std::min(mins,(int)*iter);
-                                       }
-                               }
-                               //insert onto new list
-                               samples.push_back(maxs);
-                               samples.push_back(mins);
-
-                               //and flush all the used samples for curaccum
-                               curaccum -= 1;
-                       }
-               }else if(channelsize == 2)
-               {
-                       //process the data
-                       char *iter = sampledata;
-                       char *end = iter + sizeall;
-
-                       float curaccum = 0;
-                       float numinc = sps/(float)allsamplerate;
-
-                       /* Loop per sample DDA alg.
-                       */
-
-                       int i = 0;
-
-                       //HACK - to prevent if statement inside inner loop
-                       //synfig::warning("wo baby wo baby, inc: %d, stride: %f, size: %d", inc, stride, sizeall);
-                       while(iter < end)
-                       {
-                               int maxs = 0, mins = 0;
-
-                               for(;curaccum < 1; curaccum += numinc)
-                               {
-                                       for(i = 0; iter < end && i < channels; ++i, iter += channelsize)
-                                       {
-                                               maxs = std::max(maxs,(int)*(short*)iter);
-                                               mins = std::min(mins,(int)*(short*)iter);
-                                       }
-                               }
-                               //insert onto new list
-                               samples.push_back(maxs / 256);
-                               samples.push_back(mins / 256);
-
-                               //and flush all the used samples for curaccum
-                               curaccum -= 1;
-                       }
-               }
-       }
-
-       synfig::warning("Stats: %f seconds with %d bytes now %d bytes", (samples.size()/2)/sps, sizeall, samples.size());
-       synfig::warning("               %f seconds before", numsamples/(float)allsamplerate);
-
-       //we're done yay!, unlock
-       FSOUND_Sample_Unlock(sample,sampledata,useless,len1,len2);
-       synfig::info("Unlocked");
-
-       //FSOUND_PlaySound(FSOUND_FREE,sound); //test
-
-       //we're done
-       samplerate = sps*2; //it must be x2 because we are sampling max and min
-
-       return true;
-
-       #else
-
-       return false;
-
-       #endif
-}
-
-
-//FMOD Systemwide Specific data mostly here...
-
-struct scrubinfo;
-
-#ifdef WITH_FMOD
-static double  buffer_length_sec = 0;
-
-//------- Scrubbing --------------
-/* Scrubbing works as follows:
-
-       The sound is played using PlaySoundEx
-               we specify a user created DSP for scrubbing
-               set it initially to inactive
-
-       When the program initiates it
-               we set the initial data in the shared structure and activate the dsp unit
-               then for each cursor update we get we set the value in the shared structure
-*/
-
-/* Things to check:
-       If IsPlaying just governs the channel play/stop value or if it also concerns the pause state
-
-*/
-
-//so we can know where to create all this stuff
-struct scrubinfo
-{
-       /*      Linearly fit the frequency to hit the desired zero point...
-       */
-       /*struct scrubelement
-       {
-               double  pos;
-               double  dt;
-               //the amount of time left til the cursor hits this one
-               //      it's incremental so that the cursor must pass previous
-               //      ones before decrementing this value
-       };
-       */
-
-       //the time it should take to get to the next position...
-
-       //to prevent from writing to the same location at once... (pos, deltatime, delaystart)
-       //Glib::Mutex   lock;
-
-       //the queue system would provide a more accurate representation...
-       volatile double pos;
-       volatile double deltatime;
-
-       volatile double delaystart; //the amount of time we need to go before we start interpolating...
-
-       volatile int    channel;
-
-       /*std::list<scrubelement>       queue;
-
-       volatile int    channel;
-
-       //current position is FSOUND_GetCurrentPosition and current time is always 0...
-
-       void add(const scrubelement &elem)
-       {
-               lock.LockWrite();
-
-               queue.push_back(elem);
-
-               lock.UnlockWrite();
-       }
-
-       //Function to safely get rid of all the old samples (dt < 0)
-       void flush()
-       {
-               lock.LockWrite();
-
-               while(queue.size() && queue.front().dt < 0)
-               {
-                       queue.pop_front();
-               }
-
-               lock.UnlockWrite();
-       }*/
-
-       void Lock()
-       {
-               //lock.lock();
-       }
-
-       void Unlock()
-       {
-               //lock.unlock();
-       }
-
-       //All parameters and state should be set by the time we get here...
-       void scrub_dsp_process()
-       {
-               const double epsilon = 1e-5;
-
-               //Trivial reject... we go nowhere if we aren't playing (hit boundary...)
-               if(!FSOUND_IsPlaying(channel)) return;
-
-               //Get rid of all the old samples
-               //flush();
-
-               //Trivial reject #2 - We also go nowhere with no future samples (pause)
-               /*if(queue.size() <= 0)
-               {
-                       FSOUND_SetPaused(channel,true);
-                       return;
-               }*/
-
-               double dt = buffer_length_sec;
-
-               //Lock ourselves so we don't die
-               Lock();
-
-               //printf("DSP data: delay = %.3f s, pos = %d, dt = %.3f\n", delaystart, (int)pos, deltatime);
-
-               //Check delay
-               if(delaystart > 0)
-               {
-                       delaystart -= dt;
-
-                       if(delaystart < 0)
-                       {
-                               dt = -delaystart; //add time back...
-                               delaystart = 0;
-                       }
-               }
-
-               //Trivial reject for if we're past current sample...
-               if(delaystart > 0 || deltatime <= 0)
-               {
-                       FSOUND_SetPaused(channel,true);
-                       Unlock();
-                       return;
-               }
-
-               //Calculate stretched frequency based on delayed future sample...
-
-               //NOTE: BY NOT TRACKING POSITION AS A FLOAT AND JUST USING THE SOUNDS VALUE
-               //              WE ARE LOSING A TINY AMOUNT OF PRECISION ACCURACY EVERY UPDATE
-               //              (THIS SHOULDN'T BE A PROBLEM)
-               const double p0 = FSOUND_GetCurrentPosition(channel);
-               double curdp = 0;
-
-               if(!FSOUND_GetPaused(channel))
-               {
-                       curdp = FSOUND_GetFrequency(channel) * deltatime;
-               }
-
-               //need to rescale derivative...
-
-               //Extrapolate from difference in position and deltatime vs dt...
-               const double pa = p0 + curdp/2;
-
-               const double p1 = pos;
-
-               //const double pb = p0/3 + p1*2/3;
-
-               //will extrapolate if needed... (could be funky on a curve)
-               double t = 0;
-               if(deltatime > epsilon)
-               {
-                       t = dt / deltatime;
-               }
-
-               //Decrement deltatime (we may have gone past but that's what happens when we don't get input...)
-               deltatime -= dt;
-
-               //we don't need to look at the current variables anymore...
-               Unlock();
-
-               const double invt = 1-t;
-               //double deltapos = (p1-p0)*t; //linear version
-               double deltapos = invt*invt*p0 + 2*t*invt*pa + t*t*p1 - p0; //quadratic smoothing version
-
-               //Attempted cubic smoothing
-               //const double invt2 = invt*invt;
-               //const double t2 = t*t;
-               //double deltapos = invt2*invt*p0 + 3*t*invt2*pa + 3*t2*invt*pb + t2*t*p1;
-               //double deltapos = p0 + t*(3*(pa-p0) + t*(3*(p0+2*pa+pb) + t*((p1-3*pb+3*ba-p0)))); //unwound cubic
-
-               //printf("\ttime = %.2f; p(%d,%d,%d) dp:%d - delta = %d\n",t,(int)p0,(int)p1,(int)p2,(int)curdp,(int)deltapos);
-
-               //Based on the delta info calculate the stretched frequency
-               const int dest_samplesize = FSOUND_DSP_GetBufferLength();
-
-               //rounded to nearest frequency... (hopefully...)
-               int freq = (int)(deltapos * FSOUND_GetOutputRate() / (double)dest_samplesize);
-
-               //NOTE: WE MIGHT WANT TO DO THIS TO BE MORE ACCURATE BUT YEAH... ISSUES WITH SMALL NUMBERS
-               //double newdp = deltapos / t;
-
-               //printf("\tfreq = %d Hz\n", freq);
-
-               // !If I failed... um assume we have to pause it... ?
-               if(abs(freq) < 100)
-               {
-                       FSOUND_SetPaused(channel,true);
-               }else
-               {
-                       //synfig::info("DSP f = %d Hz", freq);
-                       FSOUND_SetPaused(channel,false);
-                       if(!FSOUND_SetFrequency(channel,freq))
-                       {
-                               //ERROR WILL ROBINSON!!!...
-                               printf("Error in Freq... what do I do?\n");
-                       }
-               }
-       }
-};
-
-struct scrubuserdata
-{
-       /* //for use with multiple
-       //each one is a 'handle' to a pointer that will be effected by something else
-       typedef scrubinfo**     value_type;
-       typedef std::set< value_type > scrubslist;
-       scrubslist              scrubs;
-
-       //so we can lock access to the list...
-       ReadWriteLock   lock;
-
-       void AddScrub(scrubinfo **i)
-       {
-               lock.LockWrite();
-               scrubs.insert(i);
-               lock.UnLockWrite();
-       }
-
-       void RemoveScrub(scrubinfo **i)
-       {
-               lock.LockWrite();
-               scrubs.erase(i);
-               lock.UnLockWrite();
-       }*/
-
-       scrubinfo * volatile *  scrub;
-};
-
-//Scrubbing data structures
-static const int               default_scrub_priority = 5; //between clear and sfx/music mix
-static scrubuserdata   g_scrubdata = {0};
-static FSOUND_DSPUNIT  *scrubdspunit = 0;
-
-void * scrubdspwrap(void *originalbuffer, void *newbuffer, int length, void *userdata)
-{
-       //std::string   dsp = "DSP";
-       if(userdata)
-       {
-               scrubuserdata &sd = *(scrubuserdata*)userdata;
-
-               /* //For use with multiple scrubs...
-               //Lock so no one can write to it while we're reading from it...
-               sd.lock.LockRead();
-
-               //make a copy of it...
-               std::vector<scrubinfo**>        v(sd.scrubs.begin(),sd.scrubs.end());
-
-               //other things can do stuff with it again...
-               sd.lock.UnLockRead();
-
-               //loop through the list and process all the active scrub units
-               std::vector<scrubinfo**>::iterator      i = v.begin(),
-                                                                                       end = v.end();
-               for(;i != end; ++i)
-               {
-                       //check to make sure this object is active...
-                       if(*i && **i)
-                       {
-                               (**i)->scrub_dsp_process();
-                       }
-               }
-               */
-
-               if(sd.scrub && *sd.scrub)
-               {
-                       //dsp += " processing...";
-                       scrubinfo * info = (*sd.scrub);
-                       info->scrub_dsp_process();
-               }
-       }
-
-       //synfig::info(dsp);
-
-       return newbuffer;
-}
-
-//------- Class for loading fmod on demand -------
-
-class FMODInitializer
-{
-       bool loaded;
-       int     refcount;
-
-public:
-       FMODInitializer():loaded(false),refcount(0) {}
-       ~FMODInitializer()
-       {
-               clear();
-       }
-
-       void addref()
-       {
-               if(!loaded)
-               {
-                       #ifdef WITH_FMOD
-                       synfig::info("Initializing FMOD on demand...");
-
-                       {
-                               FSOUND_SetOutput(AUDIO_OUTPUT);
-
-                               /*int numdrivers = FSOUND_GetNumDrivers();
-                               synfig::info("Num FMOD drivers = %d",numdrivers);
-                               synfig::info("Current Driver is #%d", FSOUND_GetDriver());
-
-                               for(int i = 0; i < numdrivers; ++i)
-                               {
-                                       unsigned int caps = 0;
-                                       FSOUND_GetDriverCaps(i,&caps);
-
-                                       synfig::info("   Caps for driver %d (%s) = %x",i,FSOUND_GetDriverName(i),caps);
-                               }
-
-                               FSOUND_SetDriver(0);*/
-
-                               //Modify buffer size...
-                               //FSOUND_SetBufferSize(100);
-
-                               if(!FSOUND_Init(44100, 32, 0))
-                               {
-                                       synfig::warning("Unable to load FMOD");
-                               }else
-                               {
-                                       loaded = true;
-
-                                       //Create the DSP for processing scrubbing...
-                                       scrubdspunit = FSOUND_DSP_Create(&scrubdspwrap,default_scrub_priority,&g_scrubdata);
-
-                                       //Load the number of sec per buffer into the global variable...
-                                       buffer_length_sec = FSOUND_DSP_GetBufferLength() / (double)FSOUND_GetOutputRate();
-                               }
-                       }
-                       #endif
-               }
-
-               //add to the refcount
-               ++refcount;
-               //synfig::info("Audio: increment fmod refcount %d", refcount);
-       }
-
-       void decref()
-       {
-               if(refcount <= 0)
-               {
-                       synfig::warning("FMOD refcount is already 0...");
-               }else
-               {
-                       --refcount;
-                       //synfig::info("Audio: decrement fmod refcount %d", refcount);
-
-                       //NOTE: UNCOMMENT THIS IF YOU WANT FMOD TO UNLOAD ITSELF WHEN IT ISN'T NEEDED ANYMORE...
-                       flush();
-               }
-       }
-
-       bool is_loaded() const { return loaded; }
-
-       void clear()
-       {
-               refcount = 0;
-               flush();
-       }
-
-       void flush()
-       {
-               if(loaded && refcount <= 0)
-               {
-                       #ifdef WITH_FMOD
-                       synfig::info("Unloading FMOD");
-                       if(scrubdspunit) FSOUND_DSP_Free(scrubdspunit);
-                       FSOUND_Close();
-                       #endif
-                       loaded = false;
-               }
-       }
-};
-
-//The global counter for FMOD....
-FMODInitializer                fmodinit;
-
-#endif
-
-//----- AudioProfile Implementation -----------
-void studio::AudioProfile::clear()
-{
-       samplerate = 0;
-       samples.clear();
-}
-
-handle<AudioContainer> studio::AudioProfile::get_parent() const
-{
-       return parent;
-}
-
-void studio::AudioProfile::set_parent(etl::handle<AudioContainer> i)
-{
-       parent = i;
-}
-
-double studio::AudioProfile::get_offset() const
-{
-       if(parent)
-               return parent->get_offset();
-       return 0;
-}
-
-//---------- AudioContainer definitions ---------------------
-
-struct studio::AudioContainer::AudioImp
-{
-       //Sample load time information
-       FSOUND_SAMPLE *         sample;
-       int                                     channel;
-       int                                     sfreq;
-       int                                     length;
-
-       //Time information
-       double                          offset; //time offset for playing...
-
-       //We don't need it now that we've adopted the play(t) time schedule...
-       //current time... and playing info....
-       //float                         seekpost;
-       //bool                          useseekval;
-
-       //Make sure to sever our delayed start if we are stopped prematurely
-       sigc::connection        delaycon;
-
-       //Action information
-       bool                            playing;
-       double                          curscrubpos;
-       etl::clock                      timer;  //for getting the time diff between scrub input points
-
-       //Scrubbing information...
-       //the current position of the sound will be sufficient for normal stuff...
-       #ifdef WITH_FMOD
-       scrubinfo                       scrinfo;
-       #endif
-
-       scrubinfo                       *scrptr;
-
-       bool is_scrubbing() const {return scrptr != 0;}
-#ifdef WITH_FMOD
-       void set_scrubbing(bool s)
-#else
-       void set_scrubbing(bool /*s*/)
-#endif
-       {
-               #ifdef WITH_FMOD
-               if(s)
-                       scrptr = &scrinfo;
-               else
-               #endif
-               scrptr = 0;
-       }
-
-       //helper to make sure we are actually playing (and to get a new channel...)
-       bool init_play()
-       {
-               #ifdef WITH_FMOD
-               if(!FSOUND_IsPlaying(channel))
-               {
-                       if(sample)
-                       {
-                               //play sound paused etc.
-                               channel = FSOUND_PlaySoundEx(FSOUND_FREE,sample,0,true);
-                               if(channel < 0 || FSOUND_GetError() != FMOD_ERR_NONE)
-                               {
-                                       synfig::warning("Could not play the sample...");
-                                       return false;
-                               }
-                       }
-               }else
-               {
-                       FSOUND_SetPaused(channel,true);
-                       FSOUND_SetFrequency(channel,sfreq);
-               }
-               return true;
-
-               #else
-
-               return false;
-
-               #endif
-       }
-
-public: //structors
-       AudioImp()
-       :sample(0),
-       channel(0),
-       sfreq(0),
-       length(0),
-       offset(0),
-       playing(false),
-       scrptr(0)
-       {
-               //reuse the channel...
-               #ifdef WITH_FMOD
-               channel = FSOUND_FREE;
-               #endif
-       }
-
-       ~AudioImp()
-       {
-               clear();
-       }
-
-public: //helper/accessor funcs
-       bool start_playing_now() //callback for timer...
-       {
-               #ifdef WITH_FMOD
-               if(playing)
-               {
-                       //Make sure the sound is playing and if it is un pause it...
-                       if(init_play())
-                               FSOUND_SetPaused(channel,false);
-               }
-               #endif
-
-               return false; //so the timer doesn't repeat itself
-       }
-
-       bool isRunning()
-       {
-               #ifdef WITH_FMOD
-               return FSOUND_IsPlaying(channel);
-               #else
-               return false;
-               #endif
-       }
-
-       bool isPaused()
-       {
-#ifdef WITH_FMOD
-               return FSOUND_GetPaused(channel);
-#else
-               return false;
-#endif
-       }
-
-
-public: //forward interface
-
-       //Accessors for the offset - in seconds
-       const double &get_offset() const {return offset;}
-       void set_offset(const double &d)
-       {
-               offset = d;
-       }
-
-       //Will override the parameter timevalue if the sound is running, and not if it's not...
-#ifdef WITH_FMOD
-       bool get_current_time(double &out)
-#else
-       bool get_current_time(double &/*out*/)
-#endif
-       {
-               if(isRunning())
-               {
-                       #ifdef WITH_FMOD
-                       unsigned int pos = FSOUND_GetCurrentPosition(channel);
-
-                       //adjust back by 1 frame... HACK....
-                       //pos -= FSOUND_DSP_GetBufferLength();
-
-                       //set the position
-                       out = pos/(double)sfreq + offset;
-                       #endif
-
-                       return true;
-               }
-               return false;
-       }
-
-       //Big implementation functions...
-       bool load(const std::string &filename, const std::string &filedirectory);
-       void clear();
-
-       //playing functions
-       void play(double t);
-       void stop();
-
-       //scrubbing functions
-       void start_scrubbing(double t);
-       void scrub(double t);
-       void stop_scrubbing();
-
-       double scrub_time()
-       {
-               return curscrubpos;
-       }
-};
-
-//--------------- Audio Container definitions --------------------------
-studio::AudioContainer::AudioContainer()
-{
-       imp = 0;
-}
-
-studio::AudioContainer::~AudioContainer()
-{
-       if(imp) delete (imp);
-}
-
-bool studio::AudioContainer::load(const std::string &filename,const std::string &filedirectory)
-{
-       if(!imp)
-       {
-               imp = new AudioImp;
-       }
-
-       profilevalid = false;
-       return imp->load(filename,filedirectory);
-}
-
-#ifdef WITH_FMOD
-handle<studio::AudioProfile> studio::AudioContainer::get_profile(float samplerate)
-#else
-handle<studio::AudioProfile> studio::AudioContainer::get_profile(float /*samplerate*/)
-#endif
-{
-       #ifdef WITH_FMOD
-
-       //if we already have done our work, then we're good
-       if(profilevalid && prof)
-       {
-               //synfig::info("Using already built profile");
-               return prof;
-       }
-
-       //synfig::info("Before profile");
-       //make a new profile at current sample rate
-
-       //NOTE: We might want to reuse the structure already there...
-       prof = new AudioProfile;
-       prof->set_parent(this); //Our parent is THIS!!!
-
-       if(!prof)
-       {
-               synfig::warning("Couldn't allocate audioprofile...");
-               return handle<studio::AudioProfile>();
-       }
-
-       //setting the info for the sample rate
-       //synfig::info("Setting info...");
-
-       synfig::info("Building Profile...");
-       prof->samplerate = samplerate;
-       if(build_profile(imp->sample,prof->samplerate,prof->samples))
-       {
-               synfig::info("  Success!");
-               profilevalid = true;
-               return prof;
-       }else
-       {
-               return handle<studio::AudioProfile>();
-       }
-
-       #else
-
-       return handle<studio::AudioProfile>();
-
-       #endif
-}
-
-void studio::AudioContainer::clear()
-{
-       if(imp)
-       {
-               delete imp;
-               imp = 0;
-       }
-
-       profilevalid = false;
-}
-
-void studio::AudioContainer::play(double t)
-{
-       if(imp) imp->play(t);
-}
-
-void studio::AudioContainer::stop()
-{
-       if(imp) imp->stop();
-}
-
-bool studio::AudioContainer::get_current_time(double &out)
-{
-       if(imp) return imp->get_current_time(out);
-       else return false;
-}
-
-void AudioContainer::set_offset(const double &s)
-{
-       if(imp) imp->set_offset(s);
-}
-
-double AudioContainer::get_offset() const
-{
-       static double zero = 0;
-       if(imp)
-               return imp->get_offset();
-       return zero;
-}
-
-bool AudioContainer::is_playing() const
-{
-       if(imp)
-               return imp->playing;
-       return false;
-}
-
-bool AudioContainer::is_scrubbing() const
-{
-       if(imp)
-               return imp->is_scrubbing();
-       return false;
-}
-
-void AudioContainer::start_scrubbing(double t)
-{
-       if(imp) imp->start_scrubbing(t);
-}
-
-void AudioContainer::stop_scrubbing()
-{
-       if(imp) imp->stop_scrubbing();
-}
-
-void AudioContainer::scrub(double t)
-{
-       if(imp) imp->scrub(t);
-}
-
-double AudioContainer::scrub_time() const
-{
-       if(imp) return imp->scrub_time();
-       else return 0;
-}
-
-bool AudioContainer::isRunning() const
-{
-       if(imp) return imp->isRunning();
-       else return false;
-}
-
-bool AudioContainer::isPaused() const
-{
-       if(imp) return imp->isPaused();
-       else return false;
-}
-
-//----------- Audio imp information -------------------
-
-#ifdef WITH_FMOD
-bool studio::AudioContainer::AudioImp::load(const std::string &filename,
-                                                                                       const std::string &filedirectory)
-#else
-bool studio::AudioContainer::AudioImp::load(const std::string &/*filename*/,
-                                                                                       const std::string &/*filedirectory*/)
-#endif
-{
-       clear();
-
-       #ifdef WITH_FMOD
-
-       //And continue with the sound loading...
-       string  file = filename;
-
-       //Trivial reject... (fixes stat call problem... where it just looks at directory and not file...)
-       if(file.length() == 0) return false;
-
-       //we don't need the file directory?
-       if(!is_absolute_path(file))
-       {
-               file=filedirectory+filename;
-               synfig::warning("Not absolute hoooray");
-       }
-       synfig::info("Loading Audio file: %s", file.c_str());
-
-       //check to see if file exists
-       {
-               struct stat     s;
-               if(stat(file.c_str(),&s) == -1 && errno == ENOENT)
-               {
-                       synfig::info("There was no audio file...");
-                       return false;
-               }
-       }
-
-       //load fmod if we can...
-       //synfig::warning("I'm compiled with FMOD!");
-       fmodinit.addref();
-
-       //load the stream
-       int ch = FSOUND_FREE;
-       FSOUND_SAMPLE *sm = FSOUND_Sample_Load(FSOUND_FREE,file.c_str(),FSOUND_LOOP_OFF|FSOUND_MPEGACCURATE,0,0);
-
-       if(!sm)
-       {
-               synfig::warning("Could not open the audio file as a sample: %s",file.c_str());
-               goto error;
-       }
-
-       //synfig::warning("Opened a file as a sample! :)");
-
-       /*{
-               int bufferlen = FSOUND_DSP_GetBufferLength();
-               synfig::info("Buffer length = %d samples, %.3lf s",bufferlen, bufferlen / (double)FSOUND_GetOutputRate());
-       }*/
-
-       //set all the variables since everything has worked out...
-       //get the length of the stream
-       {
-               length = FSOUND_Sample_GetLength(sm);
-
-               int volume = 0;
-               FSOUND_Sample_GetDefaults(sm,&sfreq,&volume,0,0);
-
-               //double len = length / (double)sfreq;
-               //synfig::info("Sound info: %.2lf s long, %d Hz, %d Vol",(double)length,sfreq,volume);
-       }
-
-       //synfig::warning("Got all info, and setting up everything, %.2f sec.", length);
-       //synfig::warning("     BigSample: composed of %d samples", FSOUND_Sample_GetLength(sm));
-       synfig::info("Successfully opened %s as a sample and initialized it.",file.c_str());
-
-       //set up the playable info
-       sample = sm;
-       channel = ch;
-
-       //the length and sfreq params have already been initialized
-
-       return true;
-
-error:
-       if(sm) FSOUND_Sample_Free(sm);
-       file = "";
-
-       fmodinit.decref();
-
-       return false;
-
-       #else
-       return false;
-       #endif
-}
-
-#ifdef WITH_FMOD
-void studio::AudioContainer::AudioImp::play(double t)
-#else
-void studio::AudioContainer::AudioImp::play(double /*t*/)
-#endif
-{
-       #ifdef WITH_FMOD
-       if(!sample) return;
-
-       //stop scrubbing if we are...
-       if(is_scrubbing()) stop_scrubbing();
-
-       //t -= offset;
-       t -= get_offset();
-       playing = true;
-
-       if(t < 0)
-       {
-               unsigned int timeout = (int)floor(-t * 1000 + 0.5);
-               //synfig::info("Playing audio delayed by %d ms",timeout);
-               //delay for t seconds...
-               delaycon = Glib::signal_timeout().connect(
-                                               sigc::mem_fun(*this,&studio::AudioContainer::AudioImp::start_playing_now),timeout);
-
-               init_play();
-               FSOUND_SetFrequency(channel,sfreq);
-               FSOUND_SetCurrentPosition(channel,0);
-               return;
-       }
-
-       unsigned int position = (int)floor(t*sfreq + 0.5);
-
-       if(position >= FSOUND_Sample_GetLength(sample))
-       {
-               synfig::warning("Can't play audio when past length...");
-               return;
-       }
-
-       init_play();
-       FSOUND_SetFrequency(channel,sfreq);
-       FSOUND_SetCurrentPosition(channel,position);
-       FSOUND_SetPaused(channel,false);
-
-       //synfig::info("Playing audio with position %d samples",position);
-
-       #endif
-}
-
-void studio::AudioContainer::AudioImp::stop()
-{
-       delaycon.disconnect();
-
-       #ifdef WITH_FMOD
-       if(fmodinit.is_loaded() && playing && isRunning())
-       {
-               FSOUND_SetPaused(channel,true);
-       }
-       #endif
-
-       playing = false;
-}
-
-void studio::AudioContainer::AudioImp::clear()
-{
-       #ifdef WITH_FMOD
-       delaycon.disconnect();
-
-       stop();
-       stop_scrubbing();
-
-       if(sample)
-       {
-               if(FSOUND_IsPlaying(channel))
-               {
-                       FSOUND_StopSound(channel);
-               }
-               channel = FSOUND_FREE;
-               FSOUND_Sample_Free(sample);
-               fmodinit.decref();
-       }
-
-       playing = false;
-
-       #else
-       channel = 0;
-       #endif
-
-       sample = 0;
-       playing = false;
-}
-
-#ifdef WITH_FMOD
-void studio::AudioContainer::AudioImp::start_scrubbing(double t)
-#else
-void studio::AudioContainer::AudioImp::start_scrubbing(double /*t*/)
-#endif
-{
-       //synfig::info("Start scrubbing: %lf", t);
-       if(playing) stop();
-
-       set_scrubbing(true);
-
-       #ifdef WITH_FMOD
-       //make sure the other one is not scrubbing...
-       if(g_scrubdata.scrub)
-       {
-               *g_scrubdata.scrub = 0; //nullify the pointer...
-       }
-
-       //Set up the initial state for the delayed audio position
-       scrinfo.delaystart = 0;
-       scrinfo.pos = 0;
-       scrinfo.deltatime = 0;
-
-       //set it to point to our pointer (dizzy...)
-       g_scrubdata.scrub = &scrptr;
-
-       //setup position info so we can know what to do on boundary conditions...
-       curscrubpos = (t - get_offset()) * sfreq;
-
-       //So we can get an accurate difference...
-       timer.reset();
-
-       //reposition the sound if it won't be when scrubbed (if it's already in the range...)
-       int curi = (int)curscrubpos;
-       if(curi >= 0 && curi < length)
-       {
-               init_play();
-               FSOUND_SetCurrentPosition(channel,curi);
-
-               //Set the values...
-               scrinfo.pos = curscrubpos;
-               scrinfo.delaystart = delay_factor*buffer_length_sec;
-
-               //synfig::info("\tStarting at %d samps, with %d p %.3f delay",
-               //                              FSOUND_GetCurrentPosition(channel), (int)scrinfo.pos, scrinfo.delaystart);
-       }
-
-
-
-       //enable the dsp...
-       //synfig::info("\tActivating DSP");
-       FSOUND_DSP_SetActive(scrubdspunit,true);
-       #endif
-}
-
-void studio::AudioContainer::AudioImp::stop_scrubbing()
-{
-       //synfig::info("Stop scrubbing");
-
-       if(is_scrubbing())
-       {
-               set_scrubbing(false);
-
-               #ifdef WITH_FMOD
-               g_scrubdata.scrub = 0;
-
-               //stop the dsp...
-               //synfig::info("\tDeactivating DSP");
-               FSOUND_DSP_SetActive(scrubdspunit,false);
-               if(FSOUND_IsPlaying(channel)) FSOUND_SetPaused(channel,true);
-               #endif
-       }
-
-       curscrubpos = 0;
-}
-
-#ifdef WITH_FMOD
-void studio::AudioContainer::AudioImp::scrub(double t)
-#else
-void studio::AudioContainer::AudioImp::scrub(double /*t*/)
-#endif
-{
-       #ifdef WITH_FMOD
-       //synfig::info("Scrub to %lf",t);
-       if(is_scrubbing())
-       {
-               //What should we do?
-
-               /* Different special cases
-                       All outside, all inside,
-                       coming in (left or right),
-                       going out (left or right)
-               */
-               double oldpos = curscrubpos;
-               double newpos = (t - get_offset()) * sfreq;
-
-               curscrubpos = newpos;
-
-               //Ok the sound is running, now we need to tweak it
-               if(newpos > oldpos)
-               {
-                       //Outside so completely stopped...
-                       if(newpos < 0 || oldpos >= length)
-                       {
-                               //synfig::info("\tOut +");
-                               if(FSOUND_IsPlaying(channel))
-                               {
-                                       FSOUND_SetPaused(channel,true);
-                               }
-
-                               //Zero out the data!
-                               scrinfo.Lock();
-                               scrinfo.delaystart = 0;
-                               scrinfo.deltatime = 0;
-                               scrinfo.Unlock();
-
-                               return;
-                       }
-
-                       //going in? - start the sound at the beginning...
-                       /*else if(oldpos < 0)
-                       {
-                               //Set up the sound to be playing paused at the start...
-                               init_play();
-                               FSOUND_SetCurrentPosition(channel,0);
-
-                               synfig::info("\tIn + %d", FSOUND_GetCurrentPosition(channel));
-
-                               scrinfo.Lock();
-                               scrinfo.pos = 0;
-                               scrinfo.delaystart = delay_factor*buffer_length_sec;
-                               scrinfo.deltatime = 0;
-                               scrinfo.Unlock();
-                       }*/
-                       //don't need to deal with leaving... automatically dealt with...
-
-                       else //We're all inside...
-                       {
-                               //Set new position and decide what to do with time...
-                               scrinfo.Lock();
-                               scrinfo.pos = newpos;
-
-                               //should we restart the delay cycle... (is it done?)
-                               if(!isRunning() || (scrinfo.delaystart <= 0 && scrinfo.deltatime <= 0 && isPaused()))
-                               {
-                                       //synfig::info("Starting + at %d",(int)newpos);
-                                       scrinfo.deltatime = 0;
-                                       scrinfo.delaystart = delay_factor*buffer_length_sec;
-                                       scrinfo.Unlock();
-
-                                       //Set up the sound paused at the current position
-                                       init_play();
-                                       int setpos = min(max((int)newpos,0),length);
-                                       FSOUND_SetCurrentPosition(channel,setpos);
-                                       timer.reset();
-                                       return;
-                               }
-
-                               //No! just increment the time delta...
-                               scrinfo.deltatime += timer.pop_time();
-
-                               //Nope... continue and just increment the deltatime and reset position...
-                               scrinfo.Unlock();
-
-                               //set channel and unpause
-                               FSOUND_SetPaused(channel,false);
-                               scrinfo.channel = channel;
-
-                       }
-               }else if(newpos < oldpos)
-               {
-                       //completely stopped...
-                       if(newpos >= length || oldpos < 0)
-                       {
-                               //synfig::info("Out -");
-                               if(FSOUND_IsPlaying(channel))
-                               {
-                                       FSOUND_SetPaused(channel,true);
-                               }
-
-                               //Zero out the data!
-                               scrinfo.Lock();
-                               scrinfo.delaystart = 0;
-                               scrinfo.deltatime = 0;
-                               scrinfo.Unlock();
-                       }
-
-                       //going in? - start going backwards at the end...
-                       /*else if(oldpos >= length)
-                       {
-                               synfig::info("In -");
-                               //Set up the sound to be playing paused at the start...
-                               init_play();
-                               FSOUND_SetCurrentPosition(channel,length-1);
-
-                               scrinfo.Lock();
-                               scrinfo.pos = length-1;
-                               scrinfo.delaystart = delay_factor*buffer_length_sec;
-                               scrinfo.deltatime = 0;
-                               scrinfo.Unlock();
-                       }*/
-                       //we don't have to worry about the leaving case...
-
-                       else //We're all inside...
-                       {
-                               //Set new position and decide what to do with time...
-                               scrinfo.Lock();
-                               scrinfo.pos = newpos;
-
-                               //should we restart the delay cycle... (is it done?)
-                               if(!isRunning() ||(scrinfo.delaystart <= 0 && scrinfo.deltatime <= 0 && isPaused()))
-                               {
-                                       //synfig::info("Starting - at %d",(int)newpos);
-                                       scrinfo.deltatime = 0;
-                                       scrinfo.delaystart = delay_factor*buffer_length_sec;
-                                       scrinfo.Unlock();
-
-                                       //reset timing so next update will be a valid diff...
-                                       init_play();
-                                       int setpos = min(max((int)newpos,0),length);
-                                       FSOUND_SetCurrentPosition(channel,setpos);
-                                       timer.reset();
-                                       return;
-                               }
-
-                               //No! just increment the time delta...
-                               scrinfo.deltatime += timer.pop_time();
-
-                               //Nope... continue and just increment the deltatime and reset position...
-                               scrinfo.Unlock();
-
-                               //set channel and unpause
-                               FSOUND_SetPaused(channel,false);
-                               scrinfo.channel = channel;
-                       }
-               }
-       }
-       #endif
-}