1d5ac70f0Sopenharmony_ci#include <unistd.h> 2d5ac70f0Sopenharmony_ci#include <sys/time.h> 3d5ac70f0Sopenharmony_ci#include <alsa/asoundlib.h> 4d5ac70f0Sopenharmony_ci#include <alsa/seq.h> 5d5ac70f0Sopenharmony_ci 6d5ac70f0Sopenharmony_civoid normalize(struct timeval *tv) 7d5ac70f0Sopenharmony_ci{ 8d5ac70f0Sopenharmony_ci if (tv->tv_sec == 0) { 9d5ac70f0Sopenharmony_ci while (tv->tv_usec <= -1000000) { tv->tv_usec += 1000000; --tv->tv_sec; } 10d5ac70f0Sopenharmony_ci while (tv->tv_usec >= 1000000) { tv->tv_usec -= 1000000; ++tv->tv_sec; } 11d5ac70f0Sopenharmony_ci } else if (tv->tv_sec < 0) { 12d5ac70f0Sopenharmony_ci while (tv->tv_usec <= -1000000) { tv->tv_usec += 1000000; --tv->tv_sec; } 13d5ac70f0Sopenharmony_ci while (tv->tv_usec > 0) { tv->tv_usec -= 1000000; ++tv->tv_sec; } 14d5ac70f0Sopenharmony_ci } else { 15d5ac70f0Sopenharmony_ci while (tv->tv_usec >= 1000000) { tv->tv_usec -= 1000000; ++tv->tv_sec; } 16d5ac70f0Sopenharmony_ci while (tv->tv_usec < 0) { tv->tv_usec += 1000000; --tv->tv_sec; } 17d5ac70f0Sopenharmony_ci } 18d5ac70f0Sopenharmony_ci} 19d5ac70f0Sopenharmony_ci 20d5ac70f0Sopenharmony_ciint 21d5ac70f0Sopenharmony_cimain(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) 22d5ac70f0Sopenharmony_ci{ 23d5ac70f0Sopenharmony_ci snd_seq_t *handle; 24d5ac70f0Sopenharmony_ci int portid; 25d5ac70f0Sopenharmony_ci /* int npfd; 26d5ac70f0Sopenharmony_ci struct pollfd *pfd; 27d5ac70f0Sopenharmony_ci */ 28d5ac70f0Sopenharmony_ci int queue; 29d5ac70f0Sopenharmony_ci /* int i; 30d5ac70f0Sopenharmony_ci int rval;' 31d5ac70f0Sopenharmony_ci */ 32d5ac70f0Sopenharmony_ci struct timeval starttv, prevdiff; 33d5ac70f0Sopenharmony_ci int countdown = -1; 34d5ac70f0Sopenharmony_ci /* snd_seq_queue_timer_t *timer; 35d5ac70f0Sopenharmony_ci snd_timer_id_t *timerid; 36d5ac70f0Sopenharmony_ci */ 37d5ac70f0Sopenharmony_ci 38d5ac70f0Sopenharmony_ci if (snd_seq_open(&handle, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) { 39d5ac70f0Sopenharmony_ci fprintf(stderr, "failed to open ALSA sequencer interface\n"); 40d5ac70f0Sopenharmony_ci return 1; 41d5ac70f0Sopenharmony_ci } 42d5ac70f0Sopenharmony_ci 43d5ac70f0Sopenharmony_ci snd_seq_set_client_name(handle, "generator"); 44d5ac70f0Sopenharmony_ci 45d5ac70f0Sopenharmony_ci if ((portid = snd_seq_create_simple_port 46d5ac70f0Sopenharmony_ci (handle, "generator", 47d5ac70f0Sopenharmony_ci SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, 0)) < 0) { 48d5ac70f0Sopenharmony_ci fprintf(stderr, "failed to create ALSA sequencer port\n"); 49d5ac70f0Sopenharmony_ci return 1; 50d5ac70f0Sopenharmony_ci } 51d5ac70f0Sopenharmony_ci 52d5ac70f0Sopenharmony_ci if ((queue = snd_seq_alloc_queue(handle)) < 0) { 53d5ac70f0Sopenharmony_ci fprintf(stderr, "failed to create ALSA sequencer queue\n"); 54d5ac70f0Sopenharmony_ci return 1; 55d5ac70f0Sopenharmony_ci } 56d5ac70f0Sopenharmony_ci/* 57d5ac70f0Sopenharmony_ci snd_seq_queue_timer_alloca(&timer); 58d5ac70f0Sopenharmony_ci snd_seq_get_queue_timer(handle, queue, timer); 59d5ac70f0Sopenharmony_ci snd_timer_id_alloca(&timerid); 60d5ac70f0Sopenharmony_ci snd_timer_id_set_class(timerid, SND_TIMER_CLASS_PCM); 61d5ac70f0Sopenharmony_ci snd_timer_id_set_sclass(timerid, SND_TIMER_SCLASS_NONE); 62d5ac70f0Sopenharmony_ci snd_timer_id_set_card(timerid, 0); 63d5ac70f0Sopenharmony_ci snd_timer_id_set_device(timerid, 0); 64d5ac70f0Sopenharmony_ci snd_timer_id_set_subdevice(timerid, 0); 65d5ac70f0Sopenharmony_ci snd_seq_queue_timer_set_id(timer, timerid); 66d5ac70f0Sopenharmony_ci snd_seq_set_queue_timer(handle, queue, timer); 67d5ac70f0Sopenharmony_ci*/ 68d5ac70f0Sopenharmony_ci snd_seq_start_queue(handle, queue, 0); 69d5ac70f0Sopenharmony_ci snd_seq_drain_output(handle); 70d5ac70f0Sopenharmony_ci 71d5ac70f0Sopenharmony_ci gettimeofday(&starttv, 0); 72d5ac70f0Sopenharmony_ci prevdiff.tv_sec = 0; 73d5ac70f0Sopenharmony_ci prevdiff.tv_usec = 0; 74d5ac70f0Sopenharmony_ci 75d5ac70f0Sopenharmony_ci while (countdown != 0) { 76d5ac70f0Sopenharmony_ci 77d5ac70f0Sopenharmony_ci snd_seq_queue_status_t *status; 78d5ac70f0Sopenharmony_ci const snd_seq_real_time_t *rtime; 79d5ac70f0Sopenharmony_ci struct timeval tv, diff, diffdiff; 80d5ac70f0Sopenharmony_ci struct timespec ts; 81d5ac70f0Sopenharmony_ci 82d5ac70f0Sopenharmony_ci snd_seq_queue_status_alloca(&status); 83d5ac70f0Sopenharmony_ci 84d5ac70f0Sopenharmony_ci snd_seq_get_queue_status(handle, queue, status); 85d5ac70f0Sopenharmony_ci rtime = snd_seq_queue_status_get_real_time(status); 86d5ac70f0Sopenharmony_ci 87d5ac70f0Sopenharmony_ci gettimeofday(&tv, 0); 88d5ac70f0Sopenharmony_ci 89d5ac70f0Sopenharmony_ci tv.tv_sec -= starttv.tv_sec; 90d5ac70f0Sopenharmony_ci tv.tv_usec -= starttv.tv_usec; 91d5ac70f0Sopenharmony_ci normalize(&tv); 92d5ac70f0Sopenharmony_ci 93d5ac70f0Sopenharmony_ci diff.tv_sec = tv.tv_sec - rtime->tv_sec; 94d5ac70f0Sopenharmony_ci diff.tv_usec = tv.tv_usec - rtime->tv_nsec / 1000; 95d5ac70f0Sopenharmony_ci normalize(&diff); 96d5ac70f0Sopenharmony_ci 97d5ac70f0Sopenharmony_ci diffdiff.tv_sec = diff.tv_sec - prevdiff.tv_sec; 98d5ac70f0Sopenharmony_ci diffdiff.tv_usec = diff.tv_usec - prevdiff.tv_usec; 99d5ac70f0Sopenharmony_ci normalize(&diffdiff); 100d5ac70f0Sopenharmony_ci prevdiff = diff; 101d5ac70f0Sopenharmony_ci 102d5ac70f0Sopenharmony_ci fprintf(stderr, " real time: %12ld sec %8ld usec\nqueue time: %12ld sec %8ld usec\n diff: %12ld sec %8ld usec\n diffdiff: %12ld sec %8ld usec\n", 103d5ac70f0Sopenharmony_ci (long)tv.tv_sec, tv.tv_usec, 104d5ac70f0Sopenharmony_ci (long)rtime->tv_sec, (long)rtime->tv_nsec / 1000, 105d5ac70f0Sopenharmony_ci (long)diff.tv_sec, diff.tv_usec, 106d5ac70f0Sopenharmony_ci (long)diffdiff.tv_sec, (long)diffdiff.tv_usec); 107d5ac70f0Sopenharmony_ci 108d5ac70f0Sopenharmony_ci if (diffdiff.tv_usec > 5000 || 109d5ac70f0Sopenharmony_ci diffdiff.tv_usec < -5000) { 110d5ac70f0Sopenharmony_ci fprintf(stderr, "oops! queue slipped\n"); 111d5ac70f0Sopenharmony_ci if (tv.tv_sec < 5) { 112d5ac70f0Sopenharmony_ci fprintf(stderr, "(ignoring in first few seconds)\n"); 113d5ac70f0Sopenharmony_ci } else { 114d5ac70f0Sopenharmony_ci countdown = 2; 115d5ac70f0Sopenharmony_ci } 116d5ac70f0Sopenharmony_ci } else { 117d5ac70f0Sopenharmony_ci if (countdown > 0) --countdown; 118d5ac70f0Sopenharmony_ci } 119d5ac70f0Sopenharmony_ci 120d5ac70f0Sopenharmony_ci fprintf(stderr, "\n"); 121d5ac70f0Sopenharmony_ci// sleep(1); 122d5ac70f0Sopenharmony_ci ts.tv_sec = 0; 123d5ac70f0Sopenharmony_ci ts.tv_nsec = 500000000; 124d5ac70f0Sopenharmony_ci nanosleep(&ts, 0); 125d5ac70f0Sopenharmony_ci } 126d5ac70f0Sopenharmony_ci return EXIT_SUCCESS; 127d5ac70f0Sopenharmony_ci} 128d5ac70f0Sopenharmony_ci 129