Thu, 05 Jan 2006 05:29:51 +0000
[gaim-migrate @ 15077]
jabber.c:389: warning: ISO C90 forbids mixed declarations and code
| 12024 | 1 | /* |
| 2 | The mediastreamer library aims at providing modular media processing and I/O | |
| 3 | for linphone, but also for any telephony application. | |
| 4 | Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org | |
| 5 | ||
| 6 | This library is free software; you can redistribute it and/or | |
| 7 | modify it under the terms of the GNU Lesser General Public | |
| 8 | License as published by the Free Software Foundation; either | |
| 9 | version 2.1 of the License, or (at your option) any later version. | |
| 10 | ||
| 11 | This library is distributed in the hope that it will be useful, | |
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 14 | Lesser General Public License for more details. | |
| 15 | ||
| 16 | You should have received a copy of the GNU Lesser General Public | |
| 17 | License along with this library; if not, write to the Free Software | |
| 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | */ | |
| 20 | #ifdef HAVE_CONFIG_H | |
| 21 | #include <config.h> | |
| 22 | #endif | |
| 23 | ||
| 24 | #include "ms.h" | |
| 25 | #include "sndcard.h" | |
| 26 | #include "mscodec.h" | |
| 27 | ||
| 28 | #include <sys/types.h> | |
| 29 | #include <fcntl.h> | |
| 30 | #include <unistd.h> | |
| 31 | #include <string.h> | |
| 32 | #include <stdio.h> | |
| 33 | #include <stdlib.h> | |
| 34 | ||
| 35 | #ifdef VIDEO_ENABLED | |
| 36 | extern void ms_video_source_register_all(); | |
| 37 | #endif | |
| 38 | #ifdef HAVE_ILBC | |
| 39 | extern void ms_ilbc_codec_init(); | |
| 40 | #endif | |
| 41 | ||
| 42 | /** | |
| 43 | * ms_init: | |
| 44 | * | |
| 45 | * | |
| 46 | * Initialize the mediastreamer. This must be the first function called in a program | |
| 47 | * using the mediastreamer library. | |
| 48 | * | |
| 49 | * | |
| 50 | */ | |
| 51 | void ms_init() | |
| 52 | { | |
| 53 | if (!g_thread_supported()) g_thread_init (NULL); | |
| 54 | #ifdef HAVE_GLIB | |
| 55 | if (!g_module_supported()){ | |
| 56 | g_error("GModule is not supported."); | |
| 57 | } | |
| 58 | #endif | |
| 59 | /* initialize the oss subsystem */ | |
| 60 | snd_card_manager_init(snd_card_manager); | |
| 61 | /* register the statically linked codecs */ | |
| 62 | ms_codec_register_all(); | |
| 63 | #ifdef VIDEO_ENABLED | |
| 64 | ms_video_source_register_all(); | |
| 65 | #endif | |
| 66 | #ifdef HAVE_ILBC | |
| 67 | ms_ilbc_codec_init(); | |
| 68 | #endif | |
| 69 | } | |
| 70 | ||
| 71 | ||
| 72 | static gint compare(gconstpointer a, gconstpointer b) | |
| 73 | { | |
| 74 | MSFilter *f1=(MSFilter*)a,*f2=(MSFilter*)b; | |
| 75 | if (f1->klass<f2->klass) return -1; | |
| 76 | if (f1->klass==f2->klass) return 0; | |
| 77 | /* if f1->klass>f2->klass ....*/ | |
| 78 | return 1; | |
| 79 | } | |
| 80 | ||
| 81 | static GList *g_list_append_if_new(GList *l,gpointer data) | |
| 82 | { | |
| 83 | GList *res=l; | |
| 84 | if (g_list_find(res,data)==NULL) | |
| 85 | res=g_list_append(res,data); | |
| 86 | return(res); | |
| 87 | } | |
| 88 | ||
| 89 | static GList *get_nexts(MSFilter *f,GList *l) | |
| 90 | { | |
| 91 | int i; | |
| 92 | MSFifo *fifo; | |
| 93 | MSQueue *q; | |
| 94 | GList *res=l; | |
| 95 | ||
| 96 | /* check fifos*/ | |
| 97 | for (i=0;i <f->klass->max_foutputs;i++) | |
| 98 | { | |
| 99 | fifo=f->outfifos[i]; | |
| 100 | if (fifo!=NULL) res=g_list_append_if_new(res,(gpointer)fifo->next_data); | |
| 101 | } | |
| 102 | /* check queues*/ | |
| 103 | for (i=0;i <f->klass->max_qoutputs;i++) | |
| 104 | { | |
| 105 | q=f->outqueues[i]; | |
| 106 | if (q!=NULL) res=g_list_append_if_new(res,(gpointer)q->next_data); | |
| 107 | } | |
| 108 | return(res); | |
| 109 | } | |
| 110 | ||
| 111 | /* compile graphs attached to a sync source*/ | |
| 112 | int ms_compile(MSSync *sync) | |
| 113 | { | |
| 114 | int i; | |
| 115 | GList *list1=NULL,*list2=NULL,*elem; | |
| 116 | GList *proc_chain=NULL; | |
| 117 | MSFilter *f; | |
| 118 | ||
| 119 | /* first free the old list if we are just updating*/ | |
| 120 | if (sync->execution_list!=NULL) g_list_free(sync->execution_list); | |
| 121 | /* get the list of filters attached to this sync*/ | |
| 122 | for (i=0;i<sync->filters;i++) | |
| 123 | { | |
| 124 | //printf("found filter !\n"); | |
| 125 | list1=g_list_append(list1,sync->attached_filters[i]); | |
| 126 | } | |
| 127 | /* find the processing chain */ | |
| 128 | while (list1!=NULL) | |
| 129 | { | |
| 130 | list2=NULL; | |
| 131 | /* sort the list by types of filter*/ | |
| 132 | list1=g_list_sort(list1,compare); | |
| 133 | /* save into the processing chain list*/ | |
| 134 | //printf("list1 :%i elements\n",g_list_length(list1)); | |
| 135 | proc_chain=g_list_concat(proc_chain,list1); | |
| 136 | /* get all following filters. They are appended to list2*/ | |
| 137 | elem=list1; | |
| 138 | while (elem!=NULL) | |
| 139 | { | |
| 140 | f=(MSFilter*)(elem->data); | |
| 141 | /* check if filter 's status */ | |
| 142 | if (f->klass->attributes & FILTER_CAN_SYNC) | |
| 143 | { | |
| 144 | sync->samples_per_tick=0; | |
| 145 | } | |
| 146 | list2=get_nexts(f,list2); | |
| 147 | elem=g_list_next(elem); | |
| 148 | } | |
| 149 | list1=list2; | |
| 150 | } | |
| 151 | sync->execution_list=proc_chain; | |
| 152 | sync->flags&=~MS_SYNC_NEED_UPDATE; | |
| 153 | ms_trace("%i filters successfully compiled in a processing chain.",g_list_length(sync->execution_list)); | |
| 154 | return 0; | |
| 155 | } | |
| 156 | ||
| 157 | /*execute the processing chain attached to a sync source. It is called as a thread by ms_main()*/ | |
| 158 | void *ms_thread_run(void *sync_ptr) | |
| 159 | { | |
| 160 | MSSync *sync=(MSSync*) sync_ptr; | |
| 161 | GList *filter; | |
| 162 | MSFilter *f; | |
| 163 | ||
| 164 | ||
| 165 | ms_sync_lock(sync); | |
| 166 | while(sync->run) | |
| 167 | { | |
| 168 | //g_message("sync->run=%i",sync->run); | |
| 169 | if (sync->samples_per_tick==0) ms_sync_suspend(sync); | |
| 170 | if (sync->flags & MS_SYNC_NEED_UPDATE){ | |
| 171 | ms_compile(sync); | |
| 172 | ms_sync_setup(sync); | |
| 173 | } | |
| 174 | filter=sync->execution_list; | |
| 175 | ms_sync_unlock(sync); | |
| 176 | //ms_trace("Calling synchronisation"); | |
| 177 | ms_sync_synchronize(sync); | |
| 178 | while(filter!=NULL) | |
| 179 | { | |
| 180 | f=(MSFilter*)filter->data; | |
| 181 | if (MS_FILTER_GET_CLASS(f)->attributes & FILTER_IS_SOURCE) | |
| 182 | { | |
| 183 | /* execute it once */ | |
| 184 | ms_trace("Running source filter %s.",f->klass->name); | |
| 185 | ms_filter_process(f); | |
| 186 | } | |
| 187 | else | |
| 188 | { | |
| 189 | /* make the filter process its input data until it has no more */ | |
| 190 | while ( ms_filter_fifos_have_data(f) || ms_filter_queues_have_data(f) ) | |
| 191 | { | |
| 192 | ms_trace("Running filter %s.",f->klass->name); | |
| 193 | ms_filter_process(f); | |
| 194 | } | |
| 195 | } | |
| 196 | filter=g_list_next(filter); | |
| 197 | } | |
| 198 | ms_sync_lock(sync); | |
| 199 | } | |
| 200 | g_cond_signal(sync->stop_cond); /* signal that the sync thread has finished */ | |
| 201 | ms_sync_unlock(sync); | |
| 202 | g_message("Mediastreamer processing thread is exiting."); | |
| 203 | return NULL; | |
| 204 | } | |
| 205 | ||
| 206 | /* stop the processing chain attached to a sync source.*/ | |
| 207 | void ms_thread_stop(MSSync *sync) | |
| 208 | { | |
| 209 | if (sync->thread!=NULL) | |
| 210 | { | |
| 211 | if (sync->samples_per_tick==0) | |
| 212 | { | |
| 213 | /* to wakeup the thread */ | |
| 214 | //g_cond_signal(sync->thread_cond); | |
| 215 | } | |
| 216 | g_mutex_lock(sync->lock); | |
| 217 | sync->run=0; | |
| 218 | sync->thread=NULL; | |
| 219 | g_cond_wait(sync->stop_cond,sync->lock); | |
| 220 | g_mutex_unlock(sync->lock); | |
| 221 | } | |
| 222 | //g_message("ms_thread_stop() finished."); | |
| 223 | } | |
| 224 | ||
| 225 | /** | |
| 226 | * ms_start: | |
| 227 | * @sync: A synchronisation source to be started. | |
| 228 | * | |
| 229 | * Starts a thread that will shedule all processing chains attached to the synchronisation source @sync. | |
| 230 | * | |
| 231 | * | |
| 232 | */ | |
| 233 | void ms_start(MSSync *sync) | |
| 234 | { | |
| 235 | if (sync->run==1) return; /*already running*/ | |
| 236 | ms_compile(sync); | |
| 237 | ms_sync_setup(sync); | |
| 238 | /* this is to avoid race conditions, for example: | |
| 239 | ms_start(sync); | |
| 240 | ms_oss_write_start(ossw); | |
| 241 | here tge ossw filter need to be compiled to run ms_oss_write_start() | |
| 242 | */ | |
| 243 | ms_trace("ms_start: creating new thread."); | |
| 244 | sync->run=1; | |
| 245 | sync->thread=g_thread_create((GThreadFunc)ms_thread_run,(gpointer)sync,TRUE,NULL); | |
| 246 | if (sync->thread==NULL){ | |
| 247 | g_warning("Could not create thread !"); | |
| 248 | } | |
| 249 | } | |
| 250 | ||
| 251 | /** | |
| 252 | * ms_stop: | |
| 253 | * @sync: A synchronisation source to be stopped. | |
| 254 | * | |
| 255 | * Stop the thread that was sheduling the processing chains attached to the synchronisation source @sync. | |
| 256 | * The processing chains are kept unchanged, no object is freed. The synchronisation source can be restarted using ms_start(). | |
| 257 | * | |
| 258 | * | |
| 259 | */ | |
| 260 | void ms_stop(MSSync *sync) | |
| 261 | { | |
| 262 | ms_thread_stop(sync); | |
| 263 | ms_sync_unsetup(sync); | |
| 264 | } | |
| 265 | ||
| 266 | ||
| 267 | gint ms_load_plugin(gchar *path) | |
| 268 | { | |
| 269 | #ifdef HAVE_GLIB | |
| 270 | g_module_open(path,0); | |
| 271 | #endif | |
| 272 | return 0; | |
| 273 | } | |
| 274 | ||
| 275 | gchar * ms_proc_get_param(gchar *parameter) | |
| 276 | { | |
| 277 | gchar *file; | |
| 278 | int fd; | |
| 279 | int err,len; | |
| 280 | gchar *p,*begin,*end; | |
| 281 | gchar *ret; | |
| 282 | fd=open("/proc/cpuinfo",O_RDONLY); | |
| 283 | if (fd<0){ | |
| 284 | g_warning("Could not open /proc/cpuinfo."); | |
| 285 | return NULL; | |
| 286 | } | |
| 287 | file=g_malloc(1024); | |
| 288 | err=read(fd,file,1024); | |
| 289 | file[err-1]='\0'; | |
| 290 | /* find the parameter */ | |
| 291 | p=strstr(file,parameter); | |
| 292 | if (p==NULL){ | |
| 293 | /* parameter not found */ | |
| 294 | g_free(file); | |
| 295 | return NULL; | |
| 296 | } | |
| 297 | /* find the following ':' */ | |
| 298 | p=strchr(p,':'); | |
| 299 | if (p==NULL){ | |
| 300 | g_free(file); | |
| 301 | return NULL; | |
| 302 | } | |
| 303 | /* find the value*/ | |
| 304 | begin=p+2; | |
| 305 | end=strchr(begin,'\n'); | |
| 306 | if (end==NULL) end=strchr(begin,'\0'); | |
| 307 | len=end-begin+1; | |
| 308 | ret=g_malloc(len+1); | |
| 309 | snprintf(ret,len,"%s",begin); | |
| 310 | //printf("%s=%s\n",parameter,ret); | |
| 311 | g_free(file); | |
| 312 | return ret; | |
| 313 | } | |
| 314 | ||
| 315 | gint ms_proc_get_type() | |
| 316 | { | |
| 317 | static int proc_type=0; | |
| 318 | gchar *value; | |
| 319 | if (proc_type==0){ | |
| 320 | value=ms_proc_get_param("cpu family"); | |
| 321 | if (value!=NULL) { | |
| 322 | proc_type=atoi(value); | |
| 323 | g_free(value); | |
| 324 | }else return -1; | |
| 325 | } | |
| 326 | return proc_type; | |
| 327 | } | |
| 328 | ||
| 329 | gint ms_proc_get_speed() | |
| 330 | { | |
| 331 | char *value; | |
| 332 | static int proc_speed=0; | |
| 333 | if (proc_speed==0){ | |
| 334 | value=ms_proc_get_param("cpu MHz"); | |
| 335 | if (value!=NULL){ | |
| 336 | proc_speed=atoi(value); | |
| 337 | g_free(value); | |
| 338 | }else return -1; | |
| 339 | } | |
| 340 | //printf("proc_speed=%i\n",proc_speed); | |
| 341 | return proc_speed; | |
| 342 | } |