|
|
|
/*
|
|
|
|
|
|
|
|
Copyright (C) 2002 Hans Meine
|
|
|
|
hans_meine@gmx.net
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library 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
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "flowsystem.h"
|
|
|
|
#include "soundserver.h"
|
|
|
|
#include "artsflow.h"
|
|
|
|
#include "stdsynthmodule.h"
|
|
|
|
#include "debug.h"
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace Arts;
|
|
|
|
|
|
|
|
class GSLPlayObject_impl : public GSLPlayObject_skel, public StdSynthModule {
|
|
|
|
protected:
|
|
|
|
DataHandlePlay leftPlay_, rightPlay_;
|
|
|
|
poState state_;
|
|
|
|
WaveDataHandle dhandle_;
|
|
|
|
std::string filename_;
|
|
|
|
|
|
|
|
int sampleCount()
|
|
|
|
{
|
|
|
|
if(!dhandle_.isLoaded()) return 0;
|
|
|
|
return dhandle_.valueCount() / dhandle_.channelCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
/*
|
|
|
|
* construction, destruction
|
|
|
|
*/
|
|
|
|
GSLPlayObject_impl()
|
|
|
|
: leftPlay_(DataHandlePlay::null()),
|
|
|
|
rightPlay_(DataHandlePlay::null()),
|
|
|
|
state_(posIdle)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
float speed() { return leftPlay_.speed(); }
|
|
|
|
void speed(float newSpeed)
|
|
|
|
{
|
|
|
|
if(newSpeed != speed())
|
|
|
|
{
|
|
|
|
leftPlay_.speed(newSpeed);
|
|
|
|
if(!rightPlay_.isNull())
|
|
|
|
rightPlay_.speed(newSpeed);
|
|
|
|
speed_changed(newSpeed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void streamStart()
|
|
|
|
{
|
|
|
|
arts_return_if_fail(dhandle_.isLoaded());
|
|
|
|
|
|
|
|
if(dhandle_.channelCount()>=2)
|
|
|
|
{
|
|
|
|
rightPlay_ = leftPlay_.clone();
|
|
|
|
rightPlay_.channelIndex(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
leftPlay_.start();
|
|
|
|
if(!rightPlay_.isNull())
|
|
|
|
rightPlay_.start();
|
|
|
|
|
|
|
|
arts_debug("GSLPlayObject: streamStart(%d channels) playing %d, %d",
|
|
|
|
dhandle_.channelCount(),
|
|
|
|
leftPlay_.channelIndex(),
|
|
|
|
rightPlay_.isNull() ? -1 : rightPlay_.channelIndex());
|
|
|
|
|
|
|
|
_node()->virtualize("left", leftPlay_._node(), "outvalue");
|
|
|
|
if(dhandle_.channelCount()>=2)
|
|
|
|
_node()->virtualize("right", rightPlay_._node(), "outvalue");
|
|
|
|
else
|
|
|
|
_node()->virtualize("right", leftPlay_._node(), "outvalue");
|
|
|
|
}
|
|
|
|
|
|
|
|
void streamEnd()
|
|
|
|
{
|
|
|
|
arts_return_if_fail(dhandle_.isLoaded());
|
|
|
|
|
|
|
|
_node()->devirtualize("left", leftPlay_._node(), "outvalue");
|
|
|
|
if(dhandle_.channelCount()>=2)
|
|
|
|
_node()->devirtualize("right", rightPlay_._node(), "outvalue");
|
|
|
|
else
|
|
|
|
_node()->devirtualize("right", leftPlay_._node(), "outvalue");
|
|
|
|
|
|
|
|
leftPlay_.stop();
|
|
|
|
if(!rightPlay_.isNull())
|
|
|
|
rightPlay_.stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* KMedia2 private interface
|
|
|
|
*/
|
|
|
|
bool loadMedia(const std::string &filename)
|
|
|
|
{
|
|
|
|
arts_return_val_if_fail(!dhandle_.isLoaded(), false);
|
|
|
|
|
|
|
|
arts_debug("GSLPlayObject: loadMedia('%s')", filename.c_str());
|
|
|
|
filename_ = filename;
|
|
|
|
dhandle_.load(filename);
|
|
|
|
if(dhandle_.isLoaded())
|
|
|
|
{
|
|
|
|
leftPlay_ = dhandle_.createPlayer();
|
|
|
|
if(dhandle_.channelCount()>2)
|
|
|
|
arts_debug("GSLPlayObject: can't play more than 2 channels, "
|
|
|
|
"playing first two!");
|
|
|
|
|
|
|
|
leftPlay_._node()->connect("finished_changed", _node(), "done");
|
|
|
|
}
|
|
|
|
return dhandle_.isLoaded();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* KMedia2 interface
|
|
|
|
*/
|
|
|
|
std::string description()
|
|
|
|
{
|
|
|
|
return "no description available (see " __FILE__ ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
poTime currentTime()
|
|
|
|
{
|
|
|
|
if(!dhandle_.isLoaded())
|
|
|
|
return poTime(0, 0, 0, "samples");
|
|
|
|
|
|
|
|
float timesec = leftPlay_.pos()
|
|
|
|
/ dhandle_.channelCount()
|
|
|
|
/ dhandle_.mixerFrequency();
|
|
|
|
float timems = (timesec - floor(timesec)) * 1000.0;
|
|
|
|
|
|
|
|
return poTime((long)timesec, (long)timems,
|
|
|
|
(long)leftPlay_.pos(), "samples");
|
|
|
|
}
|
|
|
|
|
|
|
|
poTime overallTime()
|
|
|
|
{
|
|
|
|
float timesec = (float)sampleCount() / dhandle_.mixerFrequency();
|
|
|
|
float timems = (timesec - floor(timesec)) * 1000.0;
|
|
|
|
|
|
|
|
return poTime((long)timesec, (long)timems,
|
|
|
|
(long)sampleCount(), "samples");
|
|
|
|
}
|
|
|
|
|
|
|
|
poCapabilities capabilities()
|
|
|
|
{
|
|
|
|
return static_cast<poCapabilities>(capPause | capSeek);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string mediaName()
|
|
|
|
{
|
|
|
|
return filename_;
|
|
|
|
}
|
|
|
|
|
|
|
|
poState state()
|
|
|
|
{
|
|
|
|
return state_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool done() { return leftPlay_.finished(); }
|
|
|
|
void done(bool d)
|
|
|
|
{
|
|
|
|
if(d && (state_ == posPlaying))
|
|
|
|
halt();
|
|
|
|
}
|
|
|
|
|
|
|
|
void play()
|
|
|
|
{
|
|
|
|
leftPlay_.paused(false);
|
|
|
|
if(!rightPlay_.isNull())
|
|
|
|
rightPlay_.paused(false);
|
|
|
|
state_ = posPlaying;
|
|
|
|
}
|
|
|
|
|
|
|
|
void halt()
|
|
|
|
{
|
|
|
|
leftPlay_.paused(true);
|
|
|
|
if(!rightPlay_.isNull())
|
|
|
|
rightPlay_.paused(true);
|
|
|
|
state_ = posIdle;
|
|
|
|
seek(poTime(-1, -1, 0, "samples"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void pause()
|
|
|
|
{
|
|
|
|
leftPlay_.paused(true);
|
|
|
|
if(!rightPlay_.isNull())
|
|
|
|
rightPlay_.paused(true);
|
|
|
|
state_ = posPaused;
|
|
|
|
}
|
|
|
|
|
|
|
|
void seek(const class poTime &newTime)
|
|
|
|
{
|
|
|
|
long newsamples = -1;
|
|
|
|
if(newTime.seconds != -1 && newTime.ms != -1)
|
|
|
|
{
|
|
|
|
float flnewtime = (float)newTime.seconds+((float)newTime.ms/1000.0);
|
|
|
|
newsamples = (long)(flnewtime * dhandle_.mixerFrequency());
|
|
|
|
}
|
|
|
|
else if(newTime.custom >= 0 && newTime.customUnit == "samples")
|
|
|
|
{
|
|
|
|
newsamples = (long)newTime.custom;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(newsamples > sampleCount())
|
|
|
|
newsamples = sampleCount();
|
|
|
|
|
|
|
|
if(newsamples >= 0)
|
|
|
|
{
|
|
|
|
leftPlay_.pos(newsamples * dhandle_.channelCount());
|
|
|
|
if(!rightPlay_.isNull())
|
|
|
|
rightPlay_.pos(newsamples * dhandle_.channelCount());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
REGISTER_IMPLEMENTATION(GSLPlayObject_impl);
|