mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-08 15:54:57 +01:00
a) dynamically loadable control surface support
b) move tranzport and generic midi into separate dirs under "surfaces" git-svn-id: svn://localhost/trunk/ardour2@442 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
f7c82c6911
commit
9ae0f6cbee
20 changed files with 356 additions and 293 deletions
|
|
@ -518,6 +518,11 @@ else:
|
||||||
'gtk2_ardour'
|
'gtk2_ardour'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
surface_subdirs = [
|
||||||
|
'libs/surfaces/tranzport',
|
||||||
|
'libs/surfaces/generic_midi'
|
||||||
|
]
|
||||||
|
|
||||||
opts.Save('scache.conf', env)
|
opts.Save('scache.conf', env)
|
||||||
Help(opts.GenerateHelpText(env))
|
Help(opts.GenerateHelpText(env))
|
||||||
|
|
||||||
|
|
@ -791,7 +796,7 @@ env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
|
||||||
for subdir in coredirs:
|
for subdir in coredirs:
|
||||||
SConscript (subdir + '/SConscript')
|
SConscript (subdir + '/SConscript')
|
||||||
|
|
||||||
for sublistdir in [subdirs, gtk_subdirs]:
|
for sublistdir in [subdirs, gtk_subdirs, surface_subdirs]:
|
||||||
for subdir in sublistdir:
|
for subdir in sublistdir:
|
||||||
SConscript (subdir + '/SConscript')
|
SConscript (subdir + '/SConscript')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
source ardev_common.sh
|
source ardev_common.sh
|
||||||
exec valgrind --num-callers=12 --tool=memcheck ./ardour.bin --novst $*
|
exec valgrind --db-attach=yes --num-callers=12 --tool=memcheck ./ardour.bin --novst $*
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ automation_event.cc
|
||||||
configuration.cc
|
configuration.cc
|
||||||
connection.cc
|
connection.cc
|
||||||
control_protocol.cc
|
control_protocol.cc
|
||||||
|
control_protocol_manager.cc
|
||||||
crossfade.cc
|
crossfade.cc
|
||||||
curve.cc
|
curve.cc
|
||||||
cycle_timer.cc
|
cycle_timer.cc
|
||||||
|
|
@ -42,7 +43,6 @@ externalsource.cc
|
||||||
filesource.cc
|
filesource.cc
|
||||||
gain.cc
|
gain.cc
|
||||||
gdither.cc
|
gdither.cc
|
||||||
generic_midi_control_protocol.cc
|
|
||||||
globals.cc
|
globals.cc
|
||||||
import.cc
|
import.cc
|
||||||
insert.cc
|
insert.cc
|
||||||
|
|
@ -69,10 +69,8 @@ send.cc
|
||||||
session.cc
|
session.cc
|
||||||
session_butler.cc
|
session_butler.cc
|
||||||
session_click.cc
|
session_click.cc
|
||||||
session_control.cc
|
|
||||||
session_events.cc
|
session_events.cc
|
||||||
session_export.cc
|
session_export.cc
|
||||||
session_feedback.cc
|
|
||||||
session_midi.cc
|
session_midi.cc
|
||||||
session_process.cc
|
session_process.cc
|
||||||
session_state.cc
|
session_state.cc
|
||||||
|
|
@ -85,7 +83,6 @@ source.cc
|
||||||
state_manager.cc
|
state_manager.cc
|
||||||
stateful.cc
|
stateful.cc
|
||||||
tempo.cc
|
tempo.cc
|
||||||
tranzport_control_protocol.cc
|
|
||||||
utils.cc
|
utils.cc
|
||||||
version.cc
|
version.cc
|
||||||
mix.cc
|
mix.cc
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ class ControlProtocol : sigc::trackable {
|
||||||
virtual ~ControlProtocol();
|
virtual ~ControlProtocol();
|
||||||
|
|
||||||
virtual int init () { return 0; }
|
virtual int init () { return 0; }
|
||||||
virtual bool active() const = 0;
|
|
||||||
|
sigc::signal<void> ActiveChanged;
|
||||||
|
|
||||||
enum SendWhat {
|
enum SendWhat {
|
||||||
SendRoute,
|
SendRoute,
|
||||||
|
|
@ -26,6 +27,9 @@ class ControlProtocol : sigc::trackable {
|
||||||
std::string name() const { return _name; }
|
std::string name() const { return _name; }
|
||||||
|
|
||||||
void set_send (SendWhat);
|
void set_send (SendWhat);
|
||||||
|
void set_active (bool yn);
|
||||||
|
bool get_active() const { return active_thread > 0; }
|
||||||
|
|
||||||
|
|
||||||
bool send() const { return _send != 0; }
|
bool send() const { return _send != 0; }
|
||||||
bool send_route_feedback () const { return _send & SendRoute; }
|
bool send_route_feedback () const { return _send & SendRoute; }
|
||||||
|
|
@ -35,10 +39,42 @@ class ControlProtocol : sigc::trackable {
|
||||||
virtual void send_global_feedback () {}
|
virtual void send_global_feedback () {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
ARDOUR::Session& session;
|
ARDOUR::Session& session;
|
||||||
SendWhat _send;
|
SendWhat _send;
|
||||||
std::string _name;
|
std::string _name;
|
||||||
|
int active_thread;
|
||||||
|
int thread_request_pipe[2];
|
||||||
|
pthread_t _thread;
|
||||||
|
|
||||||
|
static void* _thread_work (void *);
|
||||||
|
void* thread_work ();
|
||||||
|
|
||||||
|
struct ThreadRequest {
|
||||||
|
enum Type {
|
||||||
|
Start,
|
||||||
|
Stop,
|
||||||
|
Quit
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
int init_thread();
|
||||||
|
int start_thread ();
|
||||||
|
int stop_thread ();
|
||||||
|
void terminate_thread ();
|
||||||
|
int poke_thread (ThreadRequest::Type);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct ControlProtocolDescriptor {
|
||||||
|
const char* name;
|
||||||
|
void* ptr;
|
||||||
|
void* module;
|
||||||
|
ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*);
|
||||||
|
void (*destroy)(ControlProtocolDescriptor*,ControlProtocol*);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,7 @@ class AudioRegion;
|
||||||
class Region;
|
class Region;
|
||||||
class Playlist;
|
class Playlist;
|
||||||
class VSTPlugin;
|
class VSTPlugin;
|
||||||
class ControlProtocol;
|
class ControlProtocolManager;
|
||||||
class GenericMidiControlProtocol;
|
|
||||||
|
|
||||||
struct AudioExportSpecification;
|
struct AudioExportSpecification;
|
||||||
struct RouteGroup;
|
struct RouteGroup;
|
||||||
|
|
@ -246,6 +245,8 @@ class Session : public sigc::trackable, public Stateful
|
||||||
std::string dead_sound_dir () const;
|
std::string dead_sound_dir () const;
|
||||||
std::string automation_dir () const;
|
std::string automation_dir () const;
|
||||||
|
|
||||||
|
static string suffixed_search_path (std::string suffix);
|
||||||
|
static string control_protocol_path ();
|
||||||
static string template_path ();
|
static string template_path ();
|
||||||
static string template_dir ();
|
static string template_dir ();
|
||||||
static void get_template_list (list<string>&);
|
static void get_template_list (list<string>&);
|
||||||
|
|
@ -428,7 +429,6 @@ class Session : public sigc::trackable, public Stateful
|
||||||
void set_do_not_record_plugins (bool yn);
|
void set_do_not_record_plugins (bool yn);
|
||||||
void set_crossfades_active (bool yn);
|
void set_crossfades_active (bool yn);
|
||||||
void set_seamless_loop (bool yn);
|
void set_seamless_loop (bool yn);
|
||||||
void set_feedback (bool yn);
|
|
||||||
|
|
||||||
bool get_auto_play () const { return auto_play; }
|
bool get_auto_play () const { return auto_play; }
|
||||||
bool get_auto_input () const { return auto_input; }
|
bool get_auto_input () const { return auto_input; }
|
||||||
|
|
@ -445,8 +445,6 @@ class Session : public sigc::trackable, public Stateful
|
||||||
bool get_midi_control () const;
|
bool get_midi_control () const;
|
||||||
bool get_do_not_record_plugins () const { return do_not_record_plugins; }
|
bool get_do_not_record_plugins () const { return do_not_record_plugins; }
|
||||||
bool get_crossfades_active () const { return crossfades_active; }
|
bool get_crossfades_active () const { return crossfades_active; }
|
||||||
bool get_feedback() const;
|
|
||||||
bool get_tranzport_control() const;
|
|
||||||
|
|
||||||
bool get_input_auto_connect () const;
|
bool get_input_auto_connect () const;
|
||||||
AutoConnectOption get_output_auto_connect () const { return output_auto_connect; }
|
AutoConnectOption get_output_auto_connect () const { return output_auto_connect; }
|
||||||
|
|
@ -1136,7 +1134,6 @@ class Session : public sigc::trackable, public Stateful
|
||||||
bool send_mmc;
|
bool send_mmc;
|
||||||
bool mmc_control;
|
bool mmc_control;
|
||||||
bool midi_control;
|
bool midi_control;
|
||||||
bool midi_feedback;
|
|
||||||
|
|
||||||
RingBuffer<Event*> pending_events;
|
RingBuffer<Event*> pending_events;
|
||||||
|
|
||||||
|
|
@ -1363,31 +1360,6 @@ class Session : public sigc::trackable, public Stateful
|
||||||
void send_time_code_in_another_thread (bool full);
|
void send_time_code_in_another_thread (bool full);
|
||||||
void send_mmc_in_another_thread (MIDI::MachineControl::Command, jack_nframes_t frame = 0);
|
void send_mmc_in_another_thread (MIDI::MachineControl::Command, jack_nframes_t frame = 0);
|
||||||
|
|
||||||
/* Feedback */
|
|
||||||
|
|
||||||
typedef sigc::slot<int> FeedbackFunctionPtr;
|
|
||||||
static void* _feedback_thread_work (void *);
|
|
||||||
void* feedback_thread_work ();
|
|
||||||
int feedback_generic_midi_function ();
|
|
||||||
std::list<FeedbackFunctionPtr> feedback_functions;
|
|
||||||
int active_feedback;
|
|
||||||
int feedback_request_pipe[2];
|
|
||||||
pthread_t feedback_thread;
|
|
||||||
|
|
||||||
struct FeedbackRequest {
|
|
||||||
enum Type {
|
|
||||||
Start,
|
|
||||||
Stop,
|
|
||||||
Quit
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
int init_feedback();
|
|
||||||
int start_feedback ();
|
|
||||||
int stop_feedback ();
|
|
||||||
void terminate_feedback ();
|
|
||||||
int poke_feedback (FeedbackRequest::Type);
|
|
||||||
|
|
||||||
jack_nframes_t adjust_apparent_position (jack_nframes_t frames);
|
jack_nframes_t adjust_apparent_position (jack_nframes_t frames);
|
||||||
|
|
||||||
void reset_record_status ();
|
void reset_record_status ();
|
||||||
|
|
@ -1770,12 +1742,6 @@ class Session : public sigc::trackable, public Stateful
|
||||||
|
|
||||||
LayerModel layer_model;
|
LayerModel layer_model;
|
||||||
CrossfadeModel xfade_model;
|
CrossfadeModel xfade_model;
|
||||||
|
|
||||||
/* control protocols */
|
|
||||||
|
|
||||||
vector<ControlProtocol*> control_protocols;
|
|
||||||
GenericMidiControlProtocol* generic_midi_control_protocol;
|
|
||||||
void initialize_control ();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}; /* namespace ARDOUR */
|
}; /* namespace ARDOUR */
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@
|
||||||
#include <ardour/source.h>
|
#include <ardour/source.h>
|
||||||
#include <ardour/utils.h>
|
#include <ardour/utils.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
|
#include <ardour/control_protocol_manager.h>
|
||||||
|
|
||||||
#include <ardour/mix.h>
|
#include <ardour/mix.h>
|
||||||
|
|
||||||
|
|
@ -71,7 +72,6 @@ Change ARDOUR::PositionChanged = ARDOUR::new_change ();
|
||||||
Change ARDOUR::NameChanged = ARDOUR::new_change ();
|
Change ARDOUR::NameChanged = ARDOUR::new_change ();
|
||||||
Change ARDOUR::BoundsChanged = Change (0); // see init(), below
|
Change ARDOUR::BoundsChanged = Change (0); // see init(), below
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
setup_midi ()
|
setup_midi ()
|
||||||
{
|
{
|
||||||
|
|
@ -266,6 +266,10 @@ ARDOUR::init (AudioEngine& engine, bool use_vst, bool try_optimization, void (*s
|
||||||
/* singleton - first object is "it" */
|
/* singleton - first object is "it" */
|
||||||
new PluginManager (engine);
|
new PluginManager (engine);
|
||||||
|
|
||||||
|
/* singleton - first object is "it" */
|
||||||
|
new ControlProtocolManager ();
|
||||||
|
ControlProtocolManager::instance().discover_control_protocols (Session::control_protocol_path());
|
||||||
|
|
||||||
BoundsChanged = Change (StartChanged|PositionChanged|LengthChanged);
|
BoundsChanged = Change (StartChanged|PositionChanged|LengthChanged);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -361,7 +361,6 @@ Session::~Session ()
|
||||||
|
|
||||||
terminate_butler_thread ();
|
terminate_butler_thread ();
|
||||||
terminate_midi_thread ();
|
terminate_midi_thread ();
|
||||||
terminate_feedback ();
|
|
||||||
|
|
||||||
if (click_data && click_data != default_click) {
|
if (click_data && click_data != default_click) {
|
||||||
delete [] click_data;
|
delete [] click_data;
|
||||||
|
|
|
||||||
|
|
@ -45,198 +45,5 @@ using namespace std;
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
//using namespace sigc;
|
//using namespace sigc;
|
||||||
|
|
||||||
int
|
|
||||||
Session::init_feedback ()
|
|
||||||
{
|
|
||||||
if (pipe (feedback_request_pipe) != 0) {
|
|
||||||
error << string_compose (_("cannot create feedback request pipe (%1)"),
|
|
||||||
strerror (errno))
|
|
||||||
<< endmsg;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fcntl (feedback_request_pipe[0], F_SETFL, O_NONBLOCK)) {
|
|
||||||
error << string_compose(_("UI: cannot set O_NONBLOCK on " "signal read pipe (%1)"), strerror (errno)) << endmsg;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fcntl (feedback_request_pipe[1], F_SETFL, O_NONBLOCK)) {
|
|
||||||
error << string_compose(_("UI: cannot set O_NONBLOCK on " "signal write pipe (%1)"), strerror (errno)) << endmsg;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
active_feedback = 0;
|
|
||||||
|
|
||||||
if (pthread_create_and_store ("feedback", &feedback_thread, 0, _feedback_thread_work, this)) {
|
|
||||||
error << _("Session: could not create feedback thread") << endmsg;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
Session::poke_feedback (FeedbackRequest::Type why)
|
|
||||||
{
|
|
||||||
char c = (char) why;
|
|
||||||
return !(write (feedback_request_pipe[1], &c, 1) == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
Session::start_feedback ()
|
|
||||||
{
|
|
||||||
return poke_feedback (FeedbackRequest::Start);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
Session::stop_feedback ()
|
|
||||||
{
|
|
||||||
return poke_feedback (FeedbackRequest::Stop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Session::set_feedback (bool yn)
|
|
||||||
{
|
|
||||||
set_dirty();
|
|
||||||
|
|
||||||
if (yn) {
|
|
||||||
/* make sure the feedback thread is alive */
|
|
||||||
start_feedback ();
|
|
||||||
} else {
|
|
||||||
/* maybe put the feedback thread to sleep */
|
|
||||||
stop_feedback ();
|
|
||||||
}
|
|
||||||
|
|
||||||
ControlChanged (Feedback); /* EMIT SIGNAL */
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Session::get_feedback() const
|
|
||||||
{
|
|
||||||
return active_feedback > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Session::terminate_feedback ()
|
|
||||||
{
|
|
||||||
void* status;
|
|
||||||
poke_feedback (FeedbackRequest::Quit);
|
|
||||||
pthread_join (feedback_thread, &status);
|
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
|
||||||
Session::_feedback_thread_work (void* arg)
|
|
||||||
{
|
|
||||||
return static_cast<Session*> (arg)->feedback_thread_work ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
|
||||||
Session::feedback_thread_work ()
|
|
||||||
{
|
|
||||||
PBD::ThreadCreated (pthread_self(), X_("Feedback"));
|
|
||||||
struct pollfd pfd[1];
|
|
||||||
int timeout;
|
|
||||||
|
|
||||||
pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, 0);
|
|
||||||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
|
|
||||||
|
|
||||||
if (active_feedback) {
|
|
||||||
timeout = max (5, (int) Config->get_feedback_interval_ms());
|
|
||||||
} else {
|
|
||||||
timeout = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
|
|
||||||
pfd[0].fd = feedback_request_pipe[0];
|
|
||||||
pfd[0].events = POLLIN|POLLHUP|POLLERR;
|
|
||||||
|
|
||||||
if (poll (pfd, 1, timeout) < 0) {
|
|
||||||
if (errno == EINTR) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
error << string_compose (_("Feedback thread poll failed (%1)"),
|
|
||||||
strerror (errno))
|
|
||||||
<< endmsg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pfd[0].revents & ~POLLIN) {
|
|
||||||
error << _("Error on feedback thread request pipe") << endmsg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pfd[0].revents & POLLIN) {
|
|
||||||
|
|
||||||
char req;
|
|
||||||
|
|
||||||
/* empty the pipe of all current requests */
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
size_t nread = read (feedback_request_pipe[0], &req, sizeof (req));
|
|
||||||
|
|
||||||
if (nread == 1) {
|
|
||||||
switch ((FeedbackRequest::Type) req) {
|
|
||||||
|
|
||||||
case FeedbackRequest::Start:
|
|
||||||
timeout = max (5, (int) Config->get_feedback_interval_ms());
|
|
||||||
active_feedback++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FeedbackRequest::Stop:
|
|
||||||
timeout = -1;
|
|
||||||
if (active_feedback) {
|
|
||||||
active_feedback--;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FeedbackRequest::Quit:
|
|
||||||
pthread_exit_pbd (0);
|
|
||||||
/*NOTREACHED*/
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (nread == 0) {
|
|
||||||
break;
|
|
||||||
} else if (errno == EAGAIN) {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
fatal << _("Error reading from feedback request pipe") << endmsg;
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!active_feedback || transport_stopped()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool send = false;
|
|
||||||
|
|
||||||
for (vector<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
|
|
||||||
if ((*i)->send()) {
|
|
||||||
send = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (send) {
|
|
||||||
|
|
||||||
RouteList routes = get_routes(); /* copies the routes */
|
|
||||||
|
|
||||||
for (vector<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
|
|
||||||
if ((*i)->send_route_feedback ()) {
|
|
||||||
(*i)->send_route_feedback (routes);
|
|
||||||
}
|
|
||||||
(*i)->send_global_feedback ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@
|
||||||
#include <ardour/diskstream.h>
|
#include <ardour/diskstream.h>
|
||||||
#include <ardour/slave.h>
|
#include <ardour/slave.h>
|
||||||
#include <ardour/cycles.h>
|
#include <ardour/cycles.h>
|
||||||
#include <ardour/generic_midi_control_protocol.h>
|
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
@ -170,19 +169,12 @@ Session::set_send_mmc (bool yn)
|
||||||
void
|
void
|
||||||
Session::set_midi_feedback (bool yn)
|
Session::set_midi_feedback (bool yn)
|
||||||
{
|
{
|
||||||
if (generic_midi_control_protocol) {
|
|
||||||
if (yn) {
|
|
||||||
generic_midi_control_protocol->set_send (ControlProtocol::SendRoute);
|
|
||||||
} else {
|
|
||||||
generic_midi_control_protocol->set_send (ControlProtocol::SendWhat (0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Session::get_midi_feedback () const
|
Session::get_midi_feedback () const
|
||||||
{
|
{
|
||||||
return generic_midi_control_protocol && generic_midi_control_protocol->active();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -328,9 +320,9 @@ Session::set_midi_port (string port_tag)
|
||||||
|
|
||||||
_midi_port = port;
|
_midi_port = port;
|
||||||
|
|
||||||
if (generic_midi_control_protocol) {
|
/* XXX need something to forward this to control protocols ? or just
|
||||||
generic_midi_control_protocol->set_port (port);
|
use the signal below
|
||||||
}
|
*/
|
||||||
|
|
||||||
Config->set_midi_port_name (port_tag);
|
Config->set_midi_port_name (port_tag);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@
|
||||||
#include <ardour/location.h>
|
#include <ardour/location.h>
|
||||||
#include <ardour/audioregion.h>
|
#include <ardour/audioregion.h>
|
||||||
#include <ardour/crossfade.h>
|
#include <ardour/crossfade.h>
|
||||||
|
#include <ardour/control_protocol_manager.h>
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
|
@ -165,9 +166,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
|
||||||
butler_mixdown_buffer = 0;
|
butler_mixdown_buffer = 0;
|
||||||
butler_gain_buffer = 0;
|
butler_gain_buffer = 0;
|
||||||
auditioner = 0;
|
auditioner = 0;
|
||||||
generic_midi_control_protocol = 0;
|
|
||||||
mmc_control = false;
|
mmc_control = false;
|
||||||
midi_feedback = false;
|
|
||||||
midi_control = true;
|
midi_control = true;
|
||||||
mmc = 0;
|
mmc = 0;
|
||||||
post_transport_work = PostTransportWork (0);
|
post_transport_work = PostTransportWork (0);
|
||||||
|
|
@ -302,12 +301,6 @@ Session::second_stage_init (bool new_session)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize_control();
|
|
||||||
|
|
||||||
if (init_feedback ()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state_tree) {
|
if (state_tree) {
|
||||||
if (set_state (*state_tree->root())) {
|
if (set_state (*state_tree->root())) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -348,7 +341,7 @@ Session::second_stage_init (bool new_session)
|
||||||
deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
|
deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
|
||||||
deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
|
deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
|
||||||
|
|
||||||
// XXX need to poke the feedback thread to send full state
|
ControlProtocolManager::instance().startup (*this);
|
||||||
|
|
||||||
if (new_session) {
|
if (new_session) {
|
||||||
_end_location_is_free = true;
|
_end_location_is_free = true;
|
||||||
|
|
@ -2300,7 +2293,7 @@ Session::template_dir ()
|
||||||
}
|
}
|
||||||
|
|
||||||
string
|
string
|
||||||
Session::template_path ()
|
Session::suffixed_search_path (string suffix)
|
||||||
{
|
{
|
||||||
string path;
|
string path;
|
||||||
|
|
||||||
|
|
@ -2317,7 +2310,8 @@ Session::template_path ()
|
||||||
|
|
||||||
for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
|
for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
|
||||||
path += *i;
|
path += *i;
|
||||||
path += "templates/";
|
path += suffix;
|
||||||
|
path += '/';
|
||||||
|
|
||||||
if (distance (i, split_path.end()) != 1) {
|
if (distance (i, split_path.end()) != 1) {
|
||||||
path += ':';
|
path += ':';
|
||||||
|
|
@ -2327,6 +2321,18 @@ Session::template_path ()
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
Session::template_path ()
|
||||||
|
{
|
||||||
|
return suffixed_search_path (X_("templates"));
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
Session::control_protocol_path ()
|
||||||
|
{
|
||||||
|
return suffixed_search_path (X_("surfaces"));
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Session::load_connections (const XMLNode& node)
|
Session::load_connections (const XMLNode& node)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -257,3 +257,4 @@ path_expand (string path)
|
||||||
return path;
|
return path;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <pbd/pthread_utils.h>
|
#include <pbd/pthread_utils.h>
|
||||||
|
|
||||||
using std::string;
|
using namespace std;
|
||||||
|
|
||||||
typedef std::map<string,pthread_t> ThreadMap;
|
typedef std::map<string,pthread_t> ThreadMap;
|
||||||
static ThreadMap all_threads;
|
static ThreadMap all_threads;
|
||||||
|
|
@ -43,6 +43,8 @@ pthread_create_and_store (string name, pthread_t *thread, pthread_attr_t *attr,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
cerr << "Creating thread " << name << endl;
|
||||||
|
|
||||||
if ((ret = pthread_create (thread, attr, start_routine, arg)) == 0) {
|
if ((ret = pthread_create (thread, attr, start_routine, arg)) == 0) {
|
||||||
std::pair<string,pthread_t> newpair;
|
std::pair<string,pthread_t> newpair;
|
||||||
newpair.first = name;
|
newpair.first = name;
|
||||||
|
|
|
||||||
51
libs/surfaces/generic_midi/SConscript
Normal file
51
libs/surfaces/generic_midi/SConscript
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
# -*- python -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import glob
|
||||||
|
|
||||||
|
Import('env final_prefix install_prefix final_config_prefix libraries i18n')
|
||||||
|
|
||||||
|
genericmidi = env.Copy()
|
||||||
|
|
||||||
|
#
|
||||||
|
# this defines the version number of libardour_genericmidi
|
||||||
|
#
|
||||||
|
|
||||||
|
domain = 'ardour_genericmidi'
|
||||||
|
|
||||||
|
genericmidi.Append(DOMAIN = domain, MAJOR = 1, MINOR = 0, MICRO = 0)
|
||||||
|
genericmidi.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
|
||||||
|
genericmidi.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
|
||||||
|
genericmidi.Append(PACKAGE = domain)
|
||||||
|
genericmidi.Append(POTFILE = domain + '.pot')
|
||||||
|
|
||||||
|
genericmidi_files=Split("""
|
||||||
|
interface.cc
|
||||||
|
generic_midi_control_protocol.cc
|
||||||
|
""")
|
||||||
|
|
||||||
|
genericmidi.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
|
||||||
|
genericmidi.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
|
||||||
|
genericmidi.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
|
||||||
|
genericmidi.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
|
||||||
|
|
||||||
|
genericmidi.Merge ([
|
||||||
|
libraries['usb'],
|
||||||
|
libraries['ardour'],
|
||||||
|
libraries['sigc2'],
|
||||||
|
libraries['pbd3'],
|
||||||
|
libraries['midi++2'],
|
||||||
|
libraries['xml']
|
||||||
|
])
|
||||||
|
|
||||||
|
libardour_genericmidi = genericmidi.SharedLibrary('ardour_genericmidi', genericmidi_files)
|
||||||
|
|
||||||
|
Default(libardour_genericmidi)
|
||||||
|
|
||||||
|
if env['NLS']:
|
||||||
|
i18n (genericmidi, genericmidi_files, env)
|
||||||
|
|
||||||
|
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
||||||
|
[ 'SConscript', 'i18n.h', 'gettext.h' ] +
|
||||||
|
genericmidi_files +
|
||||||
|
glob.glob('po/*.po') + glob.glob('*.h')))
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
#include <ardour/generic_midi_control_protocol.h>
|
|
||||||
#include <ardour/route.h>
|
#include <ardour/route.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
|
|
||||||
|
#include "generic_midi_control_protocol.h"
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
34
libs/surfaces/generic_midi/interface.cc
Normal file
34
libs/surfaces/generic_midi/interface.cc
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include <ardour/control_protocol.h>
|
||||||
|
|
||||||
|
#include "generic_midi_control_protocol.h"
|
||||||
|
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
ControlProtocol*
|
||||||
|
new_generic_midi_protocol (ControlProtocolDescriptor* descriptor, Session* s)
|
||||||
|
{
|
||||||
|
return new GenericMidiControlProtocol (*s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
delete_generic_midi_protocol (ControlProtocolDescriptor* descriptor, ControlProtocol* cp)
|
||||||
|
{
|
||||||
|
delete cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ControlProtocolDescriptor generic_midi_descriptor = {
|
||||||
|
name : "Generic MIDI",
|
||||||
|
ptr : 0,
|
||||||
|
module : 0,
|
||||||
|
initialize : new_generic_midi_protocol,
|
||||||
|
destroy : delete_generic_midi_protocol
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
ControlProtocolDescriptor*
|
||||||
|
protocol_descriptor () {
|
||||||
|
return &generic_midi_descriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
52
libs/surfaces/tranzport/SConscript
Normal file
52
libs/surfaces/tranzport/SConscript
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
# -*- python -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import glob
|
||||||
|
|
||||||
|
Import('env final_prefix install_prefix final_config_prefix libraries i18n')
|
||||||
|
|
||||||
|
tranzport = env.Copy()
|
||||||
|
|
||||||
|
#
|
||||||
|
# this defines the version number of libardour_tranzport
|
||||||
|
#
|
||||||
|
|
||||||
|
domain = 'ardour_tranzport'
|
||||||
|
|
||||||
|
tranzport.Append(DOMAIN = domain, MAJOR = 1, MINOR = 0, MICRO = 0)
|
||||||
|
tranzport.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
|
||||||
|
tranzport.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
|
||||||
|
tranzport.Append(PACKAGE = domain)
|
||||||
|
tranzport.Append(POTFILE = domain + '.pot')
|
||||||
|
|
||||||
|
tranzport_files=Split("""
|
||||||
|
interface.cc
|
||||||
|
tranzport_control_protocol.cc
|
||||||
|
""")
|
||||||
|
|
||||||
|
tranzport.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
|
||||||
|
tranzport.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
|
||||||
|
tranzport.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
|
||||||
|
tranzport.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
|
||||||
|
|
||||||
|
tranzport.Append(CPPPATH=libraries['ardour'].get ('CPPPATH', []))
|
||||||
|
tranzport.Append(CPPPATH=libraries['sigc2'].get ('CPPPATH', []))
|
||||||
|
tranzport.Append(CPPPATH=libraries['pbd3'].get ('CPPPATH', []))
|
||||||
|
tranzport.Append(CPPPATH=libraries['midi++2'].get ('CPPPATH', []))
|
||||||
|
|
||||||
|
tranzport.Merge ([
|
||||||
|
libraries['xml'],
|
||||||
|
libraries['usb']
|
||||||
|
])
|
||||||
|
|
||||||
|
libardour_tranzport = tranzport.SharedLibrary('ardour_tranzport', tranzport_files)
|
||||||
|
|
||||||
|
Default(libardour_tranzport)
|
||||||
|
|
||||||
|
if env['NLS']:
|
||||||
|
i18n (tranzport, tranzport_files, env)
|
||||||
|
|
||||||
|
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
||||||
|
[ 'SConscript', 'i18n.h', 'gettext.h' ] +
|
||||||
|
tranzport_files +
|
||||||
|
glob.glob('po/*.po') + glob.glob('*.h')))
|
||||||
34
libs/surfaces/tranzport/interface.cc
Normal file
34
libs/surfaces/tranzport/interface.cc
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include <ardour/control_protocol.h>
|
||||||
|
|
||||||
|
#include "tranzport_control_protocol.h"
|
||||||
|
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
ControlProtocol*
|
||||||
|
new_tranzport_protocol (ControlProtocolDescriptor* descriptor, Session* s)
|
||||||
|
{
|
||||||
|
return new TranzportControlProtocol (*s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
delete_tranzport_protocol (ControlProtocolDescriptor* descriptor, ControlProtocol* cp)
|
||||||
|
{
|
||||||
|
delete cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ControlProtocolDescriptor tranzport_descriptor = {
|
||||||
|
name : "Tranzport",
|
||||||
|
ptr : 0,
|
||||||
|
module : 0,
|
||||||
|
initialize : new_tranzport_protocol,
|
||||||
|
destroy : delete_tranzport_protocol
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
ControlProtocolDescriptor*
|
||||||
|
protocol_descriptor () {
|
||||||
|
return &tranzport_descriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <pbd/pthread_utils.h>
|
#include <pbd/pthread_utils.h>
|
||||||
|
|
||||||
#include <ardour/tranzport_control_protocol.h>
|
|
||||||
#include <ardour/route.h>
|
#include <ardour/route.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
|
|
||||||
|
#include "tranzport_control_protocol.h"
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
@ -22,11 +24,14 @@ TranzportControlProtocol::TranzportControlProtocol (Session& s)
|
||||||
current_route = 0;
|
current_route = 0;
|
||||||
current_track_id = 0;
|
current_track_id = 0;
|
||||||
last_where = max_frames;
|
last_where = max_frames;
|
||||||
|
memset (next_screen, ' ', sizeof (next_screen));
|
||||||
|
memset (current_screen, ' ', sizeof (current_screen));
|
||||||
}
|
}
|
||||||
|
|
||||||
TranzportControlProtocol::~TranzportControlProtocol ()
|
TranzportControlProtocol::~TranzportControlProtocol ()
|
||||||
{
|
{
|
||||||
if (udev) {
|
if (udev) {
|
||||||
|
lcd_clear ();
|
||||||
pthread_cancel_one (thread);
|
pthread_cancel_one (thread);
|
||||||
close ();
|
close ();
|
||||||
}
|
}
|
||||||
|
|
@ -39,7 +44,13 @@ TranzportControlProtocol::init ()
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_create_and_store (X_("Tranzport"), &thread, 0, _thread_work, this);
|
/* outbound thread */
|
||||||
|
|
||||||
|
init_thread ();
|
||||||
|
|
||||||
|
/* inbound thread */
|
||||||
|
|
||||||
|
pthread_create_and_store (X_("tranzport monitor"), &thread, 0, _thread_work, this);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -57,17 +68,25 @@ TranzportControlProtocol::send_route_feedback (list<Route*>& routes)
|
||||||
|
|
||||||
void
|
void
|
||||||
TranzportControlProtocol::send_global_feedback ()
|
TranzportControlProtocol::send_global_feedback ()
|
||||||
|
{
|
||||||
|
show_transport_time ();
|
||||||
|
|
||||||
|
flush_lcd ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TranzportControlProtocol::show_transport_time ()
|
||||||
{
|
{
|
||||||
jack_nframes_t where = session.transport_frame();
|
jack_nframes_t where = session.transport_frame();
|
||||||
|
|
||||||
if (where != last_where) {
|
if (where != last_where) {
|
||||||
|
|
||||||
char clock_label[16];
|
uint8_t label[12];
|
||||||
SMPTE_Time smpte;
|
SMPTE_Time smpte;
|
||||||
char* ptr = clock_label;
|
char* ptr = (char *) label;
|
||||||
|
|
||||||
session.smpte_time (where, smpte);
|
session.smpte_time (where, smpte);
|
||||||
memset (clock_label, ' ', sizeof (clock_label));
|
memset (label, ' ', sizeof (label));
|
||||||
|
|
||||||
if (smpte.negative) {
|
if (smpte.negative) {
|
||||||
sprintf (ptr, "-%02ld:", smpte.hours);
|
sprintf (ptr, "-%02ld:", smpte.hours);
|
||||||
|
|
@ -85,14 +104,57 @@ TranzportControlProtocol::send_global_feedback ()
|
||||||
sprintf (ptr, "%02ld", smpte.frames);
|
sprintf (ptr, "%02ld", smpte.frames);
|
||||||
ptr += 2;
|
ptr += 2;
|
||||||
|
|
||||||
lcd_write (7, &clock_label[0]);
|
write_clock (label);
|
||||||
lcd_write (8, &clock_label[4]);
|
|
||||||
lcd_write (9, &clock_label[8]);
|
|
||||||
|
|
||||||
last_where = where;
|
last_where = where;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TranzportControlProtocol::write_clock (const uint8_t* label)
|
||||||
|
{
|
||||||
|
memcpy (&next_screen[1][8], &label[0]);
|
||||||
|
memcpy (&next_screen[1][12], &label[4]);
|
||||||
|
memcpy (&next_screen[1][16], &label[8]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TranzportControlProtocol::flush_lcd ()
|
||||||
|
{
|
||||||
|
if (memcmp (&next_screen[0][0], ¤t_screen[0][0], 4)) {
|
||||||
|
lcd_write (0, &next_screen[0][0]);
|
||||||
|
}
|
||||||
|
if (memcmp (&next_screen[0][4], ¤t_screen[0][4], 4)) {
|
||||||
|
lcd_write (1, &next_screen[0][0]);
|
||||||
|
}
|
||||||
|
if (memcmp (&next_screen[0][8], ¤t_screen[0][8], 4)) {
|
||||||
|
lcd_write (2, &next_screen[0][0]);
|
||||||
|
}
|
||||||
|
if (memcmp (&next_screen[0][12], ¤t_screen[0][12], 4)) {
|
||||||
|
lcd_write (3, &next_screen[0][0]);
|
||||||
|
}
|
||||||
|
if (memcmp (&next_screen[0][16], ¤t_screen[0][16], 4)) {
|
||||||
|
lcd_write (4, &next_screen[0][0]);
|
||||||
|
}
|
||||||
|
if (memcmp (&next_screen[1][0], ¤t_screen[1][0], 4)) {
|
||||||
|
lcd_write (5, &next_screen[0][0]);
|
||||||
|
}
|
||||||
|
if (memcmp (&next_screen[1][4], ¤t_screen[1][4], 4)) {
|
||||||
|
lcd_write (6, &next_screen[0][0]);
|
||||||
|
}
|
||||||
|
if (memcmp (&next_screen[1][8], ¤t_screen[1][8], 4)) {
|
||||||
|
lcd_write (7, &next_screen[0][0]);
|
||||||
|
}
|
||||||
|
if (memcmp (&next_screen[1][12], ¤t_screen[1][12], 4)) {
|
||||||
|
lcd_write (8, &next_screen[0][0]);
|
||||||
|
}
|
||||||
|
if (memcmp (&next_screen[1][16], ¤t_screen[1][16], 4)) {
|
||||||
|
lcd_write (9, &next_screen[0][0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (current_screen, next_screen, sizeof (current_screen));
|
||||||
|
}
|
||||||
|
|
||||||
void*
|
void*
|
||||||
TranzportControlProtocol::_thread_work (void* arg)
|
TranzportControlProtocol::_thread_work (void* arg)
|
||||||
{
|
{
|
||||||
|
|
@ -102,7 +164,7 @@ TranzportControlProtocol::_thread_work (void* arg)
|
||||||
void*
|
void*
|
||||||
TranzportControlProtocol::thread_work ()
|
TranzportControlProtocol::thread_work ()
|
||||||
{
|
{
|
||||||
cerr << "tranzport thread here, sending message to LCD\n";
|
PBD::ThreadCreated (pthread_self(), X_("tranzport monitor"));
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (read()) {
|
if (read()) {
|
||||||
|
|
@ -138,7 +200,6 @@ TranzportControlProtocol::thread_work ()
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (read ()) {
|
if (read ()) {
|
||||||
cerr << "Tranzport command received\n";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -156,19 +217,13 @@ TranzportControlProtocol::open ()
|
||||||
usb_find_busses();
|
usb_find_busses();
|
||||||
usb_find_devices();
|
usb_find_devices();
|
||||||
|
|
||||||
cerr << "checking busses\n";
|
|
||||||
|
|
||||||
for (bus = usb_busses; bus; bus = bus->next) {
|
for (bus = usb_busses; bus; bus = bus->next) {
|
||||||
|
|
||||||
cerr << "checking devices\n";
|
|
||||||
|
|
||||||
for(dev = bus->devices; dev; dev = dev->next) {
|
for(dev = bus->devices; dev; dev = dev->next) {
|
||||||
cerr << "Checking " << dev->descriptor.idVendor << '/' << dev->descriptor.idProduct << endl;
|
|
||||||
if (dev->descriptor.idVendor != VENDORID)
|
if (dev->descriptor.idVendor != VENDORID)
|
||||||
continue;
|
continue;
|
||||||
if (dev->descriptor.idProduct != PRODUCTID)
|
if (dev->descriptor.idProduct != PRODUCTID)
|
||||||
continue;
|
continue;
|
||||||
cerr << "Open this one" << endl;
|
|
||||||
return open_core (dev);
|
return open_core (dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -218,14 +273,20 @@ TranzportControlProtocol::close ()
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
TranzportControlProtocol::write (uint8_t* cmd)
|
TranzportControlProtocol::write (uint8_t* cmd, uint32_t timeout_override)
|
||||||
{
|
{
|
||||||
int val;
|
int val;
|
||||||
val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout);
|
struct timeval tv1, tv2, tv_diff;
|
||||||
|
|
||||||
|
gettimeofday (&tv1, 0);
|
||||||
|
val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout);
|
||||||
|
gettimeofday (&tv2, 0);
|
||||||
if (val < 0)
|
if (val < 0)
|
||||||
return val;
|
return val;
|
||||||
if (val != 8)
|
if (val != 8)
|
||||||
return -1;
|
return -1;
|
||||||
|
timersub (&tv2, &tv1, &tv_diff);
|
||||||
|
cerr << "time to write command = " << tv_diff.tv_sec << '.' << tv_diff.tv_usec << endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -263,7 +324,15 @@ TranzportControlProtocol::lcd_write (uint8_t cell, const char* text)
|
||||||
cmd[6] = text[3];
|
cmd[6] = text[3];
|
||||||
cmd[7] = 0x00;
|
cmd[7] = 0x00;
|
||||||
|
|
||||||
return write (cmd);
|
int index = cell%4;
|
||||||
|
cell /= 4;
|
||||||
|
|
||||||
|
current_screen[cell][index] = text[0];
|
||||||
|
current_screen[cell][index+1] = text[1];
|
||||||
|
current_screen[cell][index+2] = text[2];
|
||||||
|
current_screen[cell][index+3] = text[3];
|
||||||
|
|
||||||
|
return write (cmd, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -280,7 +349,7 @@ TranzportControlProtocol::light_on (LightID light)
|
||||||
cmd[6] = 0x00;
|
cmd[6] = 0x00;
|
||||||
cmd[7] = 0x00;
|
cmd[7] = 0x00;
|
||||||
|
|
||||||
return write (cmd);
|
return write (cmd, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -297,23 +366,25 @@ TranzportControlProtocol::light_off (LightID light)
|
||||||
cmd[6] = 0x00;
|
cmd[6] = 0x00;
|
||||||
cmd[7] = 0x00;
|
cmd[7] = 0x00;
|
||||||
|
|
||||||
return write (cmd);
|
return write (cmd, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
TranzportControlProtocol::read ()
|
TranzportControlProtocol::read (uint32_t timeout_override)
|
||||||
{
|
{
|
||||||
uint8_t buf[8];
|
uint8_t buf[8];
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
memset(buf, 0, 8);
|
memset(buf, 0, 8);
|
||||||
val = usb_interrupt_read(udev, READ_ENDPOINT, (char*) buf, 8, timeout);
|
again:
|
||||||
|
val = usb_interrupt_read(udev, READ_ENDPOINT, (char*) buf, 8, timeout_override ? timeout_override : timeout);
|
||||||
if (val < 0) {
|
if (val < 0) {
|
||||||
cerr << "Tranzport read error, val = " << val << endl;
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
if (val != 8) {
|
if (val != 8) {
|
||||||
cerr << "Tranzport short read, val = " << val << endl;
|
if (val == 0) {
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,6 +69,7 @@ class TranzportControlProtocol : public ControlProtocol {
|
||||||
usb_dev_handle* udev;
|
usb_dev_handle* udev;
|
||||||
Route* current_route;
|
Route* current_route;
|
||||||
uint32_t current_track_id;
|
uint32_t current_track_id;
|
||||||
|
uint8_t lcd_screen[2][20];
|
||||||
|
|
||||||
bool last_negative;
|
bool last_negative;
|
||||||
uint32_t last_hrs;
|
uint32_t last_hrs;
|
||||||
|
|
@ -78,8 +79,8 @@ class TranzportControlProtocol : public ControlProtocol {
|
||||||
jack_nframes_t last_where;
|
jack_nframes_t last_where;
|
||||||
|
|
||||||
int open ();
|
int open ();
|
||||||
int read ();
|
int read (uint32_t timeout_override = 0);
|
||||||
int write (uint8_t* cmd);
|
int write (uint8_t* cmd, uint32_t timeout_override = 0);
|
||||||
int close ();
|
int close ();
|
||||||
|
|
||||||
int open_core (struct usb_device*);
|
int open_core (struct usb_device*);
|
||||||
|
|
@ -90,7 +91,11 @@ class TranzportControlProtocol : public ControlProtocol {
|
||||||
int light_on (LightID);
|
int light_on (LightID);
|
||||||
int light_off (LightID);
|
int light_off (LightID);
|
||||||
|
|
||||||
|
void flush_lcd ();
|
||||||
|
void write_clock (const uint8_t* label);
|
||||||
|
|
||||||
void show_current_track ();
|
void show_current_track ();
|
||||||
|
void show_transport_time ();
|
||||||
|
|
||||||
static void* _thread_work (void* arg);
|
static void* _thread_work (void* arg);
|
||||||
void* thread_work ();
|
void* thread_work ();
|
||||||
Loading…
Add table
Add a link
Reference in a new issue