mtc
mtc_trigger(struct mtc *mtc)
if (mtc->tstate != MTC_START) {
logx(2, "%s: not started by mmc yet, waiting.", mtc->dev->path);
if (s->opt == NULL || s->opt->mtc != mtc)
if (!dev_ref(mtc->dev))
if (s->opt == NULL || s->opt->mtc != mtc)
mtc->tstate = MTC_RUN;
mtc_midi_full(mtc);
dev_wakeup(mtc->dev);
mtc_start(struct mtc *mtc)
if (mtc->tstate == MTC_STOP) {
mtc->tstate = MTC_START;
mtc_trigger(mtc);
logx(3, "%s: ignoring mmc start", mtc->dev->path);
mtc_stop(struct mtc *mtc)
switch (mtc->tstate) {
mtc->tstate = MTC_STOP;
mtc->tstate = MTC_STOP;
dev_unref(mtc->dev);
logx(3, "%s: ignored mmc stop", mtc->dev->path);
mtc_loc(struct mtc *mtc, unsigned int origin)
logx(2, "%s: relocated to %u", mtc->dev->path, origin);
if (mtc->tstate == MTC_RUN)
mtc_stop(mtc);
mtc->origin = origin;
if (mtc->tstate == MTC_RUN)
mtc_start(mtc);
mtc_setdev(struct mtc *mtc, struct dev *d)
if (mtc->dev == d)
if (mtc->tstate == MTC_RUN) {
mtc->delta -= mtc->dev->delta;
dev_unref(mtc->dev);
mtc->dev = d;
if (mtc->tstate == MTC_RUN) {
mtc->delta += mtc->dev->delta;
dev_ref(mtc->dev);
dev_wakeup(mtc->dev);
if (o->mtc == mtc)
opt_setdev(o, mtc->dev);
s->xrun = s->opt->mtc != NULL ? XRUN_SYNC : XRUN_IGNORE;
if (s->opt->mtc == NULL) {
mtc_trigger(s->opt->mtc);
mtc_midi_qfr(struct mtc *mtc, int delta)
mtc->delta += delta * MTC_SEC;
qfrlen = mtc->dev->rate * (MTC_SEC / (4 * mtc->fps));
while (mtc->delta >= qfrlen) {
switch (mtc->qfr) {
data = mtc->fr & 0xf;
data = mtc->fr >> 4;
data = mtc->sec & 0xf;
data = mtc->sec >> 4;
data = mtc->min & 0xf;
data = mtc->min >> 4;
data = mtc->hr & 0xf;
data = (mtc->hr >> 4) | (mtc->fps_id << 1);
mtc->fr += 2;
if (mtc->fr < mtc->fps)
mtc->fr -= mtc->fps;
mtc->sec++;
if (mtc->sec < 60)
mtc->sec = 0;
mtc->min++;
if (mtc->min < 60)
mtc->min = 0;
mtc->hr++;
if (mtc->hr < 24)
mtc->hr = 0;
buf[1] = (mtc->qfr << 4) | data;
mtc->qfr++;
mtc->qfr &= 7;
dev_midi_send(mtc->dev, buf, 2);
mtc->delta -= qfrlen;
mtc_midi_full(struct mtc *mtc)
mtc->delta = -MTC_SEC * (int)mtc->dev->bufsz;
if (mtc->dev->rate % (30 * 4 * mtc->dev->round) == 0) {
mtc->fps_id = MTC_FPS_30;
mtc->fps = 30;
} else if (mtc->dev->rate % (25 * 4 * mtc->dev->round) == 0) {
mtc->fps_id = MTC_FPS_25;
mtc->fps = 25;
mtc->fps_id = MTC_FPS_24;
mtc->fps = 24;
logx(3, "%s: mtc full frame at %d, %d fps", mtc->dev->path, mtc->delta, mtc->fps);
fps = mtc->fps;
mtc->hr = (mtc->origin / (MTC_SEC * 3600)) % 24;
mtc->min = (mtc->origin / (MTC_SEC * 60)) % 60;
mtc->sec = (mtc->origin / (MTC_SEC)) % 60;
mtc->fr = (mtc->origin / (MTC_SEC / fps)) % fps;
x.u.full.hr = mtc->hr | (mtc->fps_id << 5);
x.u.full.min = mtc->min;
x.u.full.sec = mtc->sec;
x.u.full.fr = mtc->fr;
mtc->qfr = 0;
dev_midi_send(mtc->dev, (unsigned char *)&x, SYSEX_SIZE(full));
struct mtc mtc_array[1] = {
extern struct mtc mtc_array[1];
void mtc_midi_qfr(struct mtc *, int);
void mtc_midi_full(struct mtc *);
void mtc_trigger(struct mtc *);
void mtc_start(struct mtc *);
void mtc_stop(struct mtc *);
void mtc_loc(struct mtc *, unsigned int);
void mtc_setdev(struct mtc *, struct dev *);
if (o->mtc == NULL)
mtc_setdev(o->mtc, o->dev);
mtc_stop(o->mtc);
if (o->mtc == NULL)
mtc_setdev(o->mtc, o->dev);
mtc_start(o->mtc);
if (o->mtc == NULL)
mtc_setdev(o->mtc, o->dev);
mtc_stop(o->mtc);
mtc_loc(o->mtc,
o->mtc = mmc ? &mtc_array[0] : NULL;
if (o->mtc != NULL && o->mtc->dev != ndev) {
mtc_setdev(o->mtc, ndev);
struct mtc *mtc; /* if set, MMC-controlled MTC source */
o->maxweight, o->mtc != NULL, o->dup, o->mode) == NULL)
if (s->opt->mtc != NULL && s->xrun == XRUN_IGNORE)