gstreamer/ext/arts/gst_artsio_impl.cc

181 lines
4 KiB
C++
Raw Normal View History

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <math.h>
#include "artsflow.h"
#include "stdsynthmodule.h"
#include "gst_artsio.h"
#include "convert.h"
#include "connect.h"
#include "flowsystem.h"
#include <gst/gst.h>
using namespace Arts;
namespace Gst {
class ArtsStereoSink_impl : virtual public ArtsStereoSink_skel,
virtual public StdSynthModule
{
GstPad *sinkpad;
GstPad *srcpad;
unsigned long remainingsamples;
GstData *inbuf;
unsigned char *dataptr;
public:
ArtsStereoSink_impl()
{
remainingsamples = 0;
inbuf = NULL;
dataptr = NULL;
}
void calculateBlock (unsigned long samples)
{
unsigned long fulfilled = 0;
//gint16 *s;
//fprintf(stderr,"StereoSink: getting %d samples\n",samples);
while (fulfilled < samples) {
if (remainingsamples == 0) {
//fprintf(stderr,"need to get a buffer\n");
if (inbuf) {
gst_data_unref(inbuf);
inbuf = NULL;
}
// start by pulling a buffer from GStreamer
inbuf = gst_pad_pull (sinkpad);
while (GST_IS_EVENT (inbuf)) {
switch (GST_EVENT_TYPE (inbuf)) {
case GST_EVENT_EOS:
gst_element_set_eos (GST_PAD_PARENT (sinkpad));
default:
break;
}
gst_pad_event_default (srcpad, GST_EVENT(inbuf));
inbuf = gst_pad_pull (sinkpad);
}
dataptr = GST_BUFFER_DATA(GST_BUFFER(inbuf));
remainingsamples = GST_BUFFER_SIZE(GST_BUFFER(inbuf)) / 4;
//fprintf(stderr,"got a buffer with %d samples\n",remainingsamples);
}
unsigned long count = MIN(remainingsamples,samples-fulfilled);
//fprintf(stderr,"have %d samples left, can fill %d\n",remainingsamples,count);
convert_stereo_i16le_2float(count,dataptr,outleft,outright);
//s = (gint16 *)dataptr;
//fprintf(stderr,"samples in are %d and %d, out are %f and %f\n",s[0],s[1],outleft[0],outright[0]);
remainingsamples -= count;
dataptr += 4 * count;
fulfilled += count;
}
}
void setPad(GstPad *pad)
{
sinkpad = pad;
}
void setSrcPad(GstPad *pad)
{
srcpad = pad;
}
};
class ArtsStereoSrc_impl : virtual public ArtsStereoSrc_skel,
virtual public StdSynthModule
{
GstPad *srcpad;
GstBuffer *outbuf;
unsigned char *dataptr;
public:
void calculateBlock (unsigned long samples)
{
//gint16 *s;
//fprintf(stderr,"StereoSrc: handed %d samples\n",samples);
outbuf = gst_buffer_new();
GST_BUFFER_DATA(outbuf) = (guchar *)g_malloc(samples*4);
GST_BUFFER_SIZE(outbuf) = samples*4;
memset(GST_BUFFER_DATA(outbuf),0,samples*4);
convert_stereo_2float_i16le(samples,inleft,inright,GST_BUFFER_DATA(outbuf));
//s = (gint16 *)GST_BUFFER_DATA(outbuf);
//fprintf(stderr,"samples in are %f and %f, out are %d and %d\n",inleft[0],inright[0],s[0],s[1]);
gst_pad_push(srcpad,GST_DATA(outbuf));
outbuf = NULL;
}
void setPad(GstPad *pad)
{
srcpad = pad;
}
};
class GstArtsWrapper {
Dispatcher *dispatcher;
ArtsStereoSink sink;
ArtsStereoSrc source;
StereoVolumeControl effect;
public:
GstArtsWrapper(GstPad *sinkpad, GstPad *sourcepad) {
dispatcher = new Arts::Dispatcher();
ArtsStereoSink_impl *sink_impl = new ArtsStereoSink_impl();
ArtsStereoSrc_impl *source_impl = new ArtsStereoSrc_impl();
sink_impl->setPad(sinkpad);
sink_impl->setSrcPad(sourcepad);
source_impl->setPad(sourcepad);
sink = ArtsStereoSink::_from_base(sink_impl);
source = ArtsStereoSrc::_from_base(source_impl);
sink.start();
effect.start();
source.start();
effect.scaleFactor(0.5);
connect(sink, effect);
connect(effect, source);
// connect(sink,source);
}
void iterate()
{
source._node()->requireFlow();
}
};
};
extern "C" {
void *gst_arts_wrapper_new(GstPad *sinkpad, GstPad *sourcepad)
{
return new Gst::GstArtsWrapper(sinkpad, sourcepad);
}
void gst_arts_wrapper_free(void *wrapper)
{
Gst::GstArtsWrapper *w = (Gst::GstArtsWrapper *)wrapper;
delete w;
}
void gst_arts_wrapper_do(void *wrapper)
{
Gst::GstArtsWrapper *w = (Gst::GstArtsWrapper *)wrapper;
w->iterate();
}
}
// vim:sts=2:sw=2