Source: arts/synthschedule.h
|
|
|
|
/*
Copyright (C) 2000 Stefan Westerfeld
stefan@space.twc.de
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef _SYNTHMODULE_H
#define _SYNTHMODULE_H
#include "artsflow.h"
#include "flowsystem.h"
#include <string>
#include <vector>
#include <list>
/*
* BC - Status (2000-09-30): SynthBuffer, Port, AudioPort, MultiPort,
* StdFlowSystem, StdScheduleNode
*
* None of these classes is considered part of the public API. Do NOT use it
* in your apps. These are part of the implementation of libartsflow's
* StdFlowSystem, and subject to change with the needs of it.
*
* If you want to access flowsystem functionality, do so over the core.idl
* specified flowsystem interface, (object)->_node() or stuff in mcop/connect.h.
*/
namespace Arts {
class SynthBuffer
{
public: // yes, bad style, but needs to be fast
float *data;
unsigned long position,size;
/* every time I write data to a buffer, needread is incremented
by the amount of data for every module connected to that buffer,
since that (target) module has to read that data before I can write.
I can only write at max. (size-needread) items to that buffer
*/
unsigned long needread;
SynthBuffer(float initialvalue, unsigned long size);
void setValue(float value);
~SynthBuffer();
};
class StdScheduleNode;
class Port {
friend class VPort; // TODO: debugging, remove me when it works?
friend class VPortConnection; // TODO: debugging, remove me when it works?
protected:
std::string _name;
void *_ptr;
AttributeType _flags;
StdScheduleNode *parent;
// each port has a virtual port, which allows port redirection
class VPort *_vport;
// dynamic ports are created to implement multiports
bool _dynamicPort;
// functionality to remove all connections automatically as soon as
// the module gets destroyed
std::list<Port *> autoDisconnect;
/**
* call these from your (dis)connect implementation as soon as a the
* port gets (dis)connected to some other port (only one call per
* connection: destinationport->addAutoDisconnect(sourceport), not
* for the other direction)
*/
void addAutoDisconnect(Port *source);
void removeAutoDisconnect(Port *source);
public:
Port(std::string name, void *ptr, long flags, StdScheduleNode* parent);
virtual ~Port();
inline VPort* vport() { assert(_vport); return _vport; }
AttributeType flags();
std::string name();
void setPtr(void *ptr);
inline bool dynamicPort() { return _dynamicPort; }
inline void setDynamicPort() { _dynamicPort = true; }
virtual class AudioPort *audioPort();
virtual class ASyncPort *asyncPort();
virtual void disconnectAll();
virtual void connect(Port *) = 0;
virtual void disconnect(Port *) = 0;
};
class AudioPort : public Port {
protected:
AudioPort *source;
public:
StdScheduleNode *sourcemodule;
SynthBuffer *buffer, *lbuffer;
unsigned long destcount, position;
AudioPort(std::string name, void *ptr, long flags,StdScheduleNode *parent);
~AudioPort();
virtual class AudioPort *audioPort();
void setFloatValue(float f);
void connect(Port *psource);
void disconnect(Port *psource);
//------------- I/O ---------------------------------------------------------
inline unsigned long haveIn()
{
if(sourcemodule)
return(buffer->position - position);
else
return(buffer->size);// constant value; no read limitation
}
inline unsigned long outRoom()
{
long room;
room = buffer->size - buffer->needread;
if(room < 0) return 0;
return (unsigned long)room;
}
inline unsigned long readSegment(unsigned long offset, unsigned long len)
{
unsigned long rbsize = buffer->size;
unsigned long rbmask = buffer->size - 1;
unsigned long rbpos = (position+offset) & rbmask;
*((float **)_ptr) = &buffer->data[rbpos];
if(len > (rbsize-rbpos)) len = rbsize - rbpos;
return len;
}
inline unsigned long writeSegment(unsigned long offset, unsigned long len)
{
unsigned long rbsize = buffer->size;
unsigned long rbmask = buffer->size - 1;
unsigned long rbpos = (buffer->position+offset) & rbmask;
*((float **)_ptr) = &buffer->data[rbpos];
if(len > (rbsize-rbpos)) len = rbsize - rbpos;
return len;
}
inline void read(unsigned long cycles)
{
position += cycles;
buffer->needread -= cycles;
}
inline void write(unsigned long cycles)
{
buffer->position += cycles;
buffer->needread += cycles * destcount;
}
};
class MultiPort : public Port {
protected:
std::list<AudioPort *> parts;
typedef float *float_ptr;
float **conns;
long nextID;
void initConns();
public:
MultiPort(std::string name, void *ptr, long flags,StdScheduleNode *parent);
~MultiPort();
void connect(Port *port);
void disconnect(Port *port);
};
class StdFlowSystem;
class StdScheduleNode :public ScheduleNode
{
friend class StdFlowSystem;
bool running;
bool suspended;
Object_skel *_object;
SynthModule_base *module;
StdFlowSystem *flowSystem;
std::list<Port *> ports;
AudioPort **inConn;
AudioPort **outConn;
unsigned long inConnCount, outConnCount;
typedef AudioPort *AudioPort_ptr;
QueryInitStreamFunc queryInitStreamFunc;
void freeConn();
void rebuildConn();
void accessModule();
public: /* TODO? */
Port *findPort(std::string name);
/** scheduling variables - directly accessed by other schedNodes **/
long Busy,BusyHit,NeedCycles, CanPerform;
public:
StdScheduleNode(Object_skel *object, StdFlowSystem *flowSystem);
virtual ~StdScheduleNode();
void initStream(std::string name, void *ptr, long flags);
void addDynamicPort(Port *port);
void removeDynamicPort(Port *port);
void start();
void stop();
void requireFlow();
void virtualize(std::string port, ScheduleNode *implNode,
std::string implPort);
void devirtualize(std::string port, ScheduleNode *implNode,
std::string implPort);
// AutoSuspend stuff
bool suspendable();
void suspend();
void restart();
void connect(std::string port, ScheduleNode *dest, std::string destport);
void disconnect(std::string port, ScheduleNode *dest, std::string destport);
AttributeType queryFlags(const std::string& port);
void setFloatValue(std::string port, float value);
long request(long amount);
unsigned long calc(unsigned long cycles);
Object_skel *object();
void *cast(const std::string &target);
};
class StdFlowSystem :public FlowSystem_impl
{
protected:
std::list<StdScheduleNode *> nodes;
bool _suspended;
public:
StdFlowSystem();
ScheduleNode *addObject(Object_skel *object);
void removeObject(ScheduleNode *node);
/* AutoSuspend */
bool suspendable();
bool suspended();
void suspend();
void restart();
/* remote accessibility */
void startObject(Object node);
void stopObject(Object node);
void connectObject(Object sourceObject, const std::string& sourcePort,
Object destObject, const std::string& destPort);
void disconnectObject(Object sourceObject, const std::string& sourcePort,
Object destObject, const std::string& destPort);
AttributeType queryFlags(Object node, const std::string& port);
void setFloatValue(Object node, const std::string& port, float value);
FlowSystemReceiver createReceiver(Object object, const std::string &port,
FlowSystemSender sender);
/* interface to StdScheduleNode */
void schedule(unsigned long samples);
};
};
#endif
Generated by: stefan@stefan on Sat Feb 24 19:11:23 2001, using kdoc 2.0a47. |