2 Copyright (C) 2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #define __STDC_FORMAT_MACROS
31 #include <pbd/pthread_utils.h>
33 #include <ardour/route.h>
34 #include <ardour/audio_track.h>
35 #include <ardour/session.h>
36 #include <ardour/location.h>
37 #include <ardour/dB.h>
39 #include "tranzport_control_protocol.h"
41 using namespace ARDOUR;
48 #include <pbd/abstract_ui.cc>
50 BaseUI::RequestType LEDChange = BaseUI::new_request_type ();
51 BaseUI::RequestType Print = BaseUI::new_request_type ();
52 BaseUI::RequestType SetCurrentTrack = BaseUI::new_request_type ();
55 gain_to_slider_position (ARDOUR::gain_t g)
58 return pow((6.0*log(g)/log(2.0)+192.0)/198.0, 8.0);
62 static inline ARDOUR::gain_t
63 slider_position_to_gain (double pos)
65 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
66 if (pos == 0.0) return 0;
67 return pow (2.0,(sqrt(sqrt(sqrt(pos)))*198.0-192.0)/6.0);
71 TranzportControlProtocol::TranzportControlProtocol (Session& s)
72 : ControlProtocol (s, X_("Tranzport"))
74 /* tranzport controls one track at a time */
76 set_route_table_size (1);
81 _device_status = STATUS_OFFLINE;
84 last_where = max_frames;
85 wheel_mode = WheelTimeline;
86 wheel_shift_mode = WheelShiftGain;
87 timerclear (&last_wheel_motion);
89 last_track_gain = FLT_MAX;
90 display_mode = DisplayNormal;
93 memset (current_screen, 0, sizeof (current_screen));
94 memset (pending_screen, 0, sizeof (pending_screen));
96 for (uint32_t i = 0; i < sizeof(lights)/sizeof(lights[0]); ++i) {
100 for (uint32_t i = 0; i < sizeof(pending_lights)/sizeof(pending_lights[0]); ++i) {
101 pending_lights[i] = false;
105 TranzportControlProtocol::~TranzportControlProtocol ()
111 TranzportControlProtocol::probe ()
114 struct usb_device *dev;
120 for (bus = usb_busses; bus; bus = bus->next) {
122 for(dev = bus->devices; dev; dev = dev->next) {
123 if (dev->descriptor.idVendor == VENDORID && dev->descriptor.idProduct == PRODUCTID) {
133 TranzportControlProtocol::set_active (bool yn)
143 if (pthread_create_and_store (X_("tranzport monitor"), &thread, 0, _monitor_work, this) == 0) {
150 cerr << "Begin tranzport shutdown\n";
151 pthread_cancel_one (thread);
152 cerr << "Thread dead\n";
155 // cerr << "dev reset\n";
158 cerr << "End tranzport shutdown\n";
166 TranzportControlProtocol::show_track_gain ()
168 if (route_table[0]) {
169 gain_t g = route_get_gain (0);
170 if (g != last_track_gain) {
172 snprintf (buf, sizeof (buf), "%6.1fdB", coefficient_to_dB (route_get_effective_gain (0)));
182 TranzportControlProtocol::normal_update ()
184 show_current_track ();
185 show_transport_time ();
191 TranzportControlProtocol::next_display_mode ()
193 switch (display_mode) {
195 display_mode = DisplayBigMeter;
198 case DisplayBigMeter:
199 display_mode = DisplayNormal;
205 TranzportControlProtocol::enter_big_meter_mode ()
210 display_mode = DisplayBigMeter;
214 TranzportControlProtocol::enter_normal_display_mode ()
216 last_where += 1; /* force time redisplay */
217 last_track_gain = FLT_MAX; /* force gain redisplay */
221 show_current_track ();
224 show_transport_time ();
225 display_mode = DisplayNormal;
232 float def = 0.0f; /* Meter deflection %age */
236 } else if (db < -60.0f) {
237 def = (db + 70.0f) * 0.25f;
238 } else if (db < -50.0f) {
239 def = (db + 60.0f) * 0.5f + 2.5f;
240 } else if (db < -40.0f) {
241 def = (db + 50.0f) * 0.75f + 7.5f;
242 } else if (db < -30.0f) {
243 def = (db + 40.0f) * 1.5f + 15.0f;
244 } else if (db < -20.0f) {
245 def = (db + 30.0f) * 2.0f + 30.0f;
246 } else if (db < 6.0f) {
247 def = (db + 20.0f) * 2.5f + 50.0f;
252 /* 115 is the deflection %age that would be
253 when db=6.0. this is an arbitrary
254 endpoint for our scaling.
261 TranzportControlProtocol::show_meter ()
263 if (route_table[0] == 0) {
267 float level = route_get_peak_input_power (0, 0);
268 float fraction = log_meter (level);
270 /* we draw using a choice of a sort of double colon-like character ("::") or a single, left-aligned ":".
271 the screen is 20 chars wide, so we can display 40 different levels. compute the level,
272 then figure out how many "::" to fill. if the answer is odd, make the last one a ":"
275 uint32_t fill = (uint32_t) floor (fraction * 40);
279 if (fill == last_meter_fill) {
284 last_meter_fill = fill;
286 bool add_single_level = (fill % 2 != 0);
289 if (fraction > 0.98) {
290 light_on (LightAnysolo);
293 /* add all full steps */
295 for (i = 0; i < fill; ++i) {
296 buf[i] = 0x07; /* tranzport special code for 4 quadrant LCD block */
299 /* add a possible half-step */
301 if (i < 20 && add_single_level) {
302 buf[i] = 0x03; /* tranzport special code for 2 left quadrant LCD block */
306 /* fill rest with space */
308 for (; i < 20; ++i) {
312 /* print() requires this */
321 TranzportControlProtocol::show_transport_time ()
323 jack_nframes_t where = session->transport_frame();
325 if (where != last_where) {
330 session->smpte_time (where, smpte);
332 if (smpte.negative) {
333 sprintf (buf, "-%02" PRIu32 ":", smpte.hours);
335 sprintf (buf, " %02" PRIu32 ":", smpte.hours);
339 sprintf (buf, "%02" PRIu32 ":", smpte.minutes);
342 sprintf (buf, "%02" PRIu32 ":", smpte.seconds);
345 sprintf (buf, "%02" PRIu32, smpte.frames);
353 TranzportControlProtocol::_monitor_work (void* arg)
355 return static_cast<TranzportControlProtocol*>(arg)->monitor_work ();
359 TranzportControlProtocol::open ()
362 struct usb_device *dev;
368 for (bus = usb_busses; bus; bus = bus->next) {
370 for(dev = bus->devices; dev; dev = dev->next) {
371 if (dev->descriptor.idVendor != VENDORID)
373 if (dev->descriptor.idProduct != PRODUCTID)
375 return open_core (dev);
379 error << _("Tranzport: no device detected") << endmsg;
384 TranzportControlProtocol::open_core (struct usb_device* dev)
386 if (!(udev = usb_open (dev))) {
387 error << _("Tranzport: cannot open USB transport") << endmsg;
391 if (usb_claim_interface (udev, 0) < 0) {
392 error << _("Tranzport: cannot claim USB interface") << endmsg;
398 if (usb_set_configuration (udev, 1) < 0) {
399 cerr << _("Tranzport: cannot configure USB interface") << endmsg;
406 TranzportControlProtocol::close ()
414 if (usb_release_interface (udev, 0) < 0) {
415 error << _("Tranzport: cannot release interface") << endmsg;
419 if (usb_close (udev)) {
420 error << _("Tranzport: cannot close device") << endmsg;
429 TranzportControlProtocol::write (uint8_t* cmd, uint32_t timeout_override)
433 val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout);
444 TranzportControlProtocol::lcd_clear ()
446 /* special case this for speed and atomicity */
458 for (uint8_t i = 0; i < 10; ++i) {
460 usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, 1000);
463 memset (current_screen, ' ', sizeof (current_screen));
464 memset (pending_screen, ' ', sizeof (pending_screen));
468 TranzportControlProtocol::lights_off ()
480 cmd[2] = LightRecord;
481 if (write (cmd, 1000) == 0) {
482 lights[LightRecord] = false;
484 cmd[2] = LightTrackrec;
485 if (write (cmd, 1000) == 0) {
486 lights[LightTrackrec] = false;
488 cmd[2] = LightTrackmute;
489 if (write (cmd, 1000) == 0) {
490 lights[LightTrackmute] = false;
492 cmd[2] = LightTracksolo;
493 if (write (cmd, 1000) == 0) {
494 lights[LightTracksolo] = false;
496 cmd[2] = LightAnysolo;
497 if (write (cmd, 1000) == 0) {
498 lights[LightAnysolo] = false;
501 if (write (cmd, 1000) == 0) {
502 lights[LightLoop] = false;
505 if (write (cmd, 1000) == 0) {
506 lights[LightPunch] = false;
511 TranzportControlProtocol::light_on (LightID light)
515 if (!lights[light]) {
526 if (write (cmd, 1000) == 0) {
527 lights[light] = true;
539 TranzportControlProtocol::light_off (LightID light)
554 if (write (cmd, 1000) == 0) {
555 lights[light] = false;
567 TranzportControlProtocol::monitor_work ()
569 struct sched_param rtparam;
573 bool first_time = true;
575 PBD::ThreadCreated (pthread_self(), X_("Tranzport"));
577 memset (&rtparam, 0, sizeof (rtparam));
578 rtparam.sched_priority = 3; /* XXX should be relative to audio (JACK) thread */
580 if ((err = pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam)) != 0) {
581 // do we care? not particularly.
582 PBD::info << string_compose (_("%1: thread not running with realtime scheduling (%2)"), name(), strerror (errno)) << endmsg;
585 pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, 0);
586 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
592 /* bInterval for this beastie is 10ms */
594 /* anything to read ? */
596 if (_device_status == STATUS_OFFLINE) {
597 light_off (LightRecord);
601 pthread_testcancel();
602 val = usb_interrupt_read (udev, READ_ENDPOINT, (char*) buf, 8, 10);
603 pthread_testcancel();
609 if (_device_status != STATUS_OFFLINE) {
615 /* update whatever needs updating */
624 TranzportControlProtocol::update_state ()
631 /* do the text updates */
633 switch (display_mode) {
634 case DisplayBigMeter:
643 /* next: flush LCD */
647 for (row = 0; row < 2; ++row) {
649 for (col_base = 0, col = 0; col < 20; ) {
651 if (pending_screen[row][col] != current_screen[row][col]) {
653 /* something in this cell is different, so dump the cell
662 cmd[3] = pending_screen[row][col_base];
663 cmd[4] = pending_screen[row][col_base+1];
664 cmd[5] = pending_screen[row][col_base+2];
665 cmd[6] = pending_screen[row][col_base+3];
668 if (usb_interrupt_write (udev, WRITE_ENDPOINT, (char *) cmd, 8, 1000) == 8) {
669 /* successful write: copy to current */
670 memcpy (¤t_screen[row][col_base], &pending_screen[row][col_base], 4);
673 /* skip the rest of the 4 character cell since we wrote+copied it already */
683 if (col && col % 4 == 0) {
691 /* now update LED's */
695 if (route_table[0]) {
696 AudioTrack* at = dynamic_cast<AudioTrack*> (route_table[0]);
697 if (at && at->record_enabled()) {
698 pending_lights[LightTrackrec] = true;
700 pending_lights[LightTrackrec] = false;
702 if (route_get_muted (0)) {
703 pending_lights[LightTrackmute] = true;
705 pending_lights[LightTrackmute] = false;
707 if (route_get_soloed (0)) {
708 pending_lights[LightTracksolo] = true;
710 pending_lights[LightTracksolo] = false;
714 pending_lights[LightTrackrec] = false;
715 pending_lights[LightTracksolo] = false;
716 pending_lights[LightTrackmute] = false;
721 if (session->get_auto_loop()) {
722 pending_lights[LightLoop] = true;
724 pending_lights[LightLoop] = false;
727 if (session->get_punch_in() || session->get_punch_out()) {
728 pending_lights[LightPunch] = true;
730 pending_lights[LightPunch] = false;
733 if (session->get_record_enabled()) {
734 pending_lights[LightRecord] = true;
736 pending_lights[LightRecord] = false;
739 if (session->soloing ()) {
740 pending_lights[LightAnysolo] = true;
742 pending_lights[LightAnysolo] = false;
745 /* flush changed light change */
747 if (pending_lights[LightRecord] != lights[LightRecord]) {
748 if (pending_lights[LightRecord]) {
749 light_on (LightRecord);
751 light_off (LightRecord);
755 if (pending_lights[LightTracksolo] != lights[LightTracksolo]) {
756 if (pending_lights[LightTracksolo]) {
757 light_on (LightTracksolo);
759 light_off (LightTracksolo);
763 if (pending_lights[LightTrackmute] != lights[LightTrackmute]) {
764 if (pending_lights[LightTrackmute]) {
765 light_on (LightTrackmute);
767 light_off (LightTrackmute);
771 if (pending_lights[LightTracksolo] != lights[LightTracksolo]) {
772 if (pending_lights[LightTracksolo]) {
773 light_on (LightTracksolo);
775 light_off (LightTracksolo);
779 if (pending_lights[LightAnysolo] != lights[LightAnysolo]) {
780 if (pending_lights[LightAnysolo]) {
781 light_on (LightAnysolo);
783 light_off (LightAnysolo);
787 if (pending_lights[LightLoop] != lights[LightLoop]) {
788 if (pending_lights[LightLoop]) {
789 light_on (LightLoop);
791 light_off (LightLoop);
795 if (pending_lights[LightPunch] != lights[LightPunch]) {
796 if (pending_lights[LightPunch]) {
797 light_on (LightPunch);
799 light_off (LightPunch);
807 TranzportControlProtocol::process (uint8_t* buf)
809 // 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]);
811 uint32_t this_button_mask;
812 uint32_t button_changes;
814 _device_status = buf[1];
815 this_button_mask = 0;
816 this_button_mask |= buf[2] << 24;
817 this_button_mask |= buf[3] << 16;
818 this_button_mask |= buf[4] << 8;
819 this_button_mask |= buf[5];
822 button_changes = (this_button_mask ^ buttonmask);
823 buttonmask = this_button_mask;
829 if (button_changes & ButtonBattery) {
830 if (buttonmask & ButtonBattery) {
831 button_event_battery_press (buttonmask&ButtonShift);
833 button_event_battery_release (buttonmask&ButtonShift);
836 if (button_changes & ButtonBacklight) {
837 if (buttonmask & ButtonBacklight) {
838 button_event_backlight_press (buttonmask&ButtonShift);
840 button_event_backlight_release (buttonmask&ButtonShift);
843 if (button_changes & ButtonTrackLeft) {
844 if (buttonmask & ButtonTrackLeft) {
845 button_event_trackleft_press (buttonmask&ButtonShift);
847 button_event_trackleft_release (buttonmask&ButtonShift);
850 if (button_changes & ButtonTrackRight) {
851 if (buttonmask & ButtonTrackRight) {
852 button_event_trackright_press (buttonmask&ButtonShift);
854 button_event_trackright_release (buttonmask&ButtonShift);
857 if (button_changes & ButtonTrackRec) {
858 if (buttonmask & ButtonTrackRec) {
859 button_event_trackrec_press (buttonmask&ButtonShift);
861 button_event_trackrec_release (buttonmask&ButtonShift);
864 if (button_changes & ButtonTrackMute) {
865 if (buttonmask & ButtonTrackMute) {
866 button_event_trackmute_press (buttonmask&ButtonShift);
868 button_event_trackmute_release (buttonmask&ButtonShift);
871 if (button_changes & ButtonTrackSolo) {
872 if (buttonmask & ButtonTrackSolo) {
873 button_event_tracksolo_press (buttonmask&ButtonShift);
875 button_event_tracksolo_release (buttonmask&ButtonShift);
878 if (button_changes & ButtonUndo) {
879 if (buttonmask & ButtonUndo) {
880 button_event_undo_press (buttonmask&ButtonShift);
882 button_event_undo_release (buttonmask&ButtonShift);
885 if (button_changes & ButtonIn) {
886 if (buttonmask & ButtonIn) {
887 button_event_in_press (buttonmask&ButtonShift);
889 button_event_in_release (buttonmask&ButtonShift);
892 if (button_changes & ButtonOut) {
893 if (buttonmask & ButtonOut) {
894 button_event_out_press (buttonmask&ButtonShift);
896 button_event_out_release (buttonmask&ButtonShift);
899 if (button_changes & ButtonPunch) {
900 if (buttonmask & ButtonPunch) {
901 button_event_punch_press (buttonmask&ButtonShift);
903 button_event_punch_release (buttonmask&ButtonShift);
906 if (button_changes & ButtonLoop) {
907 if (buttonmask & ButtonLoop) {
908 button_event_loop_press (buttonmask&ButtonShift);
910 button_event_loop_release (buttonmask&ButtonShift);
913 if (button_changes & ButtonPrev) {
914 if (buttonmask & ButtonPrev) {
915 button_event_prev_press (buttonmask&ButtonShift);
917 button_event_prev_release (buttonmask&ButtonShift);
920 if (button_changes & ButtonAdd) {
921 if (buttonmask & ButtonAdd) {
922 button_event_add_press (buttonmask&ButtonShift);
924 button_event_add_release (buttonmask&ButtonShift);
927 if (button_changes & ButtonNext) {
928 if (buttonmask & ButtonNext) {
929 button_event_next_press (buttonmask&ButtonShift);
931 button_event_next_release (buttonmask&ButtonShift);
934 if (button_changes & ButtonRewind) {
935 if (buttonmask & ButtonRewind) {
936 button_event_rewind_press (buttonmask&ButtonShift);
938 button_event_rewind_release (buttonmask&ButtonShift);
941 if (button_changes & ButtonFastForward) {
942 if (buttonmask & ButtonFastForward) {
943 button_event_fastforward_press (buttonmask&ButtonShift);
945 button_event_fastforward_release (buttonmask&ButtonShift);
948 if (button_changes & ButtonStop) {
949 if (buttonmask & ButtonStop) {
950 button_event_stop_press (buttonmask&ButtonShift);
952 button_event_stop_release (buttonmask&ButtonShift);
955 if (button_changes & ButtonPlay) {
956 if (buttonmask & ButtonPlay) {
957 button_event_play_press (buttonmask&ButtonShift);
959 button_event_play_release (buttonmask&ButtonShift);
962 if (button_changes & ButtonRecord) {
963 if (buttonmask & ButtonRecord) {
964 button_event_record_press (buttonmask&ButtonShift);
966 button_event_record_release (buttonmask&ButtonShift);
974 TranzportControlProtocol::show_current_track ()
976 if (route_table[0] == 0) {
977 print (0, 0, "--------");
979 print (0, 0, route_get_name (0).substr (0, 8).c_str());
984 TranzportControlProtocol::button_event_battery_press (bool shifted)
989 TranzportControlProtocol::button_event_battery_release (bool shifted)
994 TranzportControlProtocol::button_event_backlight_press (bool shifted)
999 TranzportControlProtocol::button_event_backlight_release (bool shifted)
1004 TranzportControlProtocol::button_event_trackleft_press (bool shifted)
1010 TranzportControlProtocol::button_event_trackleft_release (bool shifted)
1015 TranzportControlProtocol::button_event_trackright_press (bool shifted)
1021 TranzportControlProtocol::button_event_trackright_release (bool shifted)
1026 TranzportControlProtocol::button_event_trackrec_press (bool shifted)
1029 toggle_all_rec_enables ();
1031 route_set_rec_enable (0, !route_get_rec_enable (0));
1036 TranzportControlProtocol::button_event_trackrec_release (bool shifted)
1041 TranzportControlProtocol::button_event_trackmute_press (bool shifted)
1043 route_set_muted (0, !route_get_muted (0));
1047 TranzportControlProtocol::button_event_trackmute_release (bool shifted)
1052 TranzportControlProtocol::button_event_tracksolo_press (bool shifted)
1054 if (display_mode == DisplayBigMeter) {
1055 light_off (LightAnysolo);
1060 session->set_all_solo (!session->soloing());
1062 route_set_soloed (0, !route_get_soloed (0));
1067 TranzportControlProtocol::button_event_tracksolo_release (bool shifted)
1072 TranzportControlProtocol::button_event_undo_press (bool shifted)
1082 TranzportControlProtocol::button_event_undo_release (bool shifted)
1087 TranzportControlProtocol::button_event_in_press (bool shifted)
1092 ControlProtocol::ZoomIn (); /* EMIT SIGNAL */
1097 TranzportControlProtocol::button_event_in_release (bool shifted)
1102 TranzportControlProtocol::button_event_out_press (bool shifted)
1105 toggle_punch_out ();
1107 ControlProtocol::ZoomOut (); /* EMIT SIGNAL */
1112 TranzportControlProtocol::button_event_out_release (bool shifted)
1117 TranzportControlProtocol::button_event_punch_press (bool shifted)
1122 TranzportControlProtocol::button_event_punch_release (bool shifted)
1127 TranzportControlProtocol::button_event_loop_press (bool shifted)
1130 next_wheel_shift_mode ();
1137 TranzportControlProtocol::button_event_loop_release (bool shifted)
1142 TranzportControlProtocol::button_event_prev_press (bool shifted)
1145 ControlProtocol::ZoomToSession (); /* EMIT SIGNAL */
1152 TranzportControlProtocol::button_event_prev_release (bool shifted)
1157 TranzportControlProtocol::button_event_add_press (bool shifted)
1163 TranzportControlProtocol::button_event_add_release (bool shifted)
1168 TranzportControlProtocol::button_event_next_press (bool shifted)
1178 TranzportControlProtocol::button_event_next_release (bool shifted)
1183 TranzportControlProtocol::button_event_rewind_press (bool shifted)
1193 TranzportControlProtocol::button_event_rewind_release (bool shifted)
1198 TranzportControlProtocol::button_event_fastforward_press (bool shifted)
1208 TranzportControlProtocol::button_event_fastforward_release (bool shifted)
1213 TranzportControlProtocol::button_event_stop_press (bool shifted)
1216 next_display_mode ();
1223 TranzportControlProtocol::button_event_stop_release (bool shifted)
1228 TranzportControlProtocol::button_event_play_press (bool shifted)
1234 TranzportControlProtocol::button_event_play_release (bool shifted)
1239 TranzportControlProtocol::button_event_record_press (bool shifted)
1244 rec_enable_toggle ();
1249 TranzportControlProtocol::button_event_record_release (bool shifted)
1254 TranzportControlProtocol::datawheel ()
1256 if ((buttonmask & ButtonTrackRight) || (buttonmask & ButtonTrackLeft)) {
1258 /* track scrolling */
1260 if (_datawheel < WheelDirectionThreshold) {
1266 timerclear (&last_wheel_motion);
1268 } else if ((buttonmask & ButtonPrev) || (buttonmask & ButtonNext)) {
1270 if (_datawheel < WheelDirectionThreshold) {
1276 timerclear (&last_wheel_motion);
1278 } else if (buttonmask & ButtonShift) {
1280 /* parameter control */
1282 if (route_table[0]) {
1283 switch (wheel_shift_mode) {
1284 case WheelShiftGain:
1285 if (_datawheel < WheelDirectionThreshold) {
1292 if (_datawheel < WheelDirectionThreshold) {
1299 case WheelShiftMaster:
1304 timerclear (&last_wheel_motion);
1308 switch (wheel_mode) {
1325 TranzportControlProtocol::scroll ()
1327 if (_datawheel < WheelDirectionThreshold) {
1328 ScrollTimeline (0.2);
1330 ScrollTimeline (-0.2);
1335 TranzportControlProtocol::scrub ()
1339 struct timeval delta;
1342 gettimeofday (&now, 0);
1344 if (_datawheel < WheelDirectionThreshold) {
1350 if (dir != last_wheel_dir) {
1351 /* changed direction, start over */
1354 if (timerisset (&last_wheel_motion)) {
1356 timersub (&now, &last_wheel_motion, &delta);
1358 /* 10 clicks per second => speed == 1.0 */
1360 speed = 100000.0f / (delta.tv_sec * 1000000 + delta.tv_usec);
1364 /* start at half-speed and see where we go from there */
1370 last_wheel_motion = now;
1371 last_wheel_dir = dir;
1373 set_transport_speed (speed * dir);
1377 TranzportControlProtocol::shuttle ()
1379 if (_datawheel < WheelDirectionThreshold) {
1380 if (session->transport_speed() < 0) {
1381 session->request_transport_speed (1.0);
1383 session->request_transport_speed (session->transport_speed() + 0.1);
1386 if (session->transport_speed() > 0) {
1387 session->request_transport_speed (-1.0);
1389 session->request_transport_speed (session->transport_speed() - 0.1);
1395 TranzportControlProtocol::step_gain_up ()
1397 if (buttonmask & ButtonStop) {
1398 gain_fraction += 0.001;
1400 gain_fraction += 0.01;
1403 if (gain_fraction > 2.0) {
1404 gain_fraction = 2.0;
1407 route_set_gain (0, slider_position_to_gain (gain_fraction));
1411 TranzportControlProtocol::step_gain_down ()
1413 if (buttonmask & ButtonStop) {
1414 gain_fraction -= 0.001;
1416 gain_fraction -= 0.01;
1419 if (gain_fraction < 0.0) {
1420 gain_fraction = 0.0;
1423 route_set_gain (0, slider_position_to_gain (gain_fraction));
1427 TranzportControlProtocol::step_pan_right ()
1432 TranzportControlProtocol::step_pan_left ()
1437 TranzportControlProtocol::next_wheel_shift_mode ()
1439 switch (wheel_shift_mode) {
1440 case WheelShiftGain:
1441 wheel_shift_mode = WheelShiftPan;
1444 wheel_shift_mode = WheelShiftMaster;
1446 case WheelShiftMaster:
1447 wheel_shift_mode = WheelShiftGain;
1454 TranzportControlProtocol::next_wheel_mode ()
1456 switch (wheel_mode) {
1458 wheel_mode = WheelScrub;
1461 wheel_mode = WheelShuttle;
1464 wheel_mode = WheelTimeline;
1471 TranzportControlProtocol::next_track ()
1473 ControlProtocol::next_track (current_track_id);
1474 gain_fraction = gain_to_slider_position (route_get_effective_gain (0));
1478 TranzportControlProtocol::prev_track ()
1480 ControlProtocol::prev_track (current_track_id);
1481 gain_fraction = gain_to_slider_position (route_get_effective_gain (0));
1485 TranzportControlProtocol::show_wheel_mode ()
1489 switch (wheel_mode) {
1501 switch (wheel_shift_mode) {
1502 case WheelShiftGain:
1510 case WheelShiftMaster:
1515 print (1, 0, text.c_str());
1519 TranzportControlProtocol::print (int row, int col, const char *text)
1522 uint32_t left = strlen (text);
1526 if (row < 0 || row > 1) {
1530 if (col < 0 || col > 19) {
1536 if (col >= 0 && col < 4) {
1539 } else if (col >= 4 && col < 8) {
1542 } else if (col >= 8 && col < 12) {
1545 } else if (col >= 12 && col < 16) {
1548 } else if (col >= 16 && col < 20) {
1555 int offset = col % 4;
1557 /* copy current cell contents into tmp */
1559 memcpy (tmp, &pending_screen[row][base_col], 4);
1561 /* overwrite with new text */
1563 uint32_t tocopy = min ((4U - offset), left);
1565 memcpy (tmp+offset, text, tocopy);
1567 /* copy it back to pending */
1569 memcpy (&pending_screen[row][base_col], tmp, 4);