*/
#include <stdlib.h>
+#include <pthread.h>
#include "pbd/compose.h"
#include "pbd/convert.h"
#include "pbd/enumwriter.h"
#include "midi++/parser.h"
-#include "timecode/time.h"
-#include "timecode/bbt_time.h"
+
+#include "temporal/time.h"
+#include "temporal/bbt_time.h"
#include "ardour/amp.h"
#include "ardour/async_midi_port.h"
#include "ardour/midi_port.h"
#include "ardour/session.h"
#include "ardour/tempo.h"
+#include "ardour/types_convert.h"
#include "gtkmm2ext/gui_thread.h"
#include "gtkmm2ext/rgb_macros.h"
-#include "canvas/colors.h"
+#include "gtkmm2ext/colors.h"
#include "canvas.h"
#include "gui.h"
using namespace PBD;
using namespace Glib;
using namespace ArdourSurface;
+using namespace Gtkmm2ext;
#include "pbd/abstract_ui.cc" // instantiate template
/* master cannot be removed, so no need to connect to going-away signal */
master = session->master_out ();
- ControlProtocol::StripableSelectionChanged.connect (selection_connection, MISSING_INVALIDATOR, boost::bind (&Push2::stripable_selection_change, this, _1), this);
-
/* allocate graphics layouts, even though we're not using them yet */
_canvas = new Push2Canvas (*this, 960, 160);
Push2::~Push2 ()
{
- selection_connection.disconnect ();
+ DEBUG_TRACE (DEBUG::Push2, "push2 control surface object being destroyed\n");
+
+ /* do this before stopping the event loop, so that we don't get any notifications */
+ port_reg_connection.disconnect ();
+ port_connection.disconnect ();
- stop_event_loop (); /* this will call stop_using_device () in Quit request handler */
+ stop_using_device ();
device_release ();
ports_release ();
scale_layout = 0;
delete splash_layout;
splash_layout = 0;
+ delete track_mix_layout;
+ track_mix_layout = 0;
+
+ stop_event_loop ();
}
+
void
Push2::run_event_loop ()
{
{
DEBUG_TRACE (DEBUG::Push2, "begin using device\n");
- /* set up periodic task used to push a frame buffer to the
+ /* set up periodic task used to push a sample buffer to the
* device (25fps). The device can handle 60fps, but we don't
* need that frame rate.
*/
splash ();
/* catch current selection, if any so that we can wire up the pads if appropriate */
- {
- StripableNotificationListPtr sp (new StripableNotificationList (ControlProtocol::last_selected()));
- stripable_selection_change (sp);
- }
+ stripable_selection_changed ();
request_pressure_mode ();
asp = dynamic_cast<AsyncMIDIPort*> (_output_port);
asp->drain (10000, 500000);
- AudioEngine::instance()->unregister_port (_async_in);
- AudioEngine::instance()->unregister_port (_async_out);
+ {
+ Glib::Threads::Mutex::Lock em (AudioEngine::instance()->process_lock());
+ AudioEngine::instance()->unregister_port (_async_in);
+ AudioEngine::instance()->unregister_port (_async_out);
+ }
_async_in.reset ((ARDOUR::Port*) 0);
_async_out.reset ((ARDOUR::Port*) 0);
Lower1, Lower2, Lower3, Lower4, Lower5, Lower6, Lower7, Lower8, };
for (size_t n = 0; n < sizeof (strip_buttons) / sizeof (strip_buttons[0]); ++n) {
- Button* b = id_button_map[strip_buttons[n]];
+ boost::shared_ptr<Button> b = id_button_map[strip_buttons[n]];
b->set_color (LED::Black);
b->set_state (LED::OneShot24th);
};
for (size_t n = 0; n < sizeof (buttons) / sizeof (buttons[0]); ++n) {
- Button* b = id_button_map[buttons[n]];
+ boost::shared_ptr<Button> b = id_button_map[buttons[n]];
if (startup) {
b->set_color (LED::White);
Accent, Note, Session, };
for (size_t n = 0; n < sizeof (off_buttons) / sizeof (off_buttons[0]); ++n) {
- Button* b = id_button_map[off_buttons[n]];
+ boost::shared_ptr<Button> b = id_button_map[off_buttons[n]];
b->set_color (LED::Black);
b->set_state (LED::OneShot24th);
if (!startup) {
for (NNPadMap::iterator pi = nn_pad_map.begin(); pi != nn_pad_map.end(); ++pi) {
- Pad* pad = pi->second;
+ boost::shared_ptr<Pad> pad = pi->second;
pad->set_color (LED::Black);
pad->set_state (LED::OneShot24th);
DEBUG_TRACE (DEBUG::Push2, string_compose ("data available on %1\n", port->name()));
if (in_use) {
- framepos_t now = AudioEngine::instance()->sample_time();
+ samplepos_t now = AudioEngine::instance()->sample_time();
port->parse (now);
}
}
if (ev->value) {
/* any press cancels any pending long press timeouts */
for (set<ButtonID>::iterator x = buttons_down.begin(); x != buttons_down.end(); ++x) {
- Button* bb = id_button_map[*x];
+ boost::shared_ptr<Button> bb = id_button_map[*x];
bb->timeout_connection.disconnect ();
}
}
if (b != cc_button_map.end()) {
- Button* button = b->second;
+ boost::shared_ptr<Button> button = b->second;
if (ev->value) {
buttons_down.insert (button->id);
- start_press_timeout (*button, button->id);
+ start_press_timeout (button, button->id);
} else {
buttons_down.erase (button->id);
button->timeout_connection.disconnect ();
return;
}
- const Pad * const pad_pressed = pm->second;
+ boost::shared_ptr<const Pad> pad_pressed = pm->second;
pair<FNPadMap::iterator,FNPadMap::iterator> pads_with_note = fn_pad_map.equal_range (pad_pressed->filtered);
}
for (FNPadMap::iterator pi = pads_with_note.first; pi != pads_with_note.second; ++pi) {
- Pad* pad = pi->second;
+ boost::shared_ptr<Pad> pad = pi->second;
pad->set_color (contrast_color);
pad->set_state (LED::OneShot24th);
return;
}
- const Pad * const pad_pressed = pm->second;
+ boost::shared_ptr<const Pad> const pad_pressed = pm->second;
pair<FNPadMap::iterator,FNPadMap::iterator> pads_with_note = fn_pad_map.equal_range (pad_pressed->filtered);
}
for (FNPadMap::iterator pi = pads_with_note.first; pi != pads_with_note.second; ++pi) {
- Pad* pad = pi->second;
+ boost::shared_ptr<Pad> pad = pi->second;
if (pad->do_when_pressed == Pad::FlashOn) {
pad->set_color (LED::Black);
void
Push2::thread_init ()
{
- struct sched_param rtparam;
-
pthread_set_name (event_loop_name().c_str());
PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128);
- memset (&rtparam, 0, sizeof (rtparam));
- rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
-
- if (pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam) != 0) {
- // do we care? not particularly.
- }
+ set_thread_priority ();
}
void
void
Push2::notify_transport_state_changed ()
{
- Button* b = id_button_map[Play];
+ boost::shared_ptr<Button> b = id_button_map[Play];
if (session->transport_rolling()) {
b->set_state (LED::OneShot24th);
} else {
/* disable any blink on FixedLength from pending edit range op */
- Button* fl = id_button_map[FixedLength];
+ boost::shared_ptr<Button> fl = id_button_map[FixedLength];
fl->set_color (LED::Black);
fl->set_state (LED::NoTransition);
child->add_child_nocopy (_async_out->get_state());
node.add_child_nocopy (*child);
- node.add_property (X_("root"), to_string (_scale_root, std::dec));
- node.add_property (X_("root_octave"), to_string (_root_octave, std::dec));
- node.add_property (X_("in_key"), _in_key ? X_("yes") : X_("no"));
- node.add_property (X_("mode"), enum_2_string (_mode));
+ node.set_property (X_("root"), _scale_root);
+ node.set_property (X_("root-octave"), _root_octave);
+ node.set_property (X_("in-key"), _in_key);
+ node.set_property (X_("mode"), _mode);
return node;
}
}
}
- XMLProperty const* prop;
-
- if ((prop = node.property (X_("root"))) != 0) {
- _scale_root = atoi (prop->value());
- }
-
- if ((prop = node.property (X_("root_octave"))) != 0) {
- _root_octave = atoi (prop->value());
- }
-
- if ((prop = node.property (X_("in_key"))) != 0) {
- _in_key = string_is_affirmative (prop->value());
- }
-
- if ((prop = node.property (X_("mode"))) != 0) {
- _mode = (MusicalMode::Type) string_2_enum (prop->value(), _mode);
- }
+ node.get_property (X_("root"), _scale_root);
+ node.get_property (X_("root-octave"), _root_octave);
+ node.get_property (X_("in-key"), _in_key);
+ node.get_property (X_("mode"), _mode);
return retval;
}
boost::shared_ptr<AutomationControl> ac = master->gain_control();
if (ac) {
if (touching) {
- ac->start_touch (session->audible_frame());
+ ac->start_touch (session->audible_sample());
} else {
- ac->stop_touch (true, session->audible_frame());
+ ac->stop_touch (session->audible_sample());
}
}
}
{
cerr << "start shift\n";
_modifier_state = ModifierState (_modifier_state | ModShift);
- Button* b = id_button_map[Shift];
+ boost::shared_ptr<Button> b = id_button_map[Shift];
b->set_color (LED::White);
b->set_state (LED::Blinking16th);
write (b->state_msg());
if (_modifier_state & ModShift) {
cerr << "end shift\n";
_modifier_state = ModifierState (_modifier_state & ~(ModShift));
- Button* b = id_button_map[Shift];
+ boost::shared_ptr<Button> b = id_button_map[Shift];
b->timeout_connection.disconnect ();
b->set_color (LED::White);
b->set_state (LED::OneShot24th);
NNPadMap::const_iterator nni = nn_pad_map.find (n);
if (nni != nn_pad_map.end()) {
- Pad const * pad = nni->second;
+ boost::shared_ptr<const Pad> pad = nni->second;
/* shift for output to the shadow port */
if (pad->filtered >= 0) {
(*ev).set_note (pad->filtered + (octave_shift*12));
void
Push2::port_registration_handler ()
{
- if (!_async_in && !_async_out) {
+ if (!_async_in || !_async_out) {
/* ports not registered yet */
return;
}
}
selection_color = get_color_index (current_midi_track->presentation_info().color());
- contrast_color = get_color_index (ArdourCanvas::HSV (current_midi_track->presentation_info().color()).opposite().color());
+ contrast_color = get_color_index (Gtkmm2ext::HSV (current_midi_track->presentation_info().color()).opposite().color());
reset_pad_colors ();
}
for (int col = 0; col < 8; ++col) {
int index = 36 + (row*8) + col;
- Pad* pad = nn_pad_map[index];
+ boost::shared_ptr<Pad> pad = nn_pad_map[index];
int notenum;
if (notei != mode_vector.end()) {
for (note = 36; note < 100; ++note) {
- Pad* pad = nn_pad_map[note];
+ boost::shared_ptr<Pad> pad = nn_pad_map[note];
/* Chromatic: all pads play, half-tone steps. Light
* those in the scale, and highlight root notes
for (int col = 0; col < 4; ++col) {
int index = 36 + (row*8) + col;
- Pad* pad = nn_pad_map[index];
+ boost::shared_ptr<Pad> pad = nn_pad_map[index];
pad->filtered = drum_note;
drum_note++;
for (int col = 4; col < 8; ++col) {
int index = 36 + (row*8) + col;
- Pad* pad = nn_pad_map[index];
+ boost::shared_ptr<Pad> pad = nn_pad_map[index];
pad->filtered = drum_note;
drum_note++;
}
void
-Push2::stripable_selection_change (StripableNotificationListPtr selected)
+Push2::stripable_selection_changed ()
{
boost::shared_ptr<MidiPort> pad_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in)->shadow_port();
boost::shared_ptr<MidiTrack> current_midi_track = current_pad_target.lock();
boost::shared_ptr<MidiTrack> new_pad_target;
+ StripableNotificationList const & selected (last_selected());
/* See if there's a MIDI track selected */
- for (StripableNotificationList::iterator si = selected->begin(); si != selected->end(); ++si) {
+ for (StripableNotificationList::const_iterator si = selected.begin(); si != selected.end(); ++si) {
new_pad_target = boost::dynamic_pointer_cast<MidiTrack> ((*si).lock());
new_pad_target->input()->connect (new_pad_target->input()->nth (0), pad_port->name(), this);
current_pad_target = new_pad_target;
selection_color = get_color_index (new_pad_target->presentation_info().color());
- contrast_color = get_color_index (ArdourCanvas::HSV (new_pad_target->presentation_info().color()).opposite().color());
+ contrast_color = get_color_index (Gtkmm2ext::HSV (new_pad_target->presentation_info().color()).opposite().color());
} else {
current_pad_target.reset ();
selection_color = LED::Green;
}
reset_pad_colors ();
+
+ TrackMixLayout* tml = dynamic_cast<TrackMixLayout*> (track_mix_layout);
+ assert (tml);
+ tml->set_stripable (first_selected_stripable());
}
-Push2::Button*
+boost::shared_ptr<Push2::Button>
Push2::button_by_id (ButtonID bid)
{
return id_button_map[bid];
}
uint8_t
-Push2::get_color_index (ArdourCanvas::Color rgba)
+Push2::get_color_index (Color rgba)
{
ColorMap::iterator i = color_map.find (rgba);
double dr, dg, db, da;
int r, g, b;
- ArdourCanvas::color_to_rgba (rgba, dr, dg, db, da);
+ color_to_rgba (rgba, dr, dg, db, da);
int w = 126; /* not sure where/when we should get this value */
void
Push2::fill_color_table ()
{
- colors.insert (make_pair (DarkBackground, ArdourCanvas::rgba_to_color (0, 0, 0, 1)));
- colors.insert (make_pair (LightBackground, ArdourCanvas::rgba_to_color (0.98, 0.98, 0.98, 1)));
+ colors.insert (make_pair (DarkBackground, Gtkmm2ext::rgba_to_color (0, 0, 0, 1)));
+ colors.insert (make_pair (LightBackground, Gtkmm2ext::rgba_to_color (0.98, 0.98, 0.98, 1)));
- colors.insert (make_pair (ParameterName, ArdourCanvas::rgba_to_color (0.98, 0.98, 0.98, 1)));
+ colors.insert (make_pair (ParameterName, Gtkmm2ext::rgba_to_color (0.98, 0.98, 0.98, 1)));
- colors.insert (make_pair (KnobArcBackground, ArdourCanvas::rgba_to_color (0.3, 0.3, 0.3, 1.0)));
- colors.insert (make_pair (KnobArcStart, ArdourCanvas::rgba_to_color (1.0, 0.0, 0.0, 1.0)));
- colors.insert (make_pair (KnobArcEnd, ArdourCanvas::rgba_to_color (0.0, 1.0, 0.0, 1.0)));
+ colors.insert (make_pair (KnobArcBackground, Gtkmm2ext::rgba_to_color (0.3, 0.3, 0.3, 1.0)));
+ colors.insert (make_pair (KnobArcStart, Gtkmm2ext::rgba_to_color (1.0, 0.0, 0.0, 1.0)));
+ colors.insert (make_pair (KnobArcEnd, Gtkmm2ext::rgba_to_color (0.0, 1.0, 0.0, 1.0)));
- colors.insert (make_pair (KnobLineShadow, ArdourCanvas::rgba_to_color (0, 0, 0, 0.3)));
- colors.insert (make_pair (KnobLine, ArdourCanvas::rgba_to_color (1, 1, 1, 1)));
+ colors.insert (make_pair (KnobLineShadow, Gtkmm2ext::rgba_to_color (0, 0, 0, 0.3)));
+ colors.insert (make_pair (KnobLine, Gtkmm2ext::rgba_to_color (1, 1, 1, 1)));
- colors.insert (make_pair (KnobForeground, ArdourCanvas::rgba_to_color (0.2, 0.2, 0.2, 1)));
- colors.insert (make_pair (KnobBackground, ArdourCanvas::rgba_to_color (0.2, 0.2, 0.2, 1)));
- colors.insert (make_pair (KnobShadow, ArdourCanvas::rgba_to_color (0, 0, 0, 0.1)));
- colors.insert (make_pair (KnobBorder, ArdourCanvas::rgba_to_color (0, 0, 0, 1)));
+ colors.insert (make_pair (KnobForeground, Gtkmm2ext::rgba_to_color (0.2, 0.2, 0.2, 1)));
+ colors.insert (make_pair (KnobBackground, Gtkmm2ext::rgba_to_color (0.2, 0.2, 0.2, 1)));
+ colors.insert (make_pair (KnobShadow, Gtkmm2ext::rgba_to_color (0, 0, 0, 0.1)));
+ colors.insert (make_pair (KnobBorder, Gtkmm2ext::rgba_to_color (0, 0, 0, 1)));
}
-ArdourCanvas::Color
+Gtkmm2ext::Color
Push2::get_color (ColorName name)
{
Colors::iterator c = colors.find (name);