static void a2dp_init(void) { snd_async_handler_t *async; snd_timer_info_t *info; snd_timer_params_t *params; long resolution; char timername[64]; int err, i; a2dp_lock(); for (i = 0; i < MAX_CONNECTIONS; i++) connections[i] = NULL; a2dp_unlock(); snd_timer_info_alloca(&info); snd_timer_params_alloca(¶ms); sprintf(timername, "hw:CLASS=%i,SCLASS=%i,CARD=%i,DEV=%i,SUBDEV=%i", SND_TIMER_CLASS_GLOBAL, SND_TIMER_CLASS_NONE, 0, SND_TIMER_GLOBAL_SYSTEM, 0); err = snd_timer_open(&timer, timername, SND_TIMER_OPEN_NONBLOCK); if (err < 0) { SNDERR("Can't open global timer"); return; } err = snd_timer_info(timer, info); if (err < 0) { SNDERR("Can't get global timer info"); return; } snd_timer_params_set_auto_start(params, 1); resolution = snd_timer_info_get_resolution(info); snd_timer_params_set_ticks(params, 1000000000 / resolution); if (snd_timer_params_get_ticks(params) < 1) snd_timer_params_set_ticks(params, 1); err = snd_timer_params(timer, params); if (err < 0) { SNDERR("Can't set global timer parameters"); snd_timer_close(timer); return; } err = snd_async_add_timer_handler(&async, timer, a2dp_timer, NULL); if (err < 0) { SNDERR("Can't create global async callback"); snd_timer_close(timer); return; } err = snd_timer_start(timer); }
unsigned int AlsaTimer::setTimerFreq(unsigned int freq) { signed int err; unsigned int setTick, actFreq; if(TIMER_DEBUG) printf("AlsaTimer::setTimerFreq(this=%p)\n",this); setTick = (1000000000 / snd_timer_info_get_resolution(info)) / freq; if (setTick == 0) { // return, print error if freq is below 500 (timing will suffer) if (((1000000000.0 / snd_timer_info_get_resolution(info)) / snd_timer_params_get_ticks(params)) < 500) { fprintf(stderr,"AlsaTimer::setTimerTicks(): requested freq %u Hz too high for timer (max is %g)\n", freq, 1000000000.0 / snd_timer_info_get_resolution(info)); fprintf(stderr," freq stays at %ld Hz\n", (long int)((1000000000.0 / snd_timer_info_get_resolution(info)) / snd_timer_params_get_ticks(params))); } return (long int)((1000000000.0 / snd_timer_info_get_resolution(info)) / snd_timer_params_get_ticks(params)); } actFreq = (1000000000 / snd_timer_info_get_resolution(info)) / setTick; if (actFreq != freq) { fprintf(stderr,"AlsaTimer::setTimerTicks(): warning: requested %u Hz, actual freq is %u Hz\n", freq, actFreq); } if(TIMER_DEBUG) printf("AlsaTimer::setTimerFreq(): Setting ticks (period) to %d ticks\n", setTick); snd_timer_params_set_auto_start(params, 1); snd_timer_params_set_ticks(params, setTick); if ((err = snd_timer_params(handle, params)) < 0) { fprintf(stderr, "AlsaTimer::setTimerFreq(): timer params %i (%s)\n", err, snd_strerror(err)); return 0; } return actFreq; }
signed int AlsaTimer::initTimer() { if(TIMER_DEBUG) printf("AlsaTimer::initTimer(this=%p)\n",this); int err; int devclass = SND_TIMER_CLASS_GLOBAL; int sclass = SND_TIMER_CLASS_NONE; int card = 0; int device = SND_TIMER_GLOBAL_SYSTEM; int subdevice = 0; int test_ids[] = { SND_TIMER_GLOBAL_SYSTEM , SND_TIMER_GLOBAL_RTC #ifdef SND_TIMER_GLOBAL_HPET , SND_TIMER_GLOBAL_HPET #endif }; int max_ids = sizeof(test_ids) / sizeof(int); long best_res = LONG_MAX; //int best_dev = -1; // SND_TIMER_GLOBAL_SYSTEM; int best_dev = SND_TIMER_GLOBAL_SYSTEM; int i; if (id || info || params) { fprintf(stderr,"AlsaTimer::initTimer(): called on initialised timer!\n"); return fds->fd; } snd_timer_id_malloc(&id); snd_timer_info_malloc(&info); snd_timer_params_malloc(¶ms); if (findBest) { for (i = 0; i < max_ids; ++i) { device = test_ids[i]; sprintf(timername, "hw:CLASS=%i,SCLASS=%i,CARD=%i,DEV=%i,SUBDEV=%i", devclass, sclass, card, device, subdevice); if ((err = snd_timer_open(&handle, timername, SND_TIMER_OPEN_NONBLOCK)) < 0) { continue; } if ((err = snd_timer_info(handle, info)) < 0) { snd_timer_close(handle); continue; } // select a non slave timer with the lowest resolution value int is_slave = snd_timer_info_is_slave(info); long res = snd_timer_info_get_resolution(info); if ((is_slave == 0) && (best_res > res)) { best_res = res; best_dev = device; } snd_timer_close(handle); } device = best_dev; } //if(best_dev==-1) // return -1; // no working timer found sprintf(timername, "hw:CLASS=%i,SCLASS=%i,CARD=%i,DEV=%i,SUBDEV=%i", devclass, sclass, card, device, subdevice); if ((err = snd_timer_open(&handle, timername, SND_TIMER_OPEN_NONBLOCK))<0) { fprintf(stderr, "AlsaTimer::initTimer(): timer open %i (%s)\n", err, snd_strerror(err)); return -1; } if ((err = snd_timer_info(handle, info)) < 0) { fprintf(stderr, "AlsaTimer::initTimer(): timer info %i (%s)\n", err, snd_strerror(err)); return -1; } //if(debugMsg) fprintf(stderr, "AlsaTimer::initTimer(): best available ALSA timer: %s\n", snd_timer_info_get_name(info)); snd_timer_params_set_auto_start(params, 1); snd_timer_params_set_ticks(params, 1); if ((err = snd_timer_params(handle, params)) < 0) { fprintf(stderr, "AlsaTimer::initTimer(): timer params %i (%s)\n", err, snd_strerror(err)); return -1; } count = snd_timer_poll_descriptors_count(handle); fds = (pollfd *)calloc(count, sizeof(pollfd)); if (fds == NULL) { fprintf(stderr, "AlsaTimer::initTimer(): malloc error\n"); return -1; } if ((err = snd_timer_poll_descriptors(handle, fds, count)) < 0) { fprintf(stderr, "AlsaTimer::initTimer(): snd_timer_poll_descriptors error: %s\n", snd_strerror(err)); return -1; } return fds->fd; }