/* * OpenMRCP - Open Source Media Resource Control Protocol Stack * Copyright (C) 2007, Cepstral LLC * * Version: MPL 1.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * Author(s): * Arsen Chaloyan * * Contributor(s): * */ #include "media_timer.h" #ifdef WIN32 #define ENABLE_MULTIMEDIA_TIMERS #endif #ifdef ENABLE_MULTIMEDIA_TIMERS #pragma warning(disable:4201) #include #include #ifndef TIME_KILL_SYNCHRONOUS #define TIME_KILL_SYNCHRONOUS 0x0100 #endif struct media_timer_t { unsigned int timer_id; media_timer_proc timer_proc; void *data; }; #define MAX_MEDIA_TIMERS 10 static media_timer_t media_timer_set[MAX_MEDIA_TIMERS]; static void CALLBACK mm_timer_proc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2); media_timer_t* media_timer_start(unsigned long timeout, media_timer_proc timer_proc, void *data, apr_pool_t *pool) { media_timer_t *timer = NULL; size_t i; for(i = 0; itimer_proc = timer_proc; timer->data = data; timer->timer_id = timeSetEvent(timeout, 0, mm_timer_proc, i, TIME_PERIODIC | TIME_CALLBACK_FUNCTION | TIME_KILL_SYNCHRONOUS); if(!timer->timer_id) { timer = NULL; } } return timer; } void media_timer_stop(media_timer_t *timer) { if(timer) { timeKillEvent(timer->timer_id); timer->timer_id = 0; timer->timer_proc = NULL; timer->data = NULL; } } static void CALLBACK mm_timer_proc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { media_timer_t *timer; if(dwUser >= MAX_MEDIA_TIMERS) { return; } timer = &media_timer_set[dwUser]; timer->timer_proc(timer,timer->data); } #else #include struct media_timer_t { apr_thread_t *thread; apr_byte_t running; unsigned long timeout; media_timer_proc timer_proc; void *data; }; static void* APR_THREAD_FUNC timer_thread_proc(apr_thread_t *thread, void *data); media_timer_t* media_timer_start(unsigned long timeout, media_timer_proc timer_proc, void *data, apr_pool_t *pool) { media_timer_t *timer = apr_palloc(pool,sizeof(media_timer_t)); timer->timeout = timeout; timer->timer_proc = timer_proc; timer->data = data; timer->running = 1; if(apr_thread_create(&timer->thread,NULL,timer_thread_proc,timer,pool) != APR_SUCCESS) { return NULL; } return timer; } void media_timer_stop(media_timer_t *timer) { if(timer) { timer->running = 0; if(timer->thread) { apr_status_t s; apr_thread_join(&s,timer->thread); timer->thread = NULL; } } } static void* APR_THREAD_FUNC timer_thread_proc(apr_thread_t *thread, void *data) { media_timer_t *timer = data; apr_interval_time_t timeout = timer->timeout * 1000; apr_interval_time_t time_drift = 0; apr_time_t time_now, time_last; time_now = apr_time_now(); while(timer->running) { time_last = time_now; timer->timer_proc(timer,timer->data); if(timeout > time_drift) { apr_sleep(timeout - time_drift); } time_now = apr_time_now(); time_drift += time_now - time_last - timeout; #if 0 printf("time_drift=%d\n",time_drift); #endif } return NULL; } #endif