summaryrefslogtreecommitdiff
path: root/libs/ardour/ticker.cc
blob: 866fa83e07057ad1e0e9c9eea7c29d051cac67f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
    Copyright (C) 2008 Hans Baier 

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    $Id$
*/

#include "ardour/ticker.h"
#include "ardour/session.h"
#include "ardour/tempo.h"

namespace ARDOUR
{


void Ticker::set_session(Session& s) 
{
	 _session = &s;
	 
	 if(_session) {
		 _session->tick.connect(mem_fun (*this, &Ticker::tick));
		 _session->GoingAway.connect(mem_fun (*this, &Ticker::going_away));
	 }
}

void MidiClockTicker::set_session(Session& s) 
{
	 Ticker::set_session(s);
	 
	 if(_session) {
		 _session->MIDIClock_PortChanged.connect(mem_fun (*this, &MidiClockTicker::update_midi_clock_port));
		 update_midi_clock_port();
	 }
}

void MidiClockTicker::update_midi_clock_port()
{
	 _jack_port = (MIDI::JACK_MidiPort*) _session->midi_clock_port();
}

void MidiClockTicker::tick(const nframes_t& transport_frames, const BBT_Time& transport_bbt, const SMPTE::Time& transport_smpt)
{	
	if (!Config->get_send_midi_clock() || _session == 0 || _session->transport_speed() != 1.0f)
		return;
	
	const Tempo& current_tempo = _session->tempo_map().tempo_at(transport_frames);
	const Meter& current_meter = _session->tempo_map().meter_at(transport_frames);
	double frames_per_beat =
		current_tempo.frames_per_beat(_session->nominal_frame_rate(),
		                              current_meter);

	double quarter_notes_per_beat = 4.0 / current_tempo.note_type();
	double frames_per_quarter_note = frames_per_beat / quarter_notes_per_beat;

	nframes_t one_ppqn_in_frames = frames_per_quarter_note / double (_ppqn);
	
	nframes_t next_tick = _last_tick + one_ppqn_in_frames;
	nframes_t next_tick_offset = next_tick - transport_frames;
	
	assert(_jack_port->is_process_thread());
	static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_TICK };
	_jack_port->write(_midi_clock_tick, 1, next_tick_offset);
	
	_last_tick = next_tick;
}

}