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;
47 #include <pbd/abstract_ui.cc>
49 BaseUI::RequestType LEDChange = BaseUI::new_request_type ();
50 BaseUI::RequestType Print = BaseUI::new_request_type ();
51 BaseUI::RequestType SetCurrentTrack = BaseUI::new_request_type ();
54 gain_to_slider_position (ARDOUR::gain_t g)
57 return pow((6.0*log(g)/log(2.0)+192.0)/198.0, 8.0);
61 static inline ARDOUR::gain_t
62 slider_position_to_gain (double pos)
64 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
65 if (pos == 0.0) return 0;
66 return pow (2.0,(sqrt(sqrt(sqrt(pos)))*198.0-192.0)/6.0);
70 TranzportControlProtocol::TranzportControlProtocol (Session& s)
71 : ControlProtocol (s, X_("Tranzport"))
73 /* tranzport controls one track at a time */
75 set_route_table_size (1);
80 _device_status = STATUS_OFFLINE;
83 last_where = max_frames;
84 wheel_mode = WheelTimeline;
85 wheel_shift_mode = WheelShiftGain;
86 timerclear (&last_wheel_motion);
88 last_track_gain = FLT_MAX;
89 display_mode = DisplayNormal;
92 memset (current_screen, 0, sizeof (current_screen));
93 memset (pending_screen, 0, sizeof (pending_screen));
95 for (uint32_t i = 0; i < sizeof(lights)/sizeof(lights[0]); ++i) {
99 for (uint32_t i = 0; i < sizeof(pending_lights)/sizeof(pending_lights[0]); ++i) {
100 pending_lights[i] = false;
104 TranzportControlProtocol::~TranzportControlProtocol ()
110 TranzportControlProtocol::probe ()
113 struct usb_device *dev;
119 for (bus = usb_busses; bus; bus = bus->next) {
121 for(dev = bus->devices; dev; dev = dev->next) {
122 if (dev->descriptor.idVendor == VENDORID && dev->descriptor.idProduct == PRODUCTID) {
132 TranzportControlProtocol::set_active (bool yn)
142 if (pthread_create_and_store (X_("tranzport monitor"), &thread, 0, _monitor_work, this) == 0) {
149 cerr << "Begin tranzport shutdown\n";
150 pthread_cancel_one (thread);
151 cerr << "Thread dead\n";
154 // cerr << "dev reset\n";
157 cerr << "End tranzport shutdown\n";
165 TranzportControlProtocol::show_track_gain ()
167 if (route_table[0]) {
168 gain_t g = route_get_gain (0);
169 if (g != last_track_gain) {
171 snprintf (buf, sizeof (buf), "%6.1fdB", coefficient_to_dB (route_get_effective_gain (0)));
181 TranzportControlProtocol::normal_update ()
183 show_current_track ();
184 show_transport_time ();
190 TranzportControlProtocol::next_display_mode ()
192 switch (display_mode) {
194 display_mode = DisplayBigMeter;
197 case DisplayBigMeter:
198 display_mode = DisplayNormal;
204 TranzportControlProtocol::enter_big_meter_mode ()
209 display_mode = DisplayBigMeter;
213 TranzportControlProtocol::enter_normal_display_mode ()
215 last_where += 1; /* force time redisplay */
216 last_track_gain = FLT_MAX; /* force gain redisplay */
220 show_current_track ();
223 show_transport_time ();
224 display_mode = DisplayNormal;
231 float def = 0.0f; /* Meter deflection %age */
235 } else if (db < -60.0f) {
236 def = (db + 70.0f) * 0.25f;
237 } else if (db < -50.0f) {
238 def = (db + 60.0f) * 0.5f + 2.5f;
239 } else if (db < -40.0f) {
240 def = (db + 50.0f) * 0.75f + 7.5f;
241 } else if (db < -30.0f) {
242 def = (db + 40.0f) * 1.5f + 15.0f;
243 } else if (db < -20.0f) {
244 def = (db + 30.0f) * 2.0f + 30.0f;
245 } else if (db < 6.0f) {
246 def = (db + 20.0f) * 2.5f + 50.0f;
251 /* 115 is the deflection %age that would be
252 when db=6.0. this is an arbitrary
253 endpoint for our scaling.
260 TranzportControlProtocol::show_meter ()
262 if (route_table[0] == 0) {
266 float level = route_get_peak_input_power (0, 0);
267 float fraction = log_meter (level);
269 /* we draw using a choice of a sort of double colon-like character ("::") or a single, left-aligned ":".
270 the screen is 20 chars wide, so we can display 40 different levels. compute the level,
271 then figure out how many "::" to fill. if the answer is odd, make the last one a ":"
274 uint32_t fill = (uint32_t) floor (fraction * 40);
278 if (fill == last_meter_fill) {
283 last_meter_fill = fill;
285 bool add_single_level = (fill % 2 != 0);
288 if (fraction > 0.98) {
289 light_on (LightAnysolo);
292 /* add all full steps */
294 for (i = 0; i < fill; ++i) {
295 buf[i] = 0x07; /* tranzport special code for 4 quadrant LCD block */
298 /* add a possible half-step */
300 if (i < 20 && add_single_level) {
301 buf[i] = 0x03; /* tranzport special code for 2 left quadrant LCD block */
305 /* fill rest with space */
307 for (; i < 20; ++i) {
311 /* print() requires this */
320 TranzportControlProtocol::show_transport_time ()
322 jack_nframes_t where = session->transport_frame();
324 if (where != last_where) {
329 session->smpte_time (where, smpte);
331 if (smpte.negative) {
332 sprintf (buf, "-%02" PRIu32 ":", smpte.hours);
334 sprintf (buf, " %02" PRIu32 ":", smpte.hours);
338 sprintf (buf, "%02" PRIu32 ":", smpte.minutes);
341 sprintf (buf, "%02" PRIu32 ":", smpte.seconds);
344 sprintf (buf, "%02" PRIu32, smpte.frames);
352 TranzportControlProtocol::_monitor_work (void* arg)
354 return static_cast<TranzportControlProtocol*>(arg)->monitor_work ();
358 TranzportControlProtocol::open ()
361 struct usb_device *dev;
367 for (bus = usb_busses; bus; bus = bus->next) {
369 for(dev = bus->devices; dev; dev = dev->next) {
370 if (dev->descriptor.idVendor != VENDORID)
372 if (dev->descriptor.idProduct != PRODUCTID)
374 return open_core (dev);
378 error << _("Tranzport: no device detected") << endmsg;
383 TranzportControlProtocol::open_core (struct usb_device* dev)
385 if (!(udev = usb_open (dev))) {
386 error << _("Tranzport: cannot open USB transport") << endmsg;
390 if (usb_claim_interface (udev, 0) < 0) {
391 error << _("Tranzport: cannot claim USB interface") << endmsg;
397 if (usb_set_configuration (udev, 1) < 0) {
398 cerr << _("Tranzport: cannot configure USB interface") << endmsg;
405 TranzportControlProtocol::close ()
413 if (usb_release_interface (udev, 0) < 0) {
414 error << _("Tranzport: cannot release interface") << endmsg;
418 if (usb_close (udev)) {
419 error << _("Tranzport: cannot close device") << endmsg;
428 TranzportControlProtocol::write (uint8_t* cmd, uint32_t timeout_override)
432 val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout);
443 TranzportControlProtocol::lcd_clear ()
445 /* special case this for speed and atomicity */
457 for (uint8_t i = 0; i < 10; ++i) {
459 usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, 1000);
462 memset (current_screen, ' ', sizeof (current_screen));
463 memset (pending_screen, ' ', sizeof (pending_screen));
467 TranzportControlProtocol::lights_off ()
479 cmd[2] = LightRecord;
480 if (write (cmd, 1000) == 0) {
481 lights[LightRecord] = false;
483 cmd[2] = LightTrackrec;
484 if (write (cmd, 1000) == 0) {
485 lights[LightTrackrec] = false;
487 cmd[2] = LightTrackmute;
488 if (write (cmd, 1000) == 0) {
489 lights[LightTrackmute] = false;
491 cmd[2] = LightTracksolo;
492 if (write (cmd, 1000) == 0) {
493 lights[LightTracksolo] = false;
495 cmd[2] = LightAnysolo;
496 if (write (cmd, 1000) == 0) {
497 lights[LightAnysolo] = false;
500 if (write (cmd, 1000) == 0) {
501 lights[LightLoop] = false;
504 if (write (cmd, 1000) == 0) {
505 lights[LightPunch] = false;
510 TranzportControlProtocol::light_on (LightID light)
514 if (!lights[light]) {
525 if (write (cmd, 1000) == 0) {
526 lights[light] = true;
538 TranzportControlProtocol::light_off (LightID light)
553 if (write (cmd, 1000) == 0) {
554 lights[light] = false;
566 TranzportControlProtocol::monitor_work ()
568 struct sched_param rtparam;
572 bool first_time = true;
574 PBD::ThreadCreated (pthread_self(), X_("Tranzport"));
576 memset (&rtparam, 0, sizeof (rtparam));
577 rtparam.sched_priority = 3; /* XXX should be relative to audio (JACK) thread */
579 if ((err = pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam)) != 0) {
580 // do we care? not particularly.
581 info << string_compose (_("%1: thread not running with realtime scheduling (%2)"), name(), strerror (errno)) << endmsg;
584 pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, 0);
585 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
591 /* bInterval for this beastie is 10ms */
593 /* anything to read ? */
595 if (_device_status == STATUS_OFFLINE) {
596 light_off (LightRecord);
600 pthread_testcancel();
601 val = usb_interrupt_read (udev, READ_ENDPOINT, (char*) buf, 8, 10);
602 pthread_testcancel();
608 if (_device_status != STATUS_OFFLINE) {
614 /* update whatever needs updating */
623 TranzportControlProtocol::update_state ()
630 /* do the text updates */
632 switch (display_mode) {
633 case DisplayBigMeter:
642 /* next: flush LCD */
646 for (row = 0; row < 2; ++row) {
648 for (col_base = 0, col = 0; col < 20; ) {
650 if (pending_screen[row][col] != current_screen[row][col]) {
652 /* something in this cell is different, so dump the cell
661 cmd[3] = pending_screen[row][col_base];
662 cmd[4] = pending_screen[row][col_base+1];
663 cmd[5] = pending_screen[row][col_base+2];
664 cmd[6] = pending_screen[row][col_base+3];
667 if (usb_interrupt_write (udev, WRITE_ENDPOINT, (char *) cmd, 8, 1000) == 8) {
668 /* successful write: copy to current */
669 memcpy (¤t_screen[row][col_base], &pending_screen[row][col_base], 4);
672 /* skip the rest of the 4 character cell since we wrote+copied it already */
682 if (col && col % 4 == 0) {
690 /* now update LED's */
694 if (route_table[0]) {
695 AudioTrack* at = dynamic_cast<AudioTrack*> (route_table[0]);
696 if (at && at->record_enabled()) {
697 pending_lights[LightTrackrec] = true;
699 pending_lights[LightTrackrec] = false;
701 if (route_get_muted (0)) {
702 pending_lights[LightTrackmute] = true;
704 pending_lights[LightTrackmute] = false;
706 if (route_get_soloed (0)) {
707 pending_lights[LightTracksolo] = true;
709 pending_lights[LightTracksolo] = false;
713 pending_lights[LightTrackrec] = false;
714 pending_lights[LightTracksolo] = false;
715 pending_lights[LightTrackmute] = false;
720 if (session->get_auto_loop()) {
721 pending_lights[LightLoop] = true;
723 pending_lights[LightLoop] = false;
726 if (session->get_punch_in() || session->get_punch_out()) {
727 pending_lights[LightPunch] = true;
729 pending_lights[LightPunch] = false;
732 if (session->get_record_enabled()) {
733 pending_lights[LightRecord] = true;
735 pending_lights[LightRecord] = false;
738 if (session->soloing ()) {
739 pending_lights[LightAnysolo] = true;
741 pending_lights[LightAnysolo] = false;
744 /* flush changed light change */
746 if (pending_lights[LightRecord] != lights[LightRecord]) {
747 if (pending_lights[LightRecord]) {
748 light_on (LightRecord);
750 light_off (LightRecord);
754 if (pending_lights[LightTracksolo] != lights[LightTracksolo]) {
755 if (pending_lights[LightTracksolo]) {
756 light_on (LightTracksolo);
758 light_off (LightTracksolo);
762 if (pending_lights[LightTrackmute] != lights[LightTrackmute]) {
763 if (pending_lights[LightTrackmute]) {
764 light_on (LightTrackmute);
766 light_off (LightTrackmute);
770 if (pending_lights[LightTracksolo] != lights[LightTracksolo]) {
771 if (pending_lights[LightTracksolo]) {
772 light_on (LightTracksolo);
774 light_off (LightTracksolo);
778 if (pending_lights[LightAnysolo] != lights[LightAnysolo]) {
779 if (pending_lights[LightAnysolo]) {
780 light_on (LightAnysolo);
782 light_off (LightAnysolo);
786 if (pending_lights[LightLoop] != lights[LightLoop]) {
787 if (pending_lights[LightLoop]) {
788 light_on (LightLoop);
790 light_off (LightLoop);
794 if (pending_lights[LightPunch] != lights[LightPunch]) {
795 if (pending_lights[LightPunch]) {
796 light_on (LightPunch);
798 light_off (LightPunch);
806 TranzportControlProtocol::process (uint8_t* buf)
808 // 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]);
810 uint32_t this_button_mask;
811 uint32_t button_changes;
813 _device_status = buf[1];
814 this_button_mask = 0;
815 this_button_mask |= buf[2] << 24;
816 this_button_mask |= buf[3] << 16;
817 this_button_mask |= buf[4] << 8;
818 this_button_mask |= buf[5];
821 button_changes = (this_button_mask ^ buttonmask);
822 buttonmask = this_button_mask;
828 if (button_changes & ButtonBattery) {
829 if (buttonmask & ButtonBattery) {
830 button_event_battery_press (buttonmask&ButtonShift);
832 button_event_battery_release (buttonmask&ButtonShift);
835 if (button_changes & ButtonBacklight) {
836 if (buttonmask & ButtonBacklight) {
837 button_event_backlight_press (buttonmask&ButtonShift);
839 button_event_backlight_release (buttonmask&ButtonShift);
842 if (button_changes & ButtonTrackLeft) {
843 if (buttonmask & ButtonTrackLeft) {
844 button_event_trackleft_press (buttonmask&ButtonShift);
846 button_event_trackleft_release (buttonmask&ButtonShift);
849 if (button_changes & ButtonTrackRight) {
850 if (buttonmask & ButtonTrackRight) {
851 button_event_trackright_press (buttonmask&ButtonShift);
853 button_event_trackright_release (buttonmask&ButtonShift);
856 if (button_changes & ButtonTrackRec) {
857 if (buttonmask & ButtonTrackRec) {
858 button_event_trackrec_press (buttonmask&ButtonShift);
860 button_event_trackrec_release (buttonmask&ButtonShift);
863 if (button_changes & ButtonTrackMute) {
864 if (buttonmask & ButtonTrackMute) {
865 button_event_trackmute_press (buttonmask&ButtonShift);
867 button_event_trackmute_release (buttonmask&ButtonShift);
870 if (button_changes & ButtonTrackSolo) {
871 if (buttonmask & ButtonTrackSolo) {
872 button_event_tracksolo_press (buttonmask&ButtonShift);
874 button_event_tracksolo_release (buttonmask&ButtonShift);
877 if (button_changes & ButtonUndo) {
878 if (buttonmask & ButtonUndo) {
879 button_event_undo_press (buttonmask&ButtonShift);
881 button_event_undo_release (buttonmask&ButtonShift);
884 if (button_changes & ButtonIn) {
885 if (buttonmask & ButtonIn) {
886 button_event_in_press (buttonmask&ButtonShift);
888 button_event_in_release (buttonmask&ButtonShift);
891 if (button_changes & ButtonOut) {
892 if (buttonmask & ButtonOut) {
893 button_event_out_press (buttonmask&ButtonShift);
895 button_event_out_release (buttonmask&ButtonShift);
898 if (button_changes & ButtonPunch) {
899 if (buttonmask & ButtonPunch) {
900 button_event_punch_press (buttonmask&ButtonShift);
902 button_event_punch_release (buttonmask&ButtonShift);
905 if (button_changes & ButtonLoop) {
906 if (buttonmask & ButtonLoop) {
907 button_event_loop_press (buttonmask&ButtonShift);
909 button_event_loop_release (buttonmask&ButtonShift);
912 if (button_changes & ButtonPrev) {
913 if (buttonmask & ButtonPrev) {
914 button_event_prev_press (buttonmask&ButtonShift);
916 button_event_prev_release (buttonmask&ButtonShift);
919 if (button_changes & ButtonAdd) {
920 if (buttonmask & ButtonAdd) {
921 button_event_add_press (buttonmask&ButtonShift);
923 button_event_add_release (buttonmask&ButtonShift);
926 if (button_changes & ButtonNext) {
927 if (buttonmask & ButtonNext) {
928 button_event_next_press (buttonmask&ButtonShift);
930 button_event_next_release (buttonmask&ButtonShift);
933 if (button_changes & ButtonRewind) {
934 if (buttonmask & ButtonRewind) {
935 button_event_rewind_press (buttonmask&ButtonShift);
937 button_event_rewind_release (buttonmask&ButtonShift);
940 if (button_changes & ButtonFastForward) {
941 if (buttonmask & ButtonFastForward) {
942 button_event_fastforward_press (buttonmask&ButtonShift);
944 button_event_fastforward_release (buttonmask&ButtonShift);
947 if (button_changes & ButtonStop) {
948 if (buttonmask & ButtonStop) {
949 button_event_stop_press (buttonmask&ButtonShift);
951 button_event_stop_release (buttonmask&ButtonShift);
954 if (button_changes & ButtonPlay) {
955 if (buttonmask & ButtonPlay) {
956 button_event_play_press (buttonmask&ButtonShift);
958 button_event_play_release (buttonmask&ButtonShift);
961 if (button_changes & ButtonRecord) {
962 if (buttonmask & ButtonRecord) {
963 button_event_record_press (buttonmask&ButtonShift);
965 button_event_record_release (buttonmask&ButtonShift);
973 TranzportControlProtocol::show_current_track ()
975 if (route_table[0] == 0) {
976 print (0, 0, "--------");
978 print (0, 0, route_get_name (0).substr (0, 8).c_str());
983 TranzportControlProtocol::button_event_battery_press (bool shifted)
988 TranzportControlProtocol::button_event_battery_release (bool shifted)
993 TranzportControlProtocol::button_event_backlight_press (bool shifted)
998 TranzportControlProtocol::button_event_backlight_release (bool shifted)
1003 TranzportControlProtocol::button_event_trackleft_press (bool shifted)
1009 TranzportControlProtocol::button_event_trackleft_release (bool shifted)
1014 TranzportControlProtocol::button_event_trackright_press (bool shifted)
1020 TranzportControlProtocol::button_event_trackright_release (bool shifted)
1025 TranzportControlProtocol::button_event_trackrec_press (bool shifted)
1028 toggle_all_rec_enables ();
1030 route_set_rec_enable (0, !route_get_rec_enable (0));
1035 TranzportControlProtocol::button_event_trackrec_release (bool shifted)
1040 TranzportControlProtocol::button_event_trackmute_press (bool shifted)
1042 route_set_muted (0, !route_get_muted (0));
1046 TranzportControlProtocol::button_event_trackmute_release (bool shifted)
1051 TranzportControlProtocol::button_event_tracksolo_press (bool shifted)
1053 if (display_mode == DisplayBigMeter) {
1054 light_off (LightAnysolo);
1059 session->set_all_solo (!session->soloing());
1061 route_set_soloed (0, !route_get_soloed (0));
1066 TranzportControlProtocol::button_event_tracksolo_release (bool shifted)
1071 TranzportControlProtocol::button_event_undo_press (bool shifted)
1081 TranzportControlProtocol::button_event_undo_release (bool shifted)
1086 TranzportControlProtocol::button_event_in_press (bool shifted)
1091 ControlProtocol::ZoomIn (); /* EMIT SIGNAL */
1096 TranzportControlProtocol::button_event_in_release (bool shifted)
1101 TranzportControlProtocol::button_event_out_press (bool shifted)
1104 toggle_punch_out ();
1106 ControlProtocol::ZoomOut (); /* EMIT SIGNAL */
1111 TranzportControlProtocol::button_event_out_release (bool shifted)
1116 TranzportControlProtocol::button_event_punch_press (bool shifted)
1121 TranzportControlProtocol::button_event_punch_release (bool shifted)
1126 TranzportControlProtocol::button_event_loop_press (bool shifted)
1129 next_wheel_shift_mode ();
1136 TranzportControlProtocol::button_event_loop_release (bool shifted)
1141 TranzportControlProtocol::button_event_prev_press (bool shifted)
1144 ControlProtocol::ZoomToSession (); /* EMIT SIGNAL */
1151 TranzportControlProtocol::button_event_prev_release (bool shifted)
1156 TranzportControlProtocol::button_event_add_press (bool shifted)
1162 TranzportControlProtocol::button_event_add_release (bool shifted)
1167 TranzportControlProtocol::button_event_next_press (bool shifted)
1177 TranzportControlProtocol::button_event_next_release (bool shifted)
1182 TranzportControlProtocol::button_event_rewind_press (bool shifted)
1192 TranzportControlProtocol::button_event_rewind_release (bool shifted)
1197 TranzportControlProtocol::button_event_fastforward_press (bool shifted)
1207 TranzportControlProtocol::button_event_fastforward_release (bool shifted)
1212 TranzportControlProtocol::button_event_stop_press (bool shifted)
1215 next_display_mode ();
1222 TranzportControlProtocol::button_event_stop_release (bool shifted)
1227 TranzportControlProtocol::button_event_play_press (bool shifted)
1233 TranzportControlProtocol::button_event_play_release (bool shifted)
1238 TranzportControlProtocol::button_event_record_press (bool shifted)
1243 rec_enable_toggle ();
1248 TranzportControlProtocol::button_event_record_release (bool shifted)
1253 TranzportControlProtocol::datawheel ()
1255 if ((buttonmask & ButtonTrackRight) || (buttonmask & ButtonTrackLeft)) {
1257 /* track scrolling */
1259 if (_datawheel < WheelDirectionThreshold) {
1265 timerclear (&last_wheel_motion);
1267 } else if ((buttonmask & ButtonPrev) || (buttonmask & ButtonNext)) {
1269 if (_datawheel < WheelDirectionThreshold) {
1275 timerclear (&last_wheel_motion);
1277 } else if (buttonmask & ButtonShift) {
1279 /* parameter control */
1281 if (route_table[0]) {
1282 switch (wheel_shift_mode) {
1283 case WheelShiftGain:
1284 if (_datawheel < WheelDirectionThreshold) {
1291 if (_datawheel < WheelDirectionThreshold) {
1298 case WheelShiftMaster:
1303 timerclear (&last_wheel_motion);
1307 switch (wheel_mode) {
1324 TranzportControlProtocol::scroll ()
1326 if (_datawheel < WheelDirectionThreshold) {
1327 ScrollTimeline (0.2);
1329 ScrollTimeline (-0.2);
1334 TranzportControlProtocol::scrub ()
1338 struct timeval delta;
1341 gettimeofday (&now, 0);
1343 if (_datawheel < WheelDirectionThreshold) {
1349 if (dir != last_wheel_dir) {
1350 /* changed direction, start over */
1353 if (timerisset (&last_wheel_motion)) {
1355 timersub (&now, &last_wheel_motion, &delta);
1357 /* 10 clicks per second => speed == 1.0 */
1359 speed = 100000.0f / (delta.tv_sec * 1000000 + delta.tv_usec);
1363 /* start at half-speed and see where we go from there */
1369 last_wheel_motion = now;
1370 last_wheel_dir = dir;
1372 set_transport_speed (speed * dir);
1376 TranzportControlProtocol::shuttle ()
1378 if (_datawheel < WheelDirectionThreshold) {
1379 if (session->transport_speed() < 0) {
1380 session->request_transport_speed (1.0);
1382 session->request_transport_speed (session->transport_speed() + 0.1);
1385 if (session->transport_speed() > 0) {
1386 session->request_transport_speed (-1.0);
1388 session->request_transport_speed (session->transport_speed() - 0.1);
1394 TranzportControlProtocol::step_gain_up ()
1396 if (buttonmask & ButtonStop) {
1397 gain_fraction += 0.001;
1399 gain_fraction += 0.01;
1402 if (gain_fraction > 2.0) {
1403 gain_fraction = 2.0;
1406 route_set_gain (0, slider_position_to_gain (gain_fraction));
1410 TranzportControlProtocol::step_gain_down ()
1412 if (buttonmask & ButtonStop) {
1413 gain_fraction -= 0.001;
1415 gain_fraction -= 0.01;
1418 if (gain_fraction < 0.0) {
1419 gain_fraction = 0.0;
1422 route_set_gain (0, slider_position_to_gain (gain_fraction));
1426 TranzportControlProtocol::step_pan_right ()
1431 TranzportControlProtocol::step_pan_left ()
1436 TranzportControlProtocol::next_wheel_shift_mode ()
1438 switch (wheel_shift_mode) {
1439 case WheelShiftGain:
1440 wheel_shift_mode = WheelShiftPan;
1443 wheel_shift_mode = WheelShiftMaster;
1445 case WheelShiftMaster:
1446 wheel_shift_mode = WheelShiftGain;
1453 TranzportControlProtocol::next_wheel_mode ()
1455 switch (wheel_mode) {
1457 wheel_mode = WheelScrub;
1460 wheel_mode = WheelShuttle;
1463 wheel_mode = WheelTimeline;
1470 TranzportControlProtocol::next_track ()
1472 ControlProtocol::next_track (current_track_id);
1473 gain_fraction = gain_to_slider_position (route_get_effective_gain (0));
1477 TranzportControlProtocol::prev_track ()
1479 ControlProtocol::prev_track (current_track_id);
1480 gain_fraction = gain_to_slider_position (route_get_effective_gain (0));
1484 TranzportControlProtocol::show_wheel_mode ()
1488 switch (wheel_mode) {
1500 switch (wheel_shift_mode) {
1501 case WheelShiftGain:
1509 case WheelShiftMaster:
1514 print (1, 0, text.c_str());
1518 TranzportControlProtocol::print (int row, int col, const char *text)
1521 uint32_t left = strlen (text);
1525 if (row < 0 || row > 1) {
1529 if (col < 0 || col > 19) {
1535 if (col >= 0 && col < 4) {
1538 } else if (col >= 4 && col < 8) {
1541 } else if (col >= 8 && col < 12) {
1544 } else if (col >= 12 && col < 16) {
1547 } else if (col >= 16 && col < 20) {
1554 int offset = col % 4;
1556 /* copy current cell contents into tmp */
1558 memcpy (tmp, &pending_screen[row][base_col], 4);
1560 /* overwrite with new text */
1562 uint32_t tocopy = min ((4U - offset), left);
1564 memcpy (tmp+offset, text, tocopy);
1566 /* copy it back to pending */
1568 memcpy (&pending_screen[row][base_col], tmp, 4);