6 #include <pbd/pthread_utils.h>
8 #include <ardour/route.h>
9 #include <ardour/audio_track.h>
10 #include <ardour/session.h>
11 #include <ardour/location.h>
12 #include <ardour/dB.h>
14 #include "tranzport_control_protocol.h"
16 using namespace ARDOUR;
22 TranzportControlProtocol::TranzportControlProtocol (Session& s)
23 : ControlProtocol (s, _("Tranzport"))
28 _device_status = STATUS_OFFLINE;
32 last_where = max_frames;
33 wheel_mode = WheelTimeline;
34 wheel_shift_mode = WheelShiftGain;
35 timerclear (&last_wheel_motion);
37 display_mode = DisplayNormal;
38 requested_display_mode = display_mode;
40 memset (current_screen, 0, sizeof (current_screen));
42 for (uint32_t i = 0; i < sizeof(lights)/sizeof(lights[0]); ++i) {
46 session.RecordStateChanged.connect (mem_fun (*this, &TranzportControlProtocol::record_status_changed));
49 TranzportControlProtocol::~TranzportControlProtocol ()
53 pthread_cancel_one (thread);
59 TranzportControlProtocol::init ()
67 print (0, 0, "Welcome to");
68 print (1, 0, "Ardour");
72 show_transport_time ();
80 pthread_create_and_store (X_("tranzport monitor"), &thread, 0, _thread_work, this);
86 TranzportControlProtocol::active() const
92 TranzportControlProtocol::send_route_feedback (list<Route*>& routes)
97 TranzportControlProtocol::send_global_feedback ()
99 if (requested_display_mode != display_mode) {
100 switch (requested_display_mode) {
102 enter_normal_display_mode ();
104 case DisplayBigMeter:
105 enter_big_meter_mode ();
110 switch (display_mode) {
111 case DisplayBigMeter:
116 show_transport_time ();
117 if (session.soloing()) {
118 light_on (LightAnysolo);
120 light_off (LightAnysolo);
127 TranzportControlProtocol::next_display_mode ()
129 cerr << "Next display mode\n";
131 switch (display_mode) {
133 requested_display_mode = DisplayBigMeter;
136 case DisplayBigMeter:
137 requested_display_mode = DisplayNormal;
143 TranzportControlProtocol::enter_big_meter_mode ()
147 display_mode = DisplayBigMeter;
151 TranzportControlProtocol::enter_normal_display_mode ()
155 show_current_track ();
157 show_transport_time ();
158 display_mode = DisplayNormal;
165 float def = 0.0f; /* Meter deflection %age */
169 } else if (db < -60.0f) {
170 def = (db + 70.0f) * 0.25f;
171 } else if (db < -50.0f) {
172 def = (db + 60.0f) * 0.5f + 2.5f;
173 } else if (db < -40.0f) {
174 def = (db + 50.0f) * 0.75f + 7.5f;
175 } else if (db < -30.0f) {
176 def = (db + 40.0f) * 1.5f + 15.0f;
177 } else if (db < -20.0f) {
178 def = (db + 30.0f) * 2.0f + 30.0f;
179 } else if (db < 6.0f) {
180 def = (db + 20.0f) * 2.5f + 50.0f;
185 /* 115 is the deflection %age that would be
186 when db=6.0. this is an arbitrary
187 endpoint for our scaling.
194 TranzportControlProtocol::show_meter ()
196 if (current_route == 0) {
200 float level = current_route->peak_input_power (0);
201 float fraction = log_meter (level);
202 int fill = (int) floor (fraction * 20);
206 for (i = 0; i < fill; ++i) {
207 buf[i] = 0x70; /* tranzport special code for 4 quadrant LCD block */
209 for (; i < 20; ++i) {
220 TranzportControlProtocol::show_transport_time ()
222 jack_nframes_t where = session.transport_frame();
224 if (where != last_where) {
229 session.smpte_time (where, smpte);
231 if (smpte.negative) {
232 sprintf (buf, "-%02ld:", smpte.hours);
234 sprintf (buf, " %02ld:", smpte.hours);
238 sprintf (buf, "%02ld:", smpte.minutes);
241 sprintf (buf, "%02ld:", smpte.seconds);
244 sprintf (buf, "%02ld", smpte.frames);
252 TranzportControlProtocol::_thread_work (void* arg)
254 return static_cast<TranzportControlProtocol*>(arg)->thread_work ();
258 TranzportControlProtocol::thread_work ()
260 PBD::ThreadCreated (pthread_self(), X_("tranzport monitor"));
272 TranzportControlProtocol::open ()
275 struct usb_device *dev;
281 for (bus = usb_busses; bus; bus = bus->next) {
283 for(dev = bus->devices; dev; dev = dev->next) {
284 if (dev->descriptor.idVendor != VENDORID)
286 if (dev->descriptor.idProduct != PRODUCTID)
288 return open_core (dev);
292 error << _("Tranzport: no device detected") << endmsg;
297 TranzportControlProtocol::open_core (struct usb_device* dev)
299 if (!(udev = usb_open (dev))) {
300 error << _("Tranzport: cannot open USB transport") << endmsg;
304 if (usb_claim_interface (udev, 0) < 0) {
305 error << _("Tranzport: cannot claim USB interface") << endmsg;
311 if (usb_set_configuration (udev, 1) < 0) {
312 error << _("Tranzport: cannot configure USB interface") << endmsg;
322 TranzportControlProtocol::close ()
330 if (usb_release_interface (udev, 0) < 0) {
331 error << _("Tranzport: cannot release interface") << endmsg;
335 if (usb_close (udev)) {
336 error << _("Tranzport: cannot close device") << endmsg;
344 TranzportControlProtocol::write (uint8_t* cmd, uint32_t timeout_override)
349 LockMonitor lm (write_lock, __LINE__, __FILE__);
350 val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout);
362 TranzportControlProtocol::lcd_clear ()
364 /* special case this for speed and atomicity */
377 LockMonitor lp (print_lock, __LINE__, __FILE__);
378 LockMonitor lw (write_lock, __LINE__, __FILE__);
380 for (uint8_t i = 0; i < 10; ++i) {
382 usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, 500);
385 memset (current_screen, ' ', sizeof (current_screen));
390 TranzportControlProtocol::lights_off ()
392 light_off (LightRecord);
393 light_off (LightTrackrec);
394 light_off (LightTrackmute);
395 light_off (LightTracksolo);
396 light_off (LightAnysolo);
397 light_off (LightLoop);
398 light_off (LightPunch);
402 TranzportControlProtocol::light_on (LightID light)
406 if (!lights[light]) {
417 if (write (cmd, 500) == 0) {
418 lights[light] = true;
430 TranzportControlProtocol::light_off (LightID light)
445 if (write (cmd, 500) == 0) {
446 lights[light] = false;
458 TranzportControlProtocol::read (uint32_t timeout_override)
465 val = usb_interrupt_read(udev, READ_ENDPOINT, (char*) buf, 8, timeout_override ? timeout_override : timeout);
476 // printf("read: %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
478 uint32_t this_button_mask;
479 uint32_t button_changes;
481 _device_status = buf[1];
482 this_button_mask = 0;
483 this_button_mask |= buf[2] << 24;
484 this_button_mask |= buf[3] << 16;
485 this_button_mask |= buf[4] << 8;
486 this_button_mask |= buf[5];
489 button_changes = (this_button_mask ^ buttonmask);
490 buttonmask = this_button_mask;
496 if (button_changes & ButtonBattery) {
497 if (buttonmask & ButtonBattery) {
498 button_event_battery_press (buttonmask&ButtonShift);
500 button_event_battery_release (buttonmask&ButtonShift);
503 if (button_changes & ButtonBacklight) {
504 if (buttonmask & ButtonBacklight) {
505 button_event_backlight_press (buttonmask&ButtonShift);
507 button_event_backlight_release (buttonmask&ButtonShift);
510 if (button_changes & ButtonTrackLeft) {
511 if (buttonmask & ButtonTrackLeft) {
512 button_event_trackleft_press (buttonmask&ButtonShift);
514 button_event_trackleft_release (buttonmask&ButtonShift);
517 if (button_changes & ButtonTrackRight) {
518 if (buttonmask & ButtonTrackRight) {
519 button_event_trackright_press (buttonmask&ButtonShift);
521 button_event_trackright_release (buttonmask&ButtonShift);
524 if (button_changes & ButtonTrackRec) {
525 if (buttonmask & ButtonTrackRec) {
526 button_event_trackrec_press (buttonmask&ButtonShift);
528 button_event_trackrec_release (buttonmask&ButtonShift);
531 if (button_changes & ButtonTrackMute) {
532 if (buttonmask & ButtonTrackMute) {
533 button_event_trackmute_press (buttonmask&ButtonShift);
535 button_event_trackmute_release (buttonmask&ButtonShift);
538 if (button_changes & ButtonTrackSolo) {
539 if (buttonmask & ButtonTrackSolo) {
540 button_event_tracksolo_press (buttonmask&ButtonShift);
542 button_event_tracksolo_release (buttonmask&ButtonShift);
545 if (button_changes & ButtonUndo) {
546 if (buttonmask & ButtonUndo) {
547 button_event_undo_press (buttonmask&ButtonShift);
549 button_event_undo_release (buttonmask&ButtonShift);
552 if (button_changes & ButtonIn) {
553 if (buttonmask & ButtonIn) {
554 button_event_in_press (buttonmask&ButtonShift);
556 button_event_in_release (buttonmask&ButtonShift);
559 if (button_changes & ButtonOut) {
560 if (buttonmask & ButtonOut) {
561 button_event_out_press (buttonmask&ButtonShift);
563 button_event_out_release (buttonmask&ButtonShift);
566 if (button_changes & ButtonPunch) {
567 if (buttonmask & ButtonPunch) {
568 button_event_punch_press (buttonmask&ButtonShift);
570 button_event_punch_release (buttonmask&ButtonShift);
573 if (button_changes & ButtonLoop) {
574 if (buttonmask & ButtonLoop) {
575 button_event_loop_press (buttonmask&ButtonShift);
577 button_event_loop_release (buttonmask&ButtonShift);
580 if (button_changes & ButtonPrev) {
581 if (buttonmask & ButtonPrev) {
582 button_event_prev_press (buttonmask&ButtonShift);
584 button_event_prev_release (buttonmask&ButtonShift);
587 if (button_changes & ButtonAdd) {
588 if (buttonmask & ButtonAdd) {
589 button_event_add_press (buttonmask&ButtonShift);
591 button_event_add_release (buttonmask&ButtonShift);
594 if (button_changes & ButtonNext) {
595 if (buttonmask & ButtonNext) {
596 button_event_next_press (buttonmask&ButtonShift);
598 button_event_next_release (buttonmask&ButtonShift);
601 if (button_changes & ButtonRewind) {
602 if (buttonmask & ButtonRewind) {
603 button_event_rewind_press (buttonmask&ButtonShift);
605 button_event_rewind_release (buttonmask&ButtonShift);
608 if (button_changes & ButtonFastForward) {
609 if (buttonmask & ButtonFastForward) {
610 button_event_fastforward_press (buttonmask&ButtonShift);
612 button_event_fastforward_release (buttonmask&ButtonShift);
615 if (button_changes & ButtonStop) {
616 if (buttonmask & ButtonStop) {
617 button_event_stop_press (buttonmask&ButtonShift);
619 button_event_stop_release (buttonmask&ButtonShift);
622 if (button_changes & ButtonPlay) {
623 if (buttonmask & ButtonPlay) {
624 button_event_play_press (buttonmask&ButtonShift);
626 button_event_play_release (buttonmask&ButtonShift);
629 if (button_changes & ButtonRecord) {
630 if (buttonmask & ButtonRecord) {
631 button_event_record_press (buttonmask&ButtonShift);
633 button_event_record_release (buttonmask&ButtonShift);
641 TranzportControlProtocol::show_current_track ()
643 for (vector<sigc::connection>::iterator i = track_connections.begin(); i != track_connections.end(); ++i) {
646 track_connections.clear ();
648 if (current_route == 0) {
649 print (0, 0, "--------");
653 string name = current_route->name();
655 print (0, 0, name.substr (0, 8).c_str());
657 track_solo_changed (0);
658 track_mute_changed (0);
659 track_rec_changed (0);
661 track_connections.push_back (current_route->solo_changed.connect (mem_fun (*this, &TranzportControlProtocol::track_solo_changed)));
662 track_connections.push_back (current_route->mute_changed.connect (mem_fun (*this, &TranzportControlProtocol::track_mute_changed)));
663 track_connections.push_back (current_route->record_enable_changed.connect (mem_fun (*this, &TranzportControlProtocol::track_rec_changed)));
664 track_connections.push_back (current_route->gain_changed.connect (mem_fun (*this, &TranzportControlProtocol::track_gain_changed)));
668 TranzportControlProtocol::record_status_changed ()
670 if (session.get_record_enabled()) {
671 light_on (LightRecord);
673 light_off (LightRecord);
678 TranzportControlProtocol::track_gain_changed (void* ignored)
681 snprintf (buf, sizeof (buf), "%.1fdB", coefficient_to_dB (current_route->gain()));
686 TranzportControlProtocol::track_solo_changed (void* ignored)
688 if (current_route->soloed()) {
689 light_on (LightTracksolo);
691 light_off (LightTracksolo);
696 TranzportControlProtocol::track_mute_changed (void *ignored)
698 if (current_route->muted()) {
699 light_on (LightTrackmute);
701 light_off (LightTrackmute);
706 TranzportControlProtocol::track_rec_changed (void *ignored)
708 if (current_route->record_enabled()) {
709 light_on (LightTrackrec);
711 light_off (LightTrackrec);
717 TranzportControlProtocol::button_event_battery_press (bool shifted)
722 TranzportControlProtocol::button_event_battery_release (bool shifted)
727 TranzportControlProtocol::button_event_backlight_press (bool shifted)
732 TranzportControlProtocol::button_event_backlight_release (bool shifted)
737 TranzportControlProtocol::button_event_trackleft_press (bool shifted)
743 TranzportControlProtocol::button_event_trackleft_release (bool shifted)
748 TranzportControlProtocol::button_event_trackright_press (bool shifted)
754 TranzportControlProtocol::button_event_trackright_release (bool shifted)
759 TranzportControlProtocol::button_event_trackrec_press (bool shifted)
762 if (session.get_record_enabled()) {
763 session.record_disenable_all ();
765 session.record_enable_all ();
769 AudioTrack* at = dynamic_cast<AudioTrack*>(current_route);
770 at->set_record_enable (!at->record_enabled(), this);
776 TranzportControlProtocol::button_event_trackrec_release (bool shifted)
781 TranzportControlProtocol::button_event_trackmute_press (bool shifted)
784 current_route->set_mute (!current_route->muted(), this);
789 TranzportControlProtocol::button_event_trackmute_release (bool shifted)
794 TranzportControlProtocol::button_event_tracksolo_press (bool shifted)
797 session.set_all_solo (!session.soloing());
800 current_route->set_solo (!current_route->soloed(), this);
806 TranzportControlProtocol::button_event_tracksolo_release (bool shifted)
811 TranzportControlProtocol::button_event_undo_press (bool shifted)
821 TranzportControlProtocol::button_event_undo_release (bool shifted)
826 TranzportControlProtocol::button_event_in_press (bool shifted)
829 ControlProtocol::ZoomIn (); /* EMIT SIGNAL */
834 TranzportControlProtocol::button_event_in_release (bool shifted)
839 TranzportControlProtocol::button_event_out_press (bool shifted)
842 ControlProtocol::ZoomOut (); /* EMIT SIGNAL */
847 TranzportControlProtocol::button_event_out_release (bool shifted)
852 TranzportControlProtocol::button_event_punch_press (bool shifted)
857 TranzportControlProtocol::button_event_punch_release (bool shifted)
862 TranzportControlProtocol::button_event_loop_press (bool shifted)
865 next_wheel_shift_mode ();
870 TranzportControlProtocol::button_event_loop_release (bool shifted)
875 TranzportControlProtocol::button_event_prev_press (bool shifted)
878 ControlProtocol::ZoomToSession (); /* EMIT SIGNAL */
885 TranzportControlProtocol::button_event_prev_release (bool shifted)
890 TranzportControlProtocol::button_event_add_press (bool shifted)
892 jack_nframes_t when = session.audible_frame();
893 session.locations()->add (new Location (when, when, _("unnamed"), Location::IsMark));
897 TranzportControlProtocol::button_event_add_release (bool shifted)
902 TranzportControlProtocol::button_event_next_press (bool shifted)
912 TranzportControlProtocol::button_event_next_release (bool shifted)
917 TranzportControlProtocol::button_event_rewind_press (bool shifted)
920 session.goto_start ();
922 session.request_transport_speed (-2.0f);
927 TranzportControlProtocol::button_event_rewind_release (bool shifted)
932 TranzportControlProtocol::button_event_fastforward_press (bool shifted)
937 session.request_transport_speed (2.0f);}
941 TranzportControlProtocol::button_event_fastforward_release (bool shifted)
946 TranzportControlProtocol::button_event_stop_press (bool shifted)
949 next_display_mode ();
951 session.request_transport_speed (0.0);
956 TranzportControlProtocol::button_event_stop_release (bool shifted)
961 TranzportControlProtocol::button_event_play_press (bool shifted)
963 session.request_transport_speed (1.0);
967 TranzportControlProtocol::button_event_play_release (bool shifted)
972 TranzportControlProtocol::button_event_record_press (bool shifted)
975 session.save_state ("");
977 switch (session.record_status()) {
978 case Session::Disabled:
979 if (session.ntracks() == 0) {
980 // string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
981 // MessageDialog msg (*editor, txt);
985 session.maybe_enable_record ();
987 case Session::Recording:
988 case Session::Enabled:
989 session.disable_record (true);
995 TranzportControlProtocol::button_event_record_release (bool shifted)
1000 TranzportControlProtocol::datawheel ()
1002 if ((buttonmask & ButtonTrackRight) || (buttonmask & ButtonTrackLeft)) {
1004 /* track scrolling */
1006 if (_datawheel < WheelDirectionThreshold) {
1012 timerclear (&last_wheel_motion);
1014 } else if ((buttonmask & ButtonPrev) || (buttonmask & ButtonNext)) {
1016 if (_datawheel < WheelDirectionThreshold) {
1022 timerclear (&last_wheel_motion);
1024 } else if (buttonmask & ButtonShift) {
1026 /* parameter control */
1028 if (current_route) {
1029 switch (wheel_shift_mode) {
1030 case WheelShiftGain:
1031 if (_datawheel < WheelDirectionThreshold) {
1038 if (_datawheel < WheelDirectionThreshold) {
1045 case WheelShiftMaster:
1050 timerclear (&last_wheel_motion);
1054 switch (wheel_mode) {
1071 TranzportControlProtocol::scroll ()
1073 if (_datawheel < WheelDirectionThreshold) {
1074 ScrollTimeline (0.2);
1076 ScrollTimeline (-0.2);
1081 TranzportControlProtocol::scrub ()
1085 struct timeval delta;
1088 gettimeofday (&now, 0);
1090 if (_datawheel < WheelDirectionThreshold) {
1096 if (dir != last_wheel_dir) {
1097 /* changed direction, start over */
1100 if (timerisset (&last_wheel_motion)) {
1102 timersub (&now, &last_wheel_motion, &delta);
1104 /* 10 clicks per second => speed == 1.0 */
1106 speed = 100000.0f / (delta.tv_sec * 1000000 + delta.tv_usec);
1110 /* start at half-speed and see where we go from there */
1116 last_wheel_motion = now;
1117 last_wheel_dir = dir;
1119 session.request_transport_speed (speed * dir);
1123 TranzportControlProtocol::shuttle ()
1125 if (_datawheel < WheelDirectionThreshold) {
1126 if (session.transport_speed() < 0) {
1127 session.request_transport_speed (1.0);
1129 session.request_transport_speed (session.transport_speed() + 0.1);
1132 if (session.transport_speed() > 0) {
1133 session.request_transport_speed (-1.0);
1135 session.request_transport_speed (session.transport_speed() - 0.1);
1141 TranzportControlProtocol::step_gain_up ()
1143 if (buttonmask & ButtonStop) {
1144 current_route->inc_gain (0.01, this);
1146 current_route->inc_gain (0.1, this);
1151 TranzportControlProtocol::step_gain_down ()
1153 if (buttonmask & ButtonStop) {
1154 current_route->inc_gain (-0.01, this);
1156 current_route->inc_gain (-0.1, this);
1161 TranzportControlProtocol::step_pan_right ()
1166 TranzportControlProtocol::step_pan_left ()
1171 TranzportControlProtocol::next_wheel_shift_mode ()
1173 switch (wheel_shift_mode) {
1174 case WheelShiftGain:
1175 wheel_shift_mode = WheelShiftPan;
1178 wheel_shift_mode = WheelShiftMaster;
1180 case WheelShiftMaster:
1181 wheel_shift_mode = WheelShiftGain;
1188 TranzportControlProtocol::next_wheel_mode ()
1190 switch (wheel_mode) {
1192 wheel_mode = WheelScrub;
1195 wheel_mode = WheelShuttle;
1198 wheel_mode = WheelTimeline;
1205 TranzportControlProtocol::next_marker ()
1207 Location *location = session.locations()->first_location_after (session.transport_frame());
1210 session.request_locate (location->start(), session.transport_rolling());
1212 session.request_locate (session.current_end_frame());
1217 TranzportControlProtocol::prev_marker ()
1219 Location *location = session.locations()->first_location_before (session.transport_frame());
1222 session.request_locate (location->start(), session.transport_rolling());
1224 session.goto_start ();
1229 TranzportControlProtocol::next_track ()
1231 uint32_t limit = session.nroutes();
1233 if (current_track_id == limit) {
1234 current_track_id = 0;
1239 while (current_track_id < limit) {
1240 if ((current_route = session.route_by_remote_id (current_track_id)) != 0) {
1246 if (current_track_id == limit) {
1247 current_track_id = 0;
1250 show_current_track ();
1254 TranzportControlProtocol::prev_track ()
1256 if (current_track_id == 0) {
1257 current_track_id = session.nroutes() - 1;
1262 while (current_track_id >= 0) {
1263 if ((current_route = session.route_by_remote_id (current_track_id)) != 0) {
1269 if (current_track_id < 0) {
1270 current_track_id = 0;
1273 show_current_track ();
1277 TranzportControlProtocol::show_wheel_mode ()
1281 switch (wheel_mode) {
1293 switch (wheel_shift_mode) {
1294 case WheelShiftGain:
1302 case WheelShiftMaster:
1307 print (1, 0, text.c_str());
1311 TranzportControlProtocol::print (int row, int col, const char *text)
1314 uint32_t left = strlen (text);
1318 if (row < 0 || row > 1) {
1322 if (col < 0 || col > 19) {
1328 if (col >= 0 && col < 4) {
1331 } else if (col >= 4 && col < 8) {
1334 } else if (col >= 8 && col < 12) {
1337 } else if (col >= 12 && col < 16) {
1340 } else if (col >= 16 && col < 20) {
1347 int offset = col % 4;
1351 LockMonitor lm (print_lock, __LINE__, __FILE__);
1353 /* copy current cell contents into tmp */
1355 memcpy (tmp, ¤t_screen[row][base_col], 4);
1357 /* overwrite with new text */
1359 uint32_t tocopy = min ((4U - offset), left);
1361 memcpy (tmp+offset, text, tocopy);
1365 /* compare with current screen */
1367 if (memcmp (tmp, ¤t_screen[row][base_col], 4)) {
1369 /* different, so update */
1371 memcpy (¤t_screen[row][base_col], tmp, 4);
1375 cmd[2] = cell + (row * 5);