Hello,
I am trying to write an alsa sequencer. So I read as I can some of your
tutorials, and I don't really understand what I am doing wrong, please
help me.
I want to send scheduled event with the queuing system, but with RTC
timer the queue doesn't start, and with the other timer the queue start
but no events are sent.
I have joined to this email a small code, with the same kind of
functions I am using, and some /proc/asound/seq/* outputs.
Regards,
Gilbux
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <alsa/asoundlib.h>
#define __TQSE_SEQNAME "TestQSchedEv"
#define __TQSE_PORTNAME "OutputPort"
#define __TQSE_QUEUENAME "TQSE_Queue"
#define __TQSE_BPM 120
#define __TQSE_PPQ 192
#define __TQSE_ERR_CODE -3
snd_seq_t *seqh;
int seqid, portid, queueid;
void SetTempo(unsigned int bpm,
unsigned int ppq)
{
snd_seq_queue_tempo_t *tempo;
unsigned int beat_in_microsec
= (unsigned int) (60000000 / bpm);
int err;
snd_seq_queue_tempo_alloca(&tempo);
snd_seq_queue_tempo_set_tempo(tempo, beat_in_microsec);
snd_seq_queue_tempo_set_ppq(tempo, ppq);
err = snd_seq_set_queue_tempo(seqh, queueid, tempo);
if (err < 0)
{
fprintf(stderr,
"SetTempo: snd_seq_set_queue_tempo: %s\n",
snd_strerror(err));
exit(__TQSE_ERR_CODE);
}
return;
}
void StartQueue(void)
{
int err;
snd_seq_start_queue(seqh, queueid, 0);
err = snd_seq_drain_output(seqh);
if (err < 0)
{
fprintf(stderr,
"StartQueue: snd_seq_drain_output: %s\n",
snd_strerror(err));
exit(__TQSE_ERR_CODE);
}
return;
}
void StopQueue(void)
{
int err;
snd_seq_stop_queue(seqh, queueid, 0);
err = snd_seq_drain_output(seqh);
if (err < 0)
{
fprintf(stderr,
"StopQueue: snd_seq_drain_output: %s\n",
snd_strerror(err));
exit(__TQSE_ERR_CODE);
}
return;
}
void SetNoteEv(unsigned char channel,
unsigned char note,
unsigned int duration,
unsigned int ticktime)
{
/* Trying to set queued note ev scheduled with ticktime. */
snd_seq_event_t ev;
int err;
snd_seq_ev_clear(&ev);
snd_seq_ev_schedule_tick(&ev, queueid, 0, ticktime);
snd_seq_ev_set_source(&ev, portid);
snd_seq_ev_set_subs(&ev);
snd_seq_ev_set_note(&ev, channel, note, 127, duration);
err = snd_seq_event_output_direct(seqh, &ev);
if (err < 0)
{
fprintf(stderr,
"SetNoteEv: snd_seq_event_output_direct: %s\n",
snd_strerror(err));
exit(__TQSE_ERR_CODE);
}
return;
}
void InitSeqPortQueue(void)
{
/* I try to init the alsa sequencer to just output
event I don't touch the queue pool output, because
it seems to have a default size in /proc/asound/seq/queue. */
int err;
err = snd_seq_open(&seqh, "default", SND_SEQ_OPEN_OUTPUT, 0);
if (err < 0)
{
fprintf(stderr, "snd_seq_open: %s\n", snd_strerror(err));
exit(__TQSE_ERR_CODE);
}
err = snd_seq_set_client_name(seqh, __TQSE_SEQNAME);
if (err < 0)
{
fprintf(stderr, "snd_seq_set_client_name: %s\n", snd_strerror(err));
exit(__TQSE_ERR_CODE);
}
seqid = snd_seq_client_id(seqh);
if (seqid < 0)
{
fprintf(stderr, "snd_seq_client_id: %s\n", snd_strerror(seqid));
exit(__TQSE_ERR_CODE);
}
portid = snd_seq_create_simple_port(seqh, __TQSE_PORTNAME,
SND_SEQ_PORT_CAP_SUBS_READ \
|SND_SEQ_PORT_CAP_READ, 0);
if (portid < 0)
{
fprintf(stderr, "_Init_GAlsaSeqPort: snd_seq_create_simple_port: %s\n",
snd_strerror(portid));
exit(__TQSE_ERR_CODE);
}
queueid = snd_seq_alloc_named_queue(seqh, __TQSE_QUEUENAME);
if (queueid < 0)
{
fprintf(stderr, "_Init_GAlsaSeqQueue: snd_seq_alloc_named_queue: %s\n",
snd_strerror(queueid));
exit(__TQSE_ERR_CODE);
}
return;
}
void CloseSeqPortQueue(void)
{
int err;
err = snd_seq_free_queue(seqh, queueid);
if (err < 0)
fprintf(stderr, "snd_seq_free_queue: %s\n", snd_strerror(err));
err = snd_seq_delete_simple_port(seqh, portid);
if (err < 0)
fprintf(stderr, "close client port : %s\n", snd_strerror(err));
err = snd_seq_close(seqh);
if (err < 0)
fprintf(stderr, "close seq client : %s\n", snd_strerror(err));
return;
}
int main(void)
{
unsigned int i;
InitSeqPortQueue();
SetTempo((unsigned int) __TQSE_BPM,
(unsigned int) __TQSE_PPQ);
/* Preparing the queue to send an event every 4 beats */
for (i = 0; i < 16; i++)
SetNoteEv(1,
60,
(4 * __TQSE_PPQ),
(i * 16 * __TQSE_PPQ));
printf("Press Enter to start the queue when all subscribtion are done.\n");
/* trying to set enough time for event transimission */
i = (17 * 60 / __TQSE_BPM) + 1;
fgetc(stdin);
printf("Starting the queue\n");
StartQueue();
sleep(i);
printf("\nStopping the queue\n");
StopQueue();
CloseSeqPortQueue();
return 0;
}
/* I compiled it with :
gcc -Wall -g -o TestQSchedEv TestQSchedEv.c -lasound */
/proc/asound/seq/* before starting the queue :
Client info
cur clients : 2
peak clients : 3
max clients : 192
Client 0 : "System" [Kernel]
Port 0 : "Timer" (Rwe-)
Port 1 : "Announce" (R-e-)
Client 128 : "TestQSchedEv" [User]
Port 0 : "OutputPort" (R-e-)
Output pool :
Pool size : 500
Cells in use : 16
Peak cells in use : 16
Alloc success : 16
Alloc failures : 0
queue 0: [TQSE_Queue]
owned by client : 128
lock status : Locked
queued time events : 0
queued tick events : 16
timer state : Stopped
timer PPQ : 192
current tempo : 500000
current BPM : 120
current time : 0.000000000 s
current tick : 0
Timer for queue 0 : RTC timer
Period time : 0.000000000
Skew : 65536 / 65536
-----
/proc/asound/seq/* after starting the queue :
Client info
cur clients : 2
peak clients : 3
max clients : 192
Client 0 : "System" [Kernel]
Port 0 : "Timer" (Rwe-)
Port 1 : "Announce" (R-e-)
Client 128 : "TestQSchedEv" [User]
Port 0 : "OutputPort" (R-e-)
Output pool :
Pool size : 500
Cells in use : 0
Peak cells in use : 16
Alloc success : 16
Alloc failures : 0
queue 0: [TQSE_Queue]
owned by client : 128
lock status : Locked
queued time events : 0
queued tick events : 0
timer state : Running
timer PPQ : 192
current tempo : 500000
current BPM : 120
current time : 0.000000000 s
current tick : 0
Timer for queue 0 : RTC timer
Period time : 0.000976562
Skew : 65536 / 65536
_______________________________________________
Alsa-devel mailing list
Alsa-devel@xxxxxxxxxxxxxxxx
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel