a) basic prototype of OSC control
b) various changes to ControlProtocol model/implementation c) more attempts to get autoscroll to work nicely (unfinished) d) move editor item types into their own header git-svn-id: svn://localhost/trunk/ardour2@506 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
15
SConstruct
15
SConstruct
@@ -418,6 +418,19 @@ else:
|
||||
|
||||
libraries['usb'] = conf.Finish ()
|
||||
|
||||
#
|
||||
# Check for liblo
|
||||
|
||||
libraries['lo'] = LibraryInfo ()
|
||||
|
||||
conf = Configure (libraries['lo'])
|
||||
if conf.CheckLib ('lo', 'lo_server_new'):
|
||||
have_liblo = True
|
||||
else:
|
||||
have_liblo = False
|
||||
|
||||
libraries['lo'] = conf.Finish ()
|
||||
|
||||
#
|
||||
# Check for dmalloc
|
||||
|
||||
@@ -558,6 +571,8 @@ if env['SURFACES']:
|
||||
surface_subdirs += [ 'libs/surfaces/generic_midi' ]
|
||||
if have_libusb:
|
||||
surface_subdirs += [ 'libs/surfaces/tranzport' ]
|
||||
if have_liblo:
|
||||
surface_subdirs += [ 'libs/surfaces/osc' ]
|
||||
|
||||
opts.Save('scache.conf', env)
|
||||
Help(opts.GenerateHelpText(env))
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "canvas.h"
|
||||
#include "editor_items.h"
|
||||
|
||||
#include <ardour/types.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
@@ -16,6 +18,7 @@ class TimeAxisView;
|
||||
|
||||
struct DragInfo {
|
||||
ArdourCanvas::Item* item;
|
||||
ItemType item_type;
|
||||
void* data;
|
||||
jack_nframes_t last_frame_position;
|
||||
int32_t pointer_frame_offset;
|
||||
|
||||
@@ -2844,6 +2844,10 @@ Editor::autoscroll_canvas ()
|
||||
{
|
||||
jack_nframes_t new_frame;
|
||||
bool keep_calling = true;
|
||||
jack_nframes_t limit = max_frames - current_page_frames();
|
||||
GdkEventMotion ev;
|
||||
|
||||
autoscroll_distance = current_page_frames() * 3 / 4;
|
||||
|
||||
if (autoscroll_direction < 0) {
|
||||
if (leftmost_frame < autoscroll_distance) {
|
||||
@@ -2851,42 +2855,62 @@ Editor::autoscroll_canvas ()
|
||||
} else {
|
||||
new_frame = leftmost_frame - autoscroll_distance;
|
||||
}
|
||||
ev.x = drag_info.current_pointer_x - autoscroll_distance;
|
||||
} else {
|
||||
if (leftmost_frame > max_frames - autoscroll_distance) {
|
||||
new_frame = max_frames;
|
||||
if (leftmost_frame > limit - autoscroll_distance) {
|
||||
new_frame = limit;
|
||||
} else {
|
||||
new_frame = leftmost_frame + autoscroll_distance;
|
||||
}
|
||||
ev.x = drag_info.current_pointer_x + autoscroll_distance;
|
||||
}
|
||||
|
||||
if (new_frame != leftmost_frame) {
|
||||
cerr << "move to " << new_frame << " which is " << autoscroll_distance << " away" << endl;
|
||||
reposition_x_origin (new_frame);
|
||||
}
|
||||
|
||||
if (new_frame == 0 || new_frame == max_frames) {
|
||||
/* now fake a motion event to get the object that is being dragged to move too */
|
||||
|
||||
ev.type = GDK_MOTION_NOTIFY;
|
||||
ev.x = frame_to_unit (ev.x);
|
||||
ev.y = frame_to_unit (drag_info.current_pointer_y);
|
||||
motion_handler (drag_info.item, (GdkEvent*) &ev, drag_info.item_type, true);
|
||||
|
||||
if (new_frame == 0 || new_frame == limit) {
|
||||
/* we are done */
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
autoscroll_cnt++;
|
||||
|
||||
if (autoscroll_cnt == 1) {
|
||||
|
||||
/* connect the timeout so that we get called repeatedly */
|
||||
|
||||
autoscroll_timeout_tag = gtk_timeout_add (40, _autoscroll_canvas, this);
|
||||
|
||||
} else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
|
||||
autoscroll_timeout_tag = gtk_timeout_add (20, _autoscroll_canvas, this);
|
||||
keep_calling = false;
|
||||
|
||||
} else if (autoscroll_cnt == 50) { /* 0.5 seconds */
|
||||
|
||||
/* after about a while, speed up a bit by changing the timeout interval */
|
||||
|
||||
autoscroll_timeout_tag = gtk_timeout_add (20, _autoscroll_canvas, this);
|
||||
autoscroll_distance = (jack_nframes_t) floor (current_page_frames()/50.0f);
|
||||
cerr << "change distance to " << autoscroll_distance << endl;
|
||||
|
||||
} else if (autoscroll_cnt >= 30) {
|
||||
} else if (autoscroll_cnt == 75) { /* 1.0 seconds */
|
||||
|
||||
autoscroll_distance = (jack_nframes_t) floor (current_page_frames()/20.0f);
|
||||
cerr << "change distance to " << autoscroll_distance << endl;
|
||||
|
||||
} else if (autoscroll_cnt == 100) { /* 1.5 seconds */
|
||||
|
||||
/* after about another while, speed up by increasing the shift per callback */
|
||||
|
||||
autoscroll_distance = (jack_nframes_t) floor (0.5 * current_page_frames());
|
||||
autoscroll_distance = (jack_nframes_t) floor (current_page_frames()/10.0f);
|
||||
cerr << "change distance to " << autoscroll_distance << endl;
|
||||
|
||||
}
|
||||
|
||||
@@ -2903,7 +2927,7 @@ Editor::start_canvas_autoscroll (int dir)
|
||||
stop_canvas_autoscroll ();
|
||||
|
||||
autoscroll_direction = dir;
|
||||
autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/50.0);
|
||||
autoscroll_distance = (jack_nframes_t) floor (current_page_frames()/100.0);
|
||||
autoscroll_cnt = 0;
|
||||
|
||||
/* do it right now, which will start the repeated callbacks */
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "public_editor.h"
|
||||
#include "editing.h"
|
||||
#include "enums.h"
|
||||
#include "editor_items.h"
|
||||
#include "region_selection.h"
|
||||
#include "canvas.h"
|
||||
#include "draginfo.h"
|
||||
@@ -347,56 +348,6 @@ class Editor : public PublicEditor
|
||||
|
||||
PlaylistSelector* _playlist_selector;
|
||||
|
||||
enum ItemType {
|
||||
RegionItem,
|
||||
StreamItem,
|
||||
PlayheadCursorItem,
|
||||
EditCursorItem,
|
||||
MarkerItem,
|
||||
MarkerBarItem,
|
||||
RangeMarkerBarItem,
|
||||
TransportMarkerBarItem,
|
||||
SelectionItem,
|
||||
GainControlPointItem,
|
||||
GainLineItem,
|
||||
GainAutomationControlPointItem,
|
||||
GainAutomationLineItem,
|
||||
PanAutomationControlPointItem,
|
||||
PanAutomationLineItem,
|
||||
RedirectAutomationControlPointItem,
|
||||
RedirectAutomationLineItem,
|
||||
MeterMarkerItem,
|
||||
TempoMarkerItem,
|
||||
MeterBarItem,
|
||||
TempoBarItem,
|
||||
AudioRegionViewNameHighlight,
|
||||
AudioRegionViewName,
|
||||
StartSelectionTrimItem,
|
||||
EndSelectionTrimItem,
|
||||
AutomationTrackItem,
|
||||
FadeInItem,
|
||||
FadeInHandleItem,
|
||||
FadeOutItem,
|
||||
FadeOutHandleItem,
|
||||
|
||||
/* <CMT Additions> */
|
||||
MarkerViewItem,
|
||||
MarkerTimeAxisItem,
|
||||
MarkerViewHandleStartItem,
|
||||
MarkerViewHandleEndItem,
|
||||
ImageFrameItem,
|
||||
ImageFrameTimeAxisItem,
|
||||
ImageFrameHandleStartItem,
|
||||
ImageFrameHandleEndItem,
|
||||
/* </CMT Additions> */
|
||||
|
||||
CrossfadeViewItem,
|
||||
|
||||
/* don't remove this */
|
||||
|
||||
NoItem
|
||||
};
|
||||
|
||||
void set_frames_per_unit (double);
|
||||
void frames_per_unit_modified ();
|
||||
|
||||
@@ -861,7 +812,7 @@ class Editor : public PublicEditor
|
||||
bool typed_event (ArdourCanvas::Item*, GdkEvent*, ItemType);
|
||||
bool button_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
|
||||
bool button_release_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
|
||||
bool motion_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
|
||||
bool motion_handler (ArdourCanvas::Item*, GdkEvent*, ItemType, bool from_autoscroll = false);
|
||||
bool enter_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
|
||||
bool leave_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
|
||||
|
||||
|
||||
@@ -1107,26 +1107,23 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
|
||||
void
|
||||
Editor::maybe_autoscroll (GdkEvent* event)
|
||||
{
|
||||
jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
|
||||
jack_nframes_t rightmost_frame = leftmost_frame + one_page;
|
||||
jack_nframes_t rightmost_frame = leftmost_frame + current_page_frames();
|
||||
|
||||
jack_nframes_t frame = drag_info.current_pointer_frame;
|
||||
|
||||
if (autoscroll_timeout_tag < 0) {
|
||||
if (frame > rightmost_frame) {
|
||||
if (rightmost_frame < max_frames) {
|
||||
start_canvas_autoscroll (1);
|
||||
}
|
||||
} else if (frame < leftmost_frame) {
|
||||
if (leftmost_frame > 0) {
|
||||
start_canvas_autoscroll (-1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (frame >= leftmost_frame && frame < rightmost_frame) {
|
||||
stop_canvas_autoscroll ();
|
||||
cerr << "maybe autoscroll @ " << frame << " left = " << leftmost_frame << " right = " << rightmost_frame << endl;
|
||||
|
||||
if (frame > rightmost_frame) {
|
||||
if (rightmost_frame < max_frames) {
|
||||
autoscroll_direction = 1;
|
||||
autoscroll_canvas ();
|
||||
}
|
||||
}
|
||||
} else if (frame < leftmost_frame) {
|
||||
if (leftmost_frame > 0) {
|
||||
autoscroll_direction = -1;
|
||||
autoscroll_canvas ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -1469,7 +1466,7 @@ Editor::left_automation_track ()
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
|
||||
Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type, bool from_autoscroll)
|
||||
{
|
||||
gint x, y;
|
||||
|
||||
@@ -1495,10 +1492,11 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item
|
||||
return true;
|
||||
}
|
||||
|
||||
drag_info.item_type = item_type;
|
||||
drag_info.current_pointer_frame = event_frame (event, &drag_info.current_pointer_x,
|
||||
&drag_info.current_pointer_y);
|
||||
|
||||
if (drag_info.item) {
|
||||
if (!from_autoscroll && drag_info.item) {
|
||||
/* item != 0 is the best test i can think of for
|
||||
dragging.
|
||||
*/
|
||||
@@ -1544,12 +1542,14 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item
|
||||
/* </CMT Additions> */
|
||||
if (drag_info.item && (event->motion.state & Gdk::BUTTON1_MASK ||
|
||||
(event->motion.state & Gdk::BUTTON2_MASK))) {
|
||||
maybe_autoscroll (event);
|
||||
(this->*(drag_info.motion_callback)) (item, event);
|
||||
goto handled;
|
||||
}
|
||||
goto not_handled;
|
||||
|
||||
if (!from_autoscroll) {
|
||||
maybe_autoscroll (event);
|
||||
}
|
||||
(this->*(drag_info.motion_callback)) (item, event);
|
||||
goto handled;
|
||||
}
|
||||
goto not_handled;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1561,7 +1561,9 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item
|
||||
case MouseTimeFX:
|
||||
if (drag_info.item && (event->motion.state & GDK_BUTTON1_MASK ||
|
||||
(event->motion.state & GDK_BUTTON2_MASK))) {
|
||||
maybe_autoscroll (event);
|
||||
if (!from_autoscroll) {
|
||||
maybe_autoscroll (event);
|
||||
}
|
||||
(this->*(drag_info.motion_callback)) (item, event);
|
||||
goto handled;
|
||||
}
|
||||
@@ -2770,6 +2772,8 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||
vector<int32_t> height_list(512) ;
|
||||
vector<int32_t>::iterator j;
|
||||
|
||||
cerr << "region motion to " << drag_info.current_pointer_frame << endl;
|
||||
|
||||
/* Which trackview is this ? */
|
||||
|
||||
TimeAxisView* tvp = trackview_by_y_position (drag_info.current_pointer_y);
|
||||
|
||||
@@ -10,25 +10,31 @@ class BasicUI {
|
||||
BasicUI (ARDOUR::Session&);
|
||||
virtual ~BasicUI ();
|
||||
|
||||
void add_marker ();
|
||||
|
||||
/* transport control */
|
||||
|
||||
void loop_toggle ();
|
||||
void goto_start ();
|
||||
void goto_end ();
|
||||
void add_marker ();
|
||||
void rewind ();
|
||||
void ffwd ();
|
||||
void transport_stop ();
|
||||
void transport_play ();
|
||||
void rec_enable_toggle ();
|
||||
void set_transport_speed (float speed);
|
||||
float get_transport_speed (float speed);
|
||||
|
||||
void save_state ();
|
||||
void prev_marker ();
|
||||
void next_marker ();
|
||||
void move_at (float speed);
|
||||
void undo ();
|
||||
void redo ();
|
||||
void toggle_all_rec_enables ();
|
||||
void toggle_punch_in ();
|
||||
void toggle_punch_out ();
|
||||
|
||||
void rec_enable_toggle ();
|
||||
void toggle_all_rec_enables ();
|
||||
|
||||
protected:
|
||||
ARDOUR::Session& session;
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define ardour_control_protocols_h
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <sigc++/sigc++.h>
|
||||
|
||||
@@ -35,9 +36,49 @@ class ControlProtocol : public sigc::trackable, public BasicUI {
|
||||
static sigc::signal<void> Enter;
|
||||
static sigc::signal<void,float> ScrollTimeline;
|
||||
|
||||
/* the model here is as follows:
|
||||
|
||||
we imagine most control surfaces being able to control
|
||||
from 1 to N tracks at a time, with a session that may
|
||||
contain 1 to M tracks, where M may be smaller, larger or
|
||||
equal to N.
|
||||
|
||||
the control surface has a fixed set of physical controllers
|
||||
which can potentially be mapped onto different tracks/busses
|
||||
via some mechanism.
|
||||
|
||||
therefore, the control protocol object maintains
|
||||
a table that reflects the current mapping between
|
||||
the controls and route object.
|
||||
*/
|
||||
|
||||
void set_route_table_size (uint32_t size);
|
||||
void set_route_table (uint32_t table_index, ARDOUR::Route*);
|
||||
|
||||
void route_set_rec_enable (uint32_t table_index, bool yn);
|
||||
bool route_get_rec_enable (uint32_t table_index);
|
||||
|
||||
float route_get_gain (uint32_t table_index);
|
||||
void route_set_gain (uint32_t table_index, float);
|
||||
float route_get_effective_gain (uint32_t table_index);
|
||||
|
||||
float route_get_peak_input_power (uint32_t table_index, uint32_t which_input);
|
||||
|
||||
bool route_get_muted (uint32_t table_index);
|
||||
void route_set_muted (uint32_t table_index, bool);
|
||||
|
||||
bool route_get_soloed (uint32_t table_index);
|
||||
void route_set_soloed (uint32_t table_index, bool);
|
||||
|
||||
std::string route_get_name (uint32_t table_index);
|
||||
|
||||
protected:
|
||||
std::vector<ARDOUR::Route*> route_table;
|
||||
std::string _name;
|
||||
bool _active;
|
||||
|
||||
void next_track (uint32_t initial_id);
|
||||
void prev_track (uint32_t initial_id);
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -157,7 +157,7 @@ BasicUI::next_marker ()
|
||||
}
|
||||
|
||||
void
|
||||
BasicUI::move_at (float speed)
|
||||
BasicUI::set_transport_speed (float speed)
|
||||
{
|
||||
session.request_transport_speed (speed);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
*/
|
||||
|
||||
#include <ardour/control_protocol.h>
|
||||
#include <ardour/session.h>
|
||||
#include <ardour/route.h>
|
||||
#include <ardour/audio_track.h>
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace std;
|
||||
@@ -40,3 +43,269 @@ ControlProtocol::~ControlProtocol ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocol::next_track (uint32_t initial_id)
|
||||
{
|
||||
uint32_t limit = session.nroutes();
|
||||
Route* cr = route_table[0];
|
||||
uint32_t id;
|
||||
|
||||
if (cr) {
|
||||
id = cr->remote_control_id ();
|
||||
} else {
|
||||
id = 0;
|
||||
}
|
||||
|
||||
if (id == limit) {
|
||||
id = 0;
|
||||
} else {
|
||||
id++;
|
||||
}
|
||||
|
||||
while (id < limit) {
|
||||
if ((cr = session.route_by_remote_id (id)) != 0) {
|
||||
break;
|
||||
}
|
||||
id++;
|
||||
}
|
||||
|
||||
if (id == limit) {
|
||||
id = 0;
|
||||
while (id != initial_id) {
|
||||
if ((cr = session.route_by_remote_id (id)) != 0) {
|
||||
break;
|
||||
}
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
route_table[0] = cr;
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocol::prev_track (uint32_t initial_id)
|
||||
{
|
||||
uint32_t limit = session.nroutes() - 1;
|
||||
Route* cr = route_table[0];
|
||||
uint32_t id;
|
||||
|
||||
if (cr) {
|
||||
id = cr->remote_control_id ();
|
||||
} else {
|
||||
id = 0;
|
||||
}
|
||||
|
||||
if (id == 0) {
|
||||
id = session.nroutes() - 1;
|
||||
} else {
|
||||
id--;
|
||||
}
|
||||
|
||||
while (id >= 0) {
|
||||
if ((cr = session.route_by_remote_id (id)) != 0) {
|
||||
break;
|
||||
}
|
||||
id--;
|
||||
}
|
||||
|
||||
if (id < 0) {
|
||||
id = limit;
|
||||
while (id > initial_id) {
|
||||
if ((cr = session.route_by_remote_id (id)) != 0) {
|
||||
break;
|
||||
}
|
||||
id--;
|
||||
}
|
||||
}
|
||||
|
||||
route_table[0] = cr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ControlProtocol::set_route_table_size (uint32_t size)
|
||||
{
|
||||
while (route_table.size() < size) {
|
||||
route_table.push_back (0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocol::set_route_table (uint32_t table_index, ARDOUR::Route*)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocol::route_set_rec_enable (uint32_t table_index, bool yn)
|
||||
{
|
||||
if (table_index > route_table.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Route* r = route_table[table_index];
|
||||
|
||||
AudioTrack* at = dynamic_cast<AudioTrack*>(r);
|
||||
|
||||
if (at) {
|
||||
at->set_record_enable (yn, this);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ControlProtocol::route_get_rec_enable (uint32_t table_index)
|
||||
{
|
||||
if (table_index > route_table.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Route* r = route_table[table_index];
|
||||
|
||||
AudioTrack* at = dynamic_cast<AudioTrack*>(r);
|
||||
|
||||
if (at) {
|
||||
at->record_enabled ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
ControlProtocol::route_get_gain (uint32_t table_index)
|
||||
{
|
||||
if (table_index > route_table.size()) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
Route* r = route_table[table_index];
|
||||
|
||||
if (r == 0) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return r->gain ();
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocol::route_set_gain (uint32_t table_index, float gain)
|
||||
{
|
||||
if (table_index > route_table.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Route* r = route_table[table_index];
|
||||
|
||||
if (r != 0) {
|
||||
r->set_gain (gain, this);
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
ControlProtocol::route_get_effective_gain (uint32_t table_index)
|
||||
{
|
||||
if (table_index > route_table.size()) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
Route* r = route_table[table_index];
|
||||
|
||||
if (r == 0) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return r->effective_gain ();
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
ControlProtocol::route_get_peak_input_power (uint32_t table_index, uint32_t which_input)
|
||||
{
|
||||
if (table_index > route_table.size()) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
Route* r = route_table[table_index];
|
||||
|
||||
if (r == 0) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return r->peak_input_power (which_input);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ControlProtocol::route_get_muted (uint32_t table_index)
|
||||
{
|
||||
if (table_index > route_table.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Route* r = route_table[table_index];
|
||||
|
||||
if (r == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return r->muted ();
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocol::route_set_muted (uint32_t table_index, bool yn)
|
||||
{
|
||||
if (table_index > route_table.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Route* r = route_table[table_index];
|
||||
|
||||
if (r != 0) {
|
||||
r->set_mute (yn, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ControlProtocol::route_get_soloed (uint32_t table_index)
|
||||
{
|
||||
if (table_index > route_table.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Route* r = route_table[table_index];
|
||||
|
||||
if (r == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return r->soloed ();
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocol::route_set_soloed (uint32_t table_index, bool yn)
|
||||
{
|
||||
if (table_index > route_table.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Route* r = route_table[table_index];
|
||||
|
||||
if (r != 0) {
|
||||
r->set_solo (yn, this);
|
||||
}
|
||||
}
|
||||
|
||||
string
|
||||
ControlProtocol:: route_get_name (uint32_t table_index)
|
||||
{
|
||||
if (table_index > route_table.size()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
Route* r = route_table[table_index];
|
||||
|
||||
if (r == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return r->name();
|
||||
}
|
||||
|
||||
|
||||
52
libs/surfaces/osc/SConscript
Normal file
52
libs/surfaces/osc/SConscript
Normal file
@@ -0,0 +1,52 @@
|
||||
# -*- python -*-
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import glob
|
||||
|
||||
Import('env final_prefix install_prefix final_config_prefix libraries i18n')
|
||||
|
||||
osc = env.Copy()
|
||||
|
||||
#
|
||||
# this defines the version number of libardour_osc
|
||||
#
|
||||
|
||||
domain = 'ardour_osc'
|
||||
|
||||
osc.Append(DOMAIN = domain, MAJOR = 1, MINOR = 0, MICRO = 0)
|
||||
osc.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
|
||||
osc.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
|
||||
osc.Append(PACKAGE = domain)
|
||||
osc.Append(POTFILE = domain + '.pot')
|
||||
|
||||
osc_files=Split("""
|
||||
interface.cc
|
||||
osc_server.cc
|
||||
""")
|
||||
|
||||
osc.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
|
||||
osc.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
|
||||
osc.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
|
||||
osc.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
|
||||
|
||||
osc.Merge ([
|
||||
libraries['ardour'],
|
||||
libraries['sigc2'],
|
||||
libraries['pbd3'],
|
||||
libraries['lo']
|
||||
])
|
||||
|
||||
libardour_osc = osc.SharedLibrary('ardour_osc', osc_files)
|
||||
|
||||
Default(libardour_osc)
|
||||
|
||||
if env['NLS']:
|
||||
i18n (osc, osc_files, env)
|
||||
|
||||
env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2/surfaces'), libardour_osc))
|
||||
|
||||
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
||||
[ 'SConscript', 'i18n.h', 'gettext.h' ] +
|
||||
osc_files +
|
||||
glob.glob('po/*.po') + glob.glob('*.h')))
|
||||
16
libs/surfaces/osc/i18n.h
Normal file
16
libs/surfaces/osc/i18n.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef __i18n_h__
|
||||
#define __i18n_h__
|
||||
|
||||
#include <pbd/compose.h>
|
||||
#include "gettext.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
std::vector<std::string> internationalize (const char **);
|
||||
|
||||
#define _(Text) dgettext (PACKAGE,Text)
|
||||
#define N_(Text) gettext_noop (Text)
|
||||
#define X_(Text) Text
|
||||
|
||||
#endif // __i18n_h__
|
||||
44
libs/surfaces/osc/interface.cc
Normal file
44
libs/surfaces/osc/interface.cc
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <ardour/control_protocol.h>
|
||||
|
||||
#include "osc_server.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
ControlProtocol*
|
||||
new_osc_protocol (ControlProtocolDescriptor* descriptor, Session* s)
|
||||
{
|
||||
ControlOSC* osc = new ControlOSC (*s, 3891);
|
||||
|
||||
if (osc->set_active (true)) {
|
||||
delete osc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return osc;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
delete_osc_protocol (ControlProtocolDescriptor* descriptor, ControlProtocol* cp)
|
||||
{
|
||||
delete cp;
|
||||
}
|
||||
|
||||
static ControlProtocolDescriptor osc_descriptor = {
|
||||
name : "OSC",
|
||||
id : "uri://ardour.org/surfaces/osc:0",
|
||||
ptr : 0,
|
||||
module : 0,
|
||||
initialize : new_osc_protocol,
|
||||
destroy : delete_osc_protocol
|
||||
|
||||
};
|
||||
|
||||
|
||||
extern "C" {
|
||||
ControlProtocolDescriptor*
|
||||
protocol_descriptor () {
|
||||
return &osc_descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
392
libs/surfaces/osc/osc_server.cc
Normal file
392
libs/surfaces/osc/osc_server.cc
Normal file
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
** Copyright (C) 2004 Jesse Chappell <jesse@essej.net>
|
||||
**
|
||||
** This program 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 program 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.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
**
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cerrno>
|
||||
#include <algorithm>
|
||||
|
||||
#include <sys/poll.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sigc++/sigc++.h>
|
||||
|
||||
#include <lo/lo.h>
|
||||
|
||||
#include "osc_server.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace sigc;
|
||||
using namespace std;
|
||||
|
||||
#include <pbd/abstract_ui.cc>
|
||||
|
||||
static void error_callback(int num, const char *m, const char *path)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "liblo server error %d in path %s: %s\n", num, path, m);
|
||||
#endif
|
||||
}
|
||||
|
||||
ControlOSC::ControlOSC (ARDOUR::Session& s, uint32_t port)
|
||||
: ControlProtocol(s, X_("OSC")),
|
||||
AbstractUI<OSCRequest> (X_("OSC"), false),
|
||||
_port(port)
|
||||
{
|
||||
_shutdown = false;
|
||||
_osc_server = 0;
|
||||
_osc_unix_server = 0;
|
||||
_osc_thread = 0;
|
||||
}
|
||||
|
||||
int
|
||||
ControlOSC::set_active (bool yn)
|
||||
{
|
||||
if (yn) {
|
||||
|
||||
char tmpstr[255];
|
||||
|
||||
for (int j=0; j < 20; ++j) {
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%d", _port);
|
||||
|
||||
if ((_osc_server = lo_server_new (tmpstr, error_callback))) {
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
cerr << "can't get osc at port: " << _port << endl;
|
||||
#endif
|
||||
_port++;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef ARDOUR_OSC_UNIX_SERVER
|
||||
|
||||
// APPEARS sluggish for now
|
||||
|
||||
// attempt to create unix socket server too
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "/tmp/sooperlooper_XXXXXX");
|
||||
int fd = mkstemp(tmpstr);
|
||||
|
||||
if (fd >= 0 ) {
|
||||
unlink (tmpstr);
|
||||
close (fd);
|
||||
|
||||
_osc_unix_server = lo_server_new (tmpstr, error_callback);
|
||||
|
||||
if (_osc_unix_server) {
|
||||
_osc_unix_socket_path = tmpstr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
register_callbacks();
|
||||
|
||||
on_session_load ();
|
||||
|
||||
// lo_server_thread_add_method(_sthread, NULL, NULL, ControlOSC::_dummy_handler, this);
|
||||
|
||||
if (!init_osc_thread()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* need to stop the OSC UDP server */
|
||||
|
||||
if (!_osc_unix_socket_path.empty()) {
|
||||
// unlink it
|
||||
unlink(_osc_unix_socket_path.c_str());
|
||||
}
|
||||
|
||||
// stop server thread
|
||||
terminate_osc_thread();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
ControlOSC::caller_is_ui_thread ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ControlOSC::~ControlOSC()
|
||||
{
|
||||
set_active (false);
|
||||
}
|
||||
|
||||
void
|
||||
ControlOSC::register_callbacks()
|
||||
{
|
||||
lo_server srvs[2];
|
||||
lo_server serv;
|
||||
|
||||
srvs[0] = _osc_server;
|
||||
srvs[1] = _osc_unix_server;
|
||||
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
|
||||
if (!srvs[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
serv = srvs[i];
|
||||
|
||||
#define REGISTER_CALLBACK(serv,path,types, function) lo_server_add_method (serv, path, types, ControlOSC::_ ## function, this)
|
||||
|
||||
REGISTER_CALLBACK (serv, "/session/add_marker", "", add_marker);
|
||||
REGISTER_CALLBACK (serv, "/session/loop_toggle", "", loop_toggle);
|
||||
REGISTER_CALLBACK (serv, "/session/goto_start", "", goto_start);
|
||||
REGISTER_CALLBACK (serv, "/session/goto_end", "", goto_end);
|
||||
REGISTER_CALLBACK (serv, "/session/rewind", "", rewind);
|
||||
REGISTER_CALLBACK (serv, "/session/ffwd", "", ffwd);
|
||||
REGISTER_CALLBACK (serv, "/session/transport_stop", "", transport_stop);
|
||||
REGISTER_CALLBACK (serv, "/session/transport_play", "", transport_play);
|
||||
REGISTER_CALLBACK (serv, "/session/set_transport_speed", "f", set_transport_speed);
|
||||
REGISTER_CALLBACK (serv, "/session/save_state", "", save_state);
|
||||
REGISTER_CALLBACK (serv, "/session/prev_marker", "", prev_marker);
|
||||
REGISTER_CALLBACK (serv, "/session/next_marker", "", next_marker);
|
||||
REGISTER_CALLBACK (serv, "/session/undo", "", undo);
|
||||
REGISTER_CALLBACK (serv, "/session/redo", "", redo);
|
||||
REGISTER_CALLBACK (serv, "/session/toggle_punch_in", "", toggle_punch_in);
|
||||
REGISTER_CALLBACK (serv, "/session/toggle_punch_out", "", toggle_punch_out);
|
||||
REGISTER_CALLBACK (serv, "/session/rec_enable_toggle", "", rec_enable_toggle);
|
||||
REGISTER_CALLBACK (serv, "/session/toggle_all_rec_enables", "", toggle_all_rec_enables);
|
||||
|
||||
#if 0
|
||||
|
||||
lo_server_add_method(serv, "/session/set", "ss", ControlOSC::global_set_handler, this);
|
||||
lo_server_add_method(serv, "/session/get", "ss", ControlOSC::global_get_handler, this);
|
||||
|
||||
// un/register_update args= s:ctrl s:returl s:retpath
|
||||
lo_server_add_method(serv, "/register_update", "sss", ControlOSC::global_register_update_handler, this);
|
||||
lo_server_add_method(serv, "/unregister_update", "sss", ControlOSC::global_unregister_update_handler, this);
|
||||
lo_server_add_method(serv, "/register_auto_update", "siss", ControlOSC::global_register_auto_update_handler, this);
|
||||
lo_server_add_method(serv, "/unregister_auto_update", "sss", ControlOSC::_global_unregister_auto_update_handler, this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ControlOSC::init_osc_thread ()
|
||||
{
|
||||
// create new thread to run server
|
||||
if (pipe (_request_pipe)) {
|
||||
cerr << "Cannot create osc request signal pipe" << strerror (errno) << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fcntl (_request_pipe[0], F_SETFL, O_NONBLOCK)) {
|
||||
cerr << "osc: cannot set O_NONBLOCK on signal read pipe " << strerror (errno) << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fcntl (_request_pipe[1], F_SETFL, O_NONBLOCK)) {
|
||||
cerr << "osc: cannot set O_NONBLOCK on signal write pipe " << strerror (errno) << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
pthread_create (&_osc_thread, NULL, &ControlOSC::_osc_receiver, this);
|
||||
if (!_osc_thread) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//pthread_detach (_osc_thread);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ControlOSC::terminate_osc_thread ()
|
||||
{
|
||||
void* status;
|
||||
|
||||
_shutdown = true;
|
||||
|
||||
poke_osc_thread ();
|
||||
|
||||
pthread_join (_osc_thread, &status);
|
||||
}
|
||||
|
||||
void
|
||||
ControlOSC::poke_osc_thread ()
|
||||
{
|
||||
char c;
|
||||
|
||||
if (write (_request_pipe[1], &c, 1) != 1) {
|
||||
cerr << "cannot send signal to osc thread! " << strerror (errno) << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ControlOSC::on_session_load ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ControlOSC::on_session_unload ()
|
||||
{
|
||||
// will be called from main event loop
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
ControlOSC::get_server_url()
|
||||
{
|
||||
string url;
|
||||
char * urlstr;
|
||||
|
||||
if (_osc_server) {
|
||||
urlstr = lo_server_get_url (_osc_server);
|
||||
url = urlstr;
|
||||
free (urlstr);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
std::string
|
||||
ControlOSC::get_unix_server_url()
|
||||
{
|
||||
string url;
|
||||
char * urlstr;
|
||||
|
||||
if (_osc_unix_server) {
|
||||
urlstr = lo_server_get_url (_osc_unix_server);
|
||||
url = urlstr;
|
||||
free (urlstr);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
/* server thread */
|
||||
|
||||
void *
|
||||
ControlOSC::_osc_receiver(void * arg)
|
||||
{
|
||||
static_cast<ControlOSC*> (arg)->osc_receiver();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ControlOSC::osc_receiver()
|
||||
{
|
||||
struct pollfd pfd[3];
|
||||
int fds[3];
|
||||
lo_server srvs[3];
|
||||
int nfds = 0;
|
||||
int timeout = -1;
|
||||
int ret;
|
||||
|
||||
fds[0] = _request_pipe[0];
|
||||
nfds++;
|
||||
|
||||
if (_osc_server && lo_server_get_socket_fd(_osc_server) >= 0) {
|
||||
fds[nfds] = lo_server_get_socket_fd(_osc_server);
|
||||
srvs[nfds] = _osc_server;
|
||||
nfds++;
|
||||
}
|
||||
|
||||
if (_osc_unix_server && lo_server_get_socket_fd(_osc_unix_server) >= 0) {
|
||||
fds[nfds] = lo_server_get_socket_fd(_osc_unix_server);
|
||||
srvs[nfds] = _osc_unix_server;
|
||||
nfds++;
|
||||
}
|
||||
|
||||
|
||||
while (!_shutdown) {
|
||||
|
||||
for (int i=0; i < nfds; ++i) {
|
||||
pfd[i].fd = fds[i];
|
||||
pfd[i].events = POLLIN|POLLPRI|POLLHUP|POLLERR;
|
||||
pfd[i].revents = 0;
|
||||
}
|
||||
|
||||
again:
|
||||
//cerr << "poll on " << nfds << " for " << timeout << endl;
|
||||
if ((ret = poll (pfd, nfds, timeout)) < 0) {
|
||||
if (errno == EINTR) {
|
||||
/* gdb at work, perhaps */
|
||||
cerr << "EINTR hit " << endl;
|
||||
goto again;
|
||||
}
|
||||
|
||||
cerr << "OSC thread poll failed: " << strerror (errno) << endl;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//cerr << "poll returned " << ret << " pfd[0].revents = " << pfd[0].revents << " pfd[1].revents = " << pfd[1].revents << endl;
|
||||
|
||||
if (_shutdown) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((pfd[0].revents & ~POLLIN)) {
|
||||
cerr << "OSC: error polling extra port" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i=1; i < nfds; ++i) {
|
||||
if (pfd[i].revents & POLLIN)
|
||||
{
|
||||
// this invokes callbacks
|
||||
//cerr << "invoking recv on " << pfd[i].fd << endl;
|
||||
lo_server_recv(srvs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//cerr << "SL engine shutdown" << endl;
|
||||
|
||||
if (_osc_server) {
|
||||
int fd = lo_server_get_socket_fd(_osc_server);
|
||||
if (fd >=0) {
|
||||
// hack around
|
||||
close(fd);
|
||||
}
|
||||
lo_server_free (_osc_server);
|
||||
_osc_server = 0;
|
||||
}
|
||||
|
||||
if (_osc_unix_server) {
|
||||
cerr << "freeing unix server" << endl;
|
||||
lo_server_free (_osc_unix_server);
|
||||
_osc_unix_server = 0;
|
||||
}
|
||||
|
||||
close(_request_pipe[0]);
|
||||
close(_request_pipe[1]);
|
||||
}
|
||||
|
||||
void
|
||||
ControlOSC::do_request (OSCRequest* req)
|
||||
{
|
||||
}
|
||||
|
||||
/* path callbacks */
|
||||
|
||||
|
||||
102
libs/surfaces/osc/osc_server.h
Normal file
102
libs/surfaces/osc/osc_server.h
Normal file
@@ -0,0 +1,102 @@
|
||||
#ifndef ardour_osc_control_protocol_h
|
||||
#define ardour_osc_control_protocol_h
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <lo/lo.h>
|
||||
|
||||
#include <pbd/lockmonitor.h>
|
||||
#include <ardour/control_protocol.h>
|
||||
#include <ardour/types.h>
|
||||
|
||||
#include <pbd/abstract_ui.h>
|
||||
|
||||
struct OSCRequest : public BaseUI::BaseRequestObject {
|
||||
/* nothing yet */
|
||||
};
|
||||
|
||||
class ControlOSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCRequest>
|
||||
{
|
||||
public:
|
||||
ControlOSC (ARDOUR::Session&, uint32_t port);
|
||||
virtual ~ControlOSC();
|
||||
|
||||
int set_active (bool yn);
|
||||
|
||||
bool caller_is_ui_thread();
|
||||
|
||||
private:
|
||||
uint32_t _port;
|
||||
volatile bool _ok;
|
||||
volatile bool _shutdown;
|
||||
lo_server _osc_server;
|
||||
lo_server _osc_unix_server;
|
||||
std::string _osc_unix_socket_path;
|
||||
pthread_t _osc_thread;
|
||||
int _request_pipe[2];
|
||||
|
||||
static void * _osc_receiver(void * arg);
|
||||
void osc_receiver();
|
||||
|
||||
bool init_osc_thread ();
|
||||
void terminate_osc_thread ();
|
||||
void poke_osc_thread ();
|
||||
|
||||
void register_callbacks ();
|
||||
|
||||
void on_session_load ();
|
||||
void on_session_unload ();
|
||||
|
||||
std::string get_server_url ();
|
||||
std::string get_unix_server_url ();
|
||||
|
||||
void do_request (OSCRequest* req);
|
||||
|
||||
#define PATH_CALLBACK(name) \
|
||||
static int _ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { \
|
||||
return static_cast<ControlOSC*>(user_data)->cb_ ## name (path, types, argv, argc, data); \
|
||||
} \
|
||||
int cb_ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data) { \
|
||||
name (); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
|
||||
PATH_CALLBACK(add_marker);
|
||||
PATH_CALLBACK(loop_toggle);
|
||||
PATH_CALLBACK(goto_start);
|
||||
PATH_CALLBACK(goto_end);
|
||||
PATH_CALLBACK(rewind);
|
||||
PATH_CALLBACK(ffwd);
|
||||
PATH_CALLBACK(transport_stop);
|
||||
PATH_CALLBACK(transport_play);
|
||||
PATH_CALLBACK(save_state);
|
||||
PATH_CALLBACK(prev_marker);
|
||||
PATH_CALLBACK(next_marker);
|
||||
PATH_CALLBACK(undo);
|
||||
PATH_CALLBACK(redo);
|
||||
PATH_CALLBACK(toggle_punch_in);
|
||||
PATH_CALLBACK(toggle_punch_out);
|
||||
PATH_CALLBACK(rec_enable_toggle);
|
||||
PATH_CALLBACK(toggle_all_rec_enables);
|
||||
|
||||
#define PATH_CALLBACK1(name,type) \
|
||||
static int _ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { \
|
||||
return static_cast<ControlOSC*>(user_data)->cb_ ## name (path, types, argv, argc, data); \
|
||||
} \
|
||||
int cb_ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data) { \
|
||||
if (argc > 0) { \
|
||||
name (argv[0]->type); \
|
||||
}\
|
||||
return 0; \
|
||||
}
|
||||
|
||||
|
||||
PATH_CALLBACK1(set_transport_speed,f);
|
||||
};
|
||||
|
||||
|
||||
#endif // ardour_osc_control_protocol_h
|
||||
@@ -70,12 +70,15 @@ TranzportControlProtocol::TranzportControlProtocol (Session& s)
|
||||
AbstractUI<TranzportRequest> (X_("Tranzport"), false)
|
||||
|
||||
{
|
||||
/* tranzport controls one track at a time */
|
||||
|
||||
set_route_table_size (1);
|
||||
|
||||
timeout = 60000;
|
||||
buttonmask = 0;
|
||||
_datawheel = 0;
|
||||
_device_status = STATUS_OFFLINE;
|
||||
udev = 0;
|
||||
current_route = 0;
|
||||
current_track_id = 0;
|
||||
last_where = max_frames;
|
||||
wheel_mode = WheelTimeline;
|
||||
@@ -139,11 +142,11 @@ TranzportControlProtocol::set_active (bool yn)
|
||||
void
|
||||
TranzportControlProtocol::show_track_gain ()
|
||||
{
|
||||
if (current_route) {
|
||||
gain_t g = current_route->gain();
|
||||
if (route_table[0]) {
|
||||
gain_t g = route_get_gain (0);
|
||||
if (g != last_track_gain) {
|
||||
char buf[16];
|
||||
snprintf (buf, sizeof (buf), "%6.1fdB", coefficient_to_dB (current_route->effective_gain()));
|
||||
snprintf (buf, sizeof (buf), "%6.1fdB", coefficient_to_dB (route_get_effective_gain (0)));
|
||||
print (0, 9, buf);
|
||||
last_track_gain = g;
|
||||
}
|
||||
@@ -234,11 +237,11 @@ log_meter (float db)
|
||||
void
|
||||
TranzportControlProtocol::show_meter ()
|
||||
{
|
||||
if (current_route == 0) {
|
||||
if (route_table[0] == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
float level = current_route->peak_input_power (0);
|
||||
float level = route_get_peak_input_power (0, 0);
|
||||
float fraction = log_meter (level);
|
||||
|
||||
/* we draw using a choice of a sort of double colon-like character ("::") or a single, left-aligned ":".
|
||||
@@ -579,10 +582,6 @@ TranzportControlProtocol::monitor_work ()
|
||||
val = usb_interrupt_read (udev, READ_ENDPOINT, (char*) buf, 8, 10);
|
||||
pthread_testcancel();
|
||||
|
||||
/* any requests to handle? */
|
||||
|
||||
handle_ui_requests ();
|
||||
|
||||
if (val == 8) {
|
||||
process (buf);
|
||||
}
|
||||
@@ -673,19 +672,19 @@ TranzportControlProtocol::update_state ()
|
||||
|
||||
/* per track */
|
||||
|
||||
if (current_route) {
|
||||
AudioTrack* at = dynamic_cast<AudioTrack*> (current_route);
|
||||
if (route_table[0]) {
|
||||
AudioTrack* at = dynamic_cast<AudioTrack*> (route_table[0]);
|
||||
if (at && at->record_enabled()) {
|
||||
pending_lights[LightTrackrec] = true;
|
||||
} else {
|
||||
pending_lights[LightTrackrec] = false;
|
||||
}
|
||||
if (current_route->muted()) {
|
||||
if (route_get_muted (0)) {
|
||||
pending_lights[LightTrackmute] = true;
|
||||
} else {
|
||||
pending_lights[LightTrackmute] = false;
|
||||
}
|
||||
if (current_route->soloed()) {
|
||||
if (route_get_soloed (0)) {
|
||||
pending_lights[LightTracksolo] = true;
|
||||
} else {
|
||||
pending_lights[LightTracksolo] = false;
|
||||
@@ -954,10 +953,10 @@ TranzportControlProtocol::process (uint8_t* buf)
|
||||
void
|
||||
TranzportControlProtocol::show_current_track ()
|
||||
{
|
||||
if (current_route == 0) {
|
||||
if (route_table[0] == 0) {
|
||||
print (0, 0, "--------");
|
||||
} else {
|
||||
print (0, 0, current_route->name().substr (0, 8).c_str());
|
||||
print (0, 0, route_get_name (0).substr (0, 8).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1009,10 +1008,7 @@ TranzportControlProtocol::button_event_trackrec_press (bool shifted)
|
||||
if (shifted) {
|
||||
toggle_all_rec_enables ();
|
||||
} else {
|
||||
if (current_route) {
|
||||
AudioTrack* at = dynamic_cast<AudioTrack*>(current_route);
|
||||
at->set_record_enable (!at->record_enabled(), this);
|
||||
}
|
||||
route_set_rec_enable (0, !route_get_rec_enable (0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1024,9 +1020,7 @@ TranzportControlProtocol::button_event_trackrec_release (bool shifted)
|
||||
void
|
||||
TranzportControlProtocol::button_event_trackmute_press (bool shifted)
|
||||
{
|
||||
if (current_route) {
|
||||
current_route->set_mute (!current_route->muted(), this);
|
||||
}
|
||||
route_set_muted (0, !route_get_muted (0));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1045,9 +1039,7 @@ TranzportControlProtocol::button_event_tracksolo_press (bool shifted)
|
||||
if (shifted) {
|
||||
session.set_all_solo (!session.soloing());
|
||||
} else {
|
||||
if (current_route) {
|
||||
current_route->set_solo (!current_route->soloed(), this);
|
||||
}
|
||||
route_set_soloed (0, !route_get_soloed (0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1267,7 +1259,7 @@ TranzportControlProtocol::datawheel ()
|
||||
|
||||
/* parameter control */
|
||||
|
||||
if (current_route) {
|
||||
if (route_table[0]) {
|
||||
switch (wheel_shift_mode) {
|
||||
case WheelShiftGain:
|
||||
if (_datawheel < WheelDirectionThreshold) {
|
||||
@@ -1358,7 +1350,7 @@ TranzportControlProtocol::scrub ()
|
||||
last_wheel_motion = now;
|
||||
last_wheel_dir = dir;
|
||||
|
||||
move_at (speed * dir);
|
||||
set_transport_speed (speed * dir);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1392,7 +1384,7 @@ TranzportControlProtocol::step_gain_up ()
|
||||
gain_fraction = 2.0;
|
||||
}
|
||||
|
||||
current_route->set_gain (slider_position_to_gain (gain_fraction), this);
|
||||
route_set_gain (0, slider_position_to_gain (gain_fraction));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1408,7 +1400,7 @@ TranzportControlProtocol::step_gain_down ()
|
||||
gain_fraction = 0.0;
|
||||
}
|
||||
|
||||
current_route->set_gain (slider_position_to_gain (gain_fraction), this);
|
||||
route_set_gain (0, slider_position_to_gain (gain_fraction));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1458,83 +1450,15 @@ TranzportControlProtocol::next_wheel_mode ()
|
||||
void
|
||||
TranzportControlProtocol::next_track ()
|
||||
{
|
||||
uint32_t limit = session.nroutes();
|
||||
uint32_t start = current_track_id;
|
||||
Route* cr = current_route;
|
||||
|
||||
if (current_track_id == limit) {
|
||||
current_track_id = 0;
|
||||
} else {
|
||||
current_track_id++;
|
||||
}
|
||||
|
||||
while (current_track_id < limit) {
|
||||
if ((cr = session.route_by_remote_id (current_track_id)) != 0) {
|
||||
break;
|
||||
}
|
||||
current_track_id++;
|
||||
}
|
||||
|
||||
if (current_track_id == limit) {
|
||||
current_track_id = 0;
|
||||
while (current_track_id != start) {
|
||||
if ((cr = session.route_by_remote_id (current_track_id)) != 0) {
|
||||
break;
|
||||
}
|
||||
current_track_id++;
|
||||
}
|
||||
}
|
||||
|
||||
current_route = cr;
|
||||
gain_fraction = gain_to_slider_position (current_route->effective_gain());
|
||||
ControlProtocol::next_track (current_track_id);
|
||||
gain_fraction = gain_to_slider_position (route_get_effective_gain (0));
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::prev_track ()
|
||||
{
|
||||
uint32_t limit = session.nroutes() - 1;
|
||||
uint32_t start = current_track_id;
|
||||
Route* cr = current_route;
|
||||
|
||||
if (current_track_id == 0) {
|
||||
current_track_id = session.nroutes() - 1;
|
||||
} else {
|
||||
current_track_id--;
|
||||
}
|
||||
|
||||
while (current_track_id >= 0) {
|
||||
if ((cr = session.route_by_remote_id (current_track_id)) != 0) {
|
||||
break;
|
||||
}
|
||||
current_track_id--;
|
||||
}
|
||||
|
||||
if (current_track_id < 0) {
|
||||
current_track_id = limit;
|
||||
while (current_track_id > start) {
|
||||
if ((cr = session.route_by_remote_id (current_track_id)) != 0) {
|
||||
break;
|
||||
}
|
||||
current_track_id--;
|
||||
}
|
||||
}
|
||||
|
||||
current_route = cr;
|
||||
gain_fraction = gain_to_slider_position (current_route->effective_gain());
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::set_current_track (Route* r)
|
||||
{
|
||||
TranzportRequest* req = get_request (SetCurrentTrack);
|
||||
|
||||
if (req == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
req->track = r;
|
||||
|
||||
send_request (req);
|
||||
ControlProtocol::prev_track (current_track_id);
|
||||
gain_fraction = gain_to_slider_position (route_get_effective_gain (0));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1640,8 +1564,8 @@ void
|
||||
TranzportControlProtocol::do_request (TranzportRequest* req)
|
||||
{
|
||||
if (req->type == SetCurrentTrack) {
|
||||
current_route = req->track;
|
||||
}
|
||||
|
||||
return;
|
||||
route_table[0] = req->track;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,6 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol, public Abstract
|
||||
uint8_t _device_status;
|
||||
usb_dev_handle* udev;
|
||||
|
||||
ARDOUR::Route* current_route;
|
||||
uint32_t current_track_id;
|
||||
WheelMode wheel_mode;
|
||||
WheelShiftMode wheel_shift_mode;
|
||||
|
||||
Reference in New Issue
Block a user