|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 2002-2003 Matthias Kretz <kretz@kde.org>
|
|
|
|
2002 Arnold Krille <arnold@arnoldarts.de>
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License version 2 as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
*/
|
|
|
|
// $Id$
|
|
|
|
|
|
|
|
#include "artsmodulescommon.h"
|
|
|
|
#include <debug.h>
|
|
|
|
#include "env_item_impl.h"
|
|
|
|
#include <connect.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <vector>
|
|
|
|
#include <map>
|
|
|
|
|
|
|
|
|
|
|
|
// Wether you are able to edit the name of the effectrack with an ugly LineInput or not.
|
|
|
|
//#define EFFECTRACK_NAME
|
|
|
|
// We should implement something like a ConfigWidget or at least a KLineInputBox or something...
|
|
|
|
|
|
|
|
namespace Arts {
|
|
|
|
namespace Environment {
|
|
|
|
|
|
|
|
class EffectRackItem_impl : virtual public EffectRackItem_skel,
|
|
|
|
virtual public Item_impl
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
std::string _name;
|
|
|
|
AudioManagerClient _amClient;
|
|
|
|
|
|
|
|
struct RackWiring {
|
|
|
|
RackWiring( const std::string & type, AudioManagerClient _amClient )
|
|
|
|
: routedtomaster( false )
|
|
|
|
, amClient( _amClient )
|
|
|
|
{
|
|
|
|
effect = SubClass( type );
|
|
|
|
|
|
|
|
connect( input, effect );
|
|
|
|
connect( effect, output );
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void setName( const std::string & efname )
|
|
|
|
{
|
|
|
|
name = efname;
|
|
|
|
input.busname( efname );
|
|
|
|
if( ! routedtomaster )
|
|
|
|
{
|
|
|
|
output.title( efname );
|
|
|
|
output.autoRestoreID( efname );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void start()
|
|
|
|
{
|
|
|
|
input.start();
|
|
|
|
effect.start();
|
|
|
|
output.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void stop()
|
|
|
|
{
|
|
|
|
input.stop();
|
|
|
|
effect.stop();
|
|
|
|
output.stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void master( bool tomaster )
|
|
|
|
{
|
|
|
|
routedtomaster = tomaster;
|
|
|
|
|
|
|
|
output.stop();
|
|
|
|
output = tomaster ? Synth_AMAN_PLAY( amClient ) : Synth_AMAN_PLAY();
|
|
|
|
connect( effect, output );
|
|
|
|
if( ! tomaster )
|
|
|
|
{
|
|
|
|
output.title( name );
|
|
|
|
output.autoRestoreID( name );
|
|
|
|
}
|
|
|
|
output.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool routedtomaster;
|
|
|
|
std::string name;
|
|
|
|
std::string effectName;
|
|
|
|
Synth_BUS_DOWNLINK input;
|
|
|
|
Arts::StereoEffect effect;
|
|
|
|
Synth_AMAN_PLAY output;
|
|
|
|
AudioManagerClient amClient;
|
|
|
|
};
|
|
|
|
std::vector<RackWiring> _wirings;
|
|
|
|
|
|
|
|
public:
|
|
|
|
EffectRackItem_impl()
|
|
|
|
: _name( "effect rack" )
|
|
|
|
, _amClient( amPlay, _name + " Master", "effectrack_" + _name )
|
|
|
|
{
|
|
|
|
// TODO: check if there's another effect rack with the same name already - if so prefix with 2./3./4.
|
|
|
|
}
|
|
|
|
|
|
|
|
// readonly attribute sequence<Arts::StereoEffect> effects;
|
|
|
|
std::vector<Arts::StereoEffect> *effects()
|
|
|
|
{
|
|
|
|
std::vector<Arts::StereoEffect> * effects = new std::vector<Arts::StereoEffect>;
|
|
|
|
for( std::vector<RackWiring>::iterator it = _wirings.begin(); it != _wirings.end(); ++it )
|
|
|
|
effects->push_back( it->effect );
|
|
|
|
return effects;
|
|
|
|
}
|
|
|
|
|
|
|
|
// attribute long effectCount;
|
|
|
|
long effectCount() { return _wirings.size(); }
|
|
|
|
|
|
|
|
// attribute string name;
|
|
|
|
void name(const std::string& newName) {
|
|
|
|
if(newName != _name)
|
|
|
|
{
|
|
|
|
_name = newName;
|
|
|
|
_amClient.title( _name + " Master" );
|
|
|
|
_amClient.autoRestoreID( "effectrack_" + _name );
|
|
|
|
for( unsigned int i = 0; i < _wirings.size(); i++ )
|
|
|
|
_wirings[i].setName( effectName( i, _wirings[ i ].effectName ) );
|
|
|
|
name_changed( newName );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::string name() { return _name; }
|
|
|
|
|
|
|
|
void loadFromList(const std::vector<std::string>& /*list*/)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string> *saveToList()
|
|
|
|
{
|
|
|
|
std::vector<std::string> *result = new std::vector<std::string>;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string effectName( int n, const std::string & en )
|
|
|
|
{
|
|
|
|
char * efname = new char[ _name.length() + en.length() + 128 ];
|
|
|
|
sprintf( efname, "%s%02d (%s)", _name.c_str(), n, en.c_str() );
|
|
|
|
return efname;
|
|
|
|
}
|
|
|
|
|
|
|
|
Arts::StereoEffect createEffect( const std::string & type, const std::string & name )
|
|
|
|
{
|
|
|
|
RackWiring wiring( type, _amClient );
|
|
|
|
wiring.setName( effectName( _wirings.size() + 1, name ) );
|
|
|
|
wiring.start();
|
|
|
|
_wirings.push_back( wiring );
|
|
|
|
return wiring.effect;
|
|
|
|
}
|
|
|
|
|
|
|
|
void delEffect( long pos )
|
|
|
|
{
|
|
|
|
_wirings[ pos ].stop();
|
|
|
|
_wirings.erase( _wirings.begin() + pos );
|
|
|
|
for( unsigned int i = pos; i < _wirings.size(); ++i )
|
|
|
|
_wirings[ i ].setName( effectName( i, _wirings[ i ].effectName ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void routeToMaster( long pos, bool tomaster )
|
|
|
|
{
|
|
|
|
_wirings[ pos ].master( tomaster );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
REGISTER_IMPLEMENTATION(EffectRackItem_impl);
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace Environment;
|
|
|
|
|
|
|
|
typedef WeakReference<VBox> VBox_wref;
|
|
|
|
|
|
|
|
class EffectRackItemGui_impl : virtual public EffectRackItemGui_skel {
|
|
|
|
private:
|
|
|
|
bool _active;
|
|
|
|
long _effectCount;
|
|
|
|
std::string _type;
|
|
|
|
EffectRackItem _effectRack;
|
|
|
|
|
|
|
|
/* widgets */
|
|
|
|
VBox_wref _widget;
|
|
|
|
HBox hbox;
|
|
|
|
VBox effect_vbox;
|
|
|
|
#ifdef EFFECTRACK_NAME
|
|
|
|
LineEdit name;
|
|
|
|
#endif
|
|
|
|
ComboBox typebox;
|
|
|
|
Button addbutton;
|
|
|
|
GenericGuiFactory guiFactory;
|
|
|
|
std::vector<EffectRackSlot> _slots;
|
|
|
|
std::map<std::string, std::string> typeforname;
|
|
|
|
std::map<std::string, std::string> namefortype;
|
|
|
|
|
|
|
|
public:
|
|
|
|
EffectRackItemGui self() { return EffectRackItemGui::_from_base(_copy()); }
|
|
|
|
|
|
|
|
void redoGui()
|
|
|
|
{
|
|
|
|
VBox vbox = _widget;
|
|
|
|
if(vbox.isNull())
|
|
|
|
arts_warning("update with vbox null");
|
|
|
|
if(_effectRack.isNull())
|
|
|
|
arts_warning("update with _effectRack null");
|
|
|
|
if(!_effectRack.isNull() && !vbox.isNull())
|
|
|
|
{
|
|
|
|
vbox.spacing( 0 );
|
|
|
|
vbox.margin( 10 );
|
|
|
|
hbox = HBox( vbox );
|
|
|
|
hbox.spacing( 5 );
|
|
|
|
hbox.margin( 0 );
|
|
|
|
|
|
|
|
#ifdef EFFECTRACK_NAME
|
|
|
|
name = LineEdit();
|
|
|
|
name.caption("name");
|
|
|
|
name.text(_effectRack.name());
|
|
|
|
name.parent(hbox);
|
|
|
|
connect(name,"text_changed", _effectRack, "name");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
std::vector<std::string> choices;
|
|
|
|
TraderQuery query;
|
|
|
|
query.supports( "Interface", "Arts::StereoEffect" );
|
|
|
|
query.supports( "Features", "RackGUI" );
|
|
|
|
std::vector<TraderOffer> *queryResults = query.query();
|
|
|
|
for(std::vector<TraderOffer>::iterator it = queryResults->begin(); it != queryResults->end(); ++it)
|
|
|
|
{
|
|
|
|
std::vector<std::string> * names = it->getProperty( "Name" );
|
|
|
|
std::string name = names->empty() ? it->interfaceName() : names->front();
|
|
|
|
delete names;
|
|
|
|
choices.push_back( name );
|
|
|
|
typeforname[ name ] = it->interfaceName();
|
|
|
|
namefortype[ it->interfaceName() ] = name;
|
|
|
|
}
|
|
|
|
delete queryResults;
|
|
|
|
typebox = ComboBox();
|
|
|
|
typebox.choices(choices);
|
|
|
|
typebox.value(_type);
|
|
|
|
typebox.parent(hbox);
|
|
|
|
connect(typebox,"value_changed", self(), "type");
|
|
|
|
|
|
|
|
addbutton = Button( "add", hbox );
|
|
|
|
connect( addbutton, "clicked_changed", self(), "addeffect" );
|
|
|
|
|
|
|
|
effect_vbox = VBox( vbox );
|
|
|
|
effect_vbox.margin( 0 );
|
|
|
|
effect_vbox.spacing( 5 );
|
|
|
|
effect_vbox.show();
|
|
|
|
|
|
|
|
Frame spacer;
|
|
|
|
spacer.parent( effect_vbox );
|
|
|
|
spacer.vSizePolicy( spExpanding );
|
|
|
|
spacer.show();
|
|
|
|
effect_vbox._addChild( spacer, "spacer" );
|
|
|
|
|
|
|
|
_slots.clear();
|
|
|
|
|
|
|
|
// add Arts::StereoEffect widgets
|
|
|
|
std::vector<Arts::StereoEffect> * effects = _effectRack.effects();
|
|
|
|
for( std::vector<Arts::StereoEffect>::iterator it = effects->begin(); it != effects->end(); ++it )
|
|
|
|
createEffectGui( *it );
|
|
|
|
delete effects;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* FIXME: maybe insert a "dead" label here */
|
|
|
|
if(!vbox.isNull())
|
|
|
|
vbox.show();
|
|
|
|
effect_vbox = VBox::null();
|
|
|
|
hbox = HBox::null();
|
|
|
|
// name = LineEdit::null();
|
|
|
|
typebox = ComboBox::null();
|
|
|
|
_slots.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void createEffectGui( Arts::StereoEffect effect )
|
|
|
|
{
|
|
|
|
Widget w = guiFactory.createGui( effect );
|
|
|
|
if( ! w.isNull() )
|
|
|
|
{
|
|
|
|
// insert effect GUI into the "Rack"
|
|
|
|
EffectRackSlot slot( effect_vbox, w, self() );
|
|
|
|
_slots.push_back( slot );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void removeSlot( EffectRackSlot slot )
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
for( i = 0; i < _slots.size() && ! _slots[ i ]._isEqual( slot ) ; ++i );
|
|
|
|
if( i < _slots.size() )
|
|
|
|
{
|
|
|
|
_slots.erase( _slots.begin() + i );
|
|
|
|
_effectRack.delEffect( i );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
arts_warning( "WARNING: Trying to remove an unknown slot" );
|
|
|
|
}
|
|
|
|
|
|
|
|
void routeToMaster( EffectRackSlot slot, bool tomaster )
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
for( i = 0; i < _slots.size() && ! _slots[ i ]._isEqual( slot ) ; ++i );
|
|
|
|
if( i < _slots.size() )
|
|
|
|
_effectRack.routeToMaster( i, tomaster );
|
|
|
|
else
|
|
|
|
arts_warning( "WARNING: Trying to route an unknown slot" );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool active() { return _active; }
|
|
|
|
void active(bool newActive)
|
|
|
|
{
|
|
|
|
if(newActive != _active)
|
|
|
|
{
|
|
|
|
_active = newActive;
|
|
|
|
if(!newActive)
|
|
|
|
_effectRack = EffectRackItem::null();
|
|
|
|
redoGui();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string type()
|
|
|
|
{
|
|
|
|
return _type;
|
|
|
|
}
|
|
|
|
void type(const std::string& t)
|
|
|
|
{
|
|
|
|
_type = typeforname[ t ];
|
|
|
|
}
|
|
|
|
|
|
|
|
bool addeffect() { return false; } //unused
|
|
|
|
void addeffect( bool clicked )
|
|
|
|
{
|
|
|
|
if( ! addbutton.clicked() || ! clicked )
|
|
|
|
return;
|
|
|
|
|
|
|
|
Arts::StereoEffect effect = _effectRack.createEffect( _type, namefortype[ _type ] );
|
|
|
|
createEffectGui( effect );
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget initialize(EffectRackItem item)
|
|
|
|
{
|
|
|
|
VBox vbox;
|
|
|
|
vbox._addChild(self(),"the_gui_updating_widget");
|
|
|
|
|
|
|
|
_widget = vbox;
|
|
|
|
_effectRack = item;
|
|
|
|
_active = item.active();
|
|
|
|
_type = "Arts::Synth_VOICE_REMOVAL";
|
|
|
|
_effectCount = item.effectCount();
|
|
|
|
|
|
|
|
if(!_effectRack.isNull())
|
|
|
|
{
|
|
|
|
connect(_effectRack, "active_changed", self(), "active");
|
|
|
|
}
|
|
|
|
redoGui();
|
|
|
|
|
|
|
|
return vbox;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
REGISTER_IMPLEMENTATION(EffectRackItemGui_impl);
|
|
|
|
|
|
|
|
class EffectRackGuiFactory_impl : virtual public EffectRackGuiFactory_skel
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Widget createGui(Object object)
|
|
|
|
{
|
|
|
|
arts_return_val_if_fail(!object.isNull(), Arts::Widget::null());
|
|
|
|
|
|
|
|
std::string iface = object._interfaceName();
|
|
|
|
arts_return_val_if_fail(iface == "Arts::Environment::EffectRackItem",
|
|
|
|
Arts::Widget::null());
|
|
|
|
if(iface == "Arts::Environment::EffectRackItem")
|
|
|
|
{
|
|
|
|
EffectRackItem effectRack = DynamicCast(object);
|
|
|
|
arts_return_val_if_fail(!effectRack.isNull(), Arts::Widget::null());
|
|
|
|
|
|
|
|
EffectRackItemGui gui;
|
|
|
|
return gui.initialize(effectRack);
|
|
|
|
}
|
|
|
|
return Arts::Widget::null();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
REGISTER_IMPLEMENTATION(EffectRackGuiFactory_impl);
|
|
|
|
}
|
|
|
|
// vim:ts=4:sw=4
|