* added Menu for sending midi clock
[ardour.git] / libs / ardour / ticker.cc
1 /*
2     Copyright (C) 2008 Hans Baier 
3
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.
8
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.
13
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.
17
18     $Id$
19 */
20
21 #include "ardour/ticker.h"
22 #include "ardour/session.h"
23 #include "ardour/tempo.h"
24
25 namespace ARDOUR
26 {
27
28
29 void Ticker::set_session(Session& s) 
30 {
31          _session = &s;
32          
33          if(_session) {
34                  _session->tick.connect(mem_fun (*this, &Ticker::tick));
35                  _session->GoingAway.connect(mem_fun (*this, &Ticker::going_away));
36          }
37 }
38
39 void MidiClockTicker::set_session(Session& s) 
40 {
41          Ticker::set_session(s);
42          
43          if(_session) {
44                  _session->MIDIClock_PortChanged.connect(mem_fun (*this, &MidiClockTicker::update_midi_clock_port));
45                  update_midi_clock_port();
46          }
47 }
48
49 void MidiClockTicker::update_midi_clock_port()
50 {
51          _jack_port = (MIDI::JACK_MidiPort*) _session->midi_clock_port();
52 }
53
54 void MidiClockTicker::tick(const nframes_t& transport_frames, const BBT_Time& transport_bbt, const SMPTE::Time& transport_smpt)
55 {       
56         if (!Config->get_send_midi_clock() || _session == 0 || _session->transport_speed() != 1.0f)
57                 return;
58         
59         const Tempo& current_tempo = _session->tempo_map().tempo_at(transport_frames);
60         const Meter& current_meter = _session->tempo_map().meter_at(transport_frames);
61         double frames_per_beat =
62                 current_tempo.frames_per_beat(_session->nominal_frame_rate(),
63                                               current_meter);
64
65         double quarter_notes_per_beat = 4.0 / current_tempo.note_type();
66         double frames_per_quarter_note = frames_per_beat / quarter_notes_per_beat;
67
68         nframes_t one_ppqn_in_frames = frames_per_quarter_note / double (_ppqn);
69         
70         nframes_t next_tick = _last_tick + one_ppqn_in_frames;
71         nframes_t next_tick_offset = next_tick - transport_frames;
72         
73         assert(_jack_port->is_process_thread());
74         static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_TICK };
75         _jack_port->write(_midi_clock_tick, 1, next_tick_offset);
76         
77         _last_tick = next_tick;
78 }
79
80 }
81