Credit Nyx's b-frame work
[HandBrake.git] / libhb / ports.c
blobbdeadc1f89688f22b2e3bfba2a869d59c120f6a0
1 /* $Id: ports.c,v 1.15 2005/10/15 18:05:03 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
7 #include <time.h>
8 #include <sys/time.h>
10 #if defined( SYS_BEOS )
11 #include <OS.h>
12 #include <signal.h>
13 #elif defined( SYS_CYGWIN )
14 #include <windows.h>
15 #endif
17 #if USE_PTHREAD
18 #include <pthread.h>
19 #endif
21 //#ifdef SYS_CYGWIN
22 //#include <winsock2.h>
23 //#include <ws2tcpip.h>
24 //#else
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <netdb.h>
28 #include <netinet/in.h>
29 //#endif
31 #include "hb.h"
33 /************************************************************************
34 * hb_get_date()
35 ************************************************************************
36 * Returns the current date in milliseconds.
37 * On Win32, we implement a gettimeofday emulation here because
38 * libdvdread and libmp4v2 use it without checking.
39 ************************************************************************/
41 #ifdef SYS_CYGWIN
42 struct timezone
46 int gettimeofday( struct timeval * tv, struct timezone * tz )
48 int tick;
49 tick = GetTickCount();
50 tv->tv_sec = tick / 1000;
51 tv->tv_usec = ( tick % 1000 ) * 1000;
52 return 0;
54 #endif
57 uint64_t hb_get_date()
59 struct timeval tv;
60 gettimeofday( &tv, NULL );
61 return( (uint64_t) tv.tv_sec * 1000 + (uint64_t) tv.tv_usec / 1000 );
64 /************************************************************************
65 * hb_snooze()
66 ************************************************************************
67 * Waits <delay> milliseconds.
68 ************************************************************************/
69 void hb_snooze( int delay )
71 if( delay < 1 )
73 return;
75 #if defined( SYS_BEOS )
76 snooze( 1000 * delay );
77 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
78 usleep( 1000 * delay );
79 #elif defined( SYS_CYGWIN )
80 Sleep( delay );
81 #endif
84 /************************************************************************
85 * hb_get_cpu_count()
86 ************************************************************************
87 * Whenever possible, returns the number of CPUs on the current
88 * computer. Returns 1 otherwise.
89 * The detection is actually only performed on the first call.
90 ************************************************************************/
91 int hb_get_cpu_count()
93 static int cpu_count = 0;
95 if( cpu_count )
97 return cpu_count;
99 cpu_count = 1;
101 #if defined( SYS_BEOS )
103 system_info info;
104 get_system_info( &info );
105 cpu_count = info.cpu_count;
108 #elif defined( SYS_DARWIN ) || defined( SYS_FREEBSD )
109 FILE * info;
110 char buffer[16];
112 if( ( info = popen( "/usr/sbin/sysctl hw.ncpu", "r" ) ) )
114 memset( buffer, 0, 16 );
115 if( fgets( buffer, 15, info ) )
117 if( sscanf( buffer, "hw.ncpu: %d", &cpu_count ) != 1 )
119 cpu_count = 1;
122 fclose( info );
125 #elif defined( SYS_LINUX )
127 FILE * info;
128 char buffer[8];
130 if( ( info = popen( "grep -c '^processor' /proc/cpuinfo",
131 "r" ) ) )
133 memset( buffer, 0, 8 );
134 if( fgets( buffer, 7, info ) )
136 if( sscanf( buffer, "%d", &cpu_count ) != 1 )
138 cpu_count = 1;
141 fclose( info );
145 #elif defined( SYS_CYGWIN )
146 SYSTEM_INFO cpuinfo;
147 GetSystemInfo( &cpuinfo );
148 cpu_count = cpuinfo.dwNumberOfProcessors;
149 #endif
151 cpu_count = MAX( 1, cpu_count );
152 cpu_count = MIN( cpu_count, 8 );
154 return cpu_count;
157 /************************************************************************
158 * Get a tempory directory for HB
159 ***********************************************************************/
160 void hb_get_tempory_directory( hb_handle_t * h, char path[512] )
162 char base[512];
164 /* Create the base */
165 #ifdef SYS_CYGWIN
166 char *p;
167 int i_size = GetTempPath( 512, base );
168 if( i_size <= 0 || i_size >= 512 )
170 if( getcwd( base, 512 ) == NULL )
171 strcpy( base, "c:" ); /* Bad fallback but ... */
174 /* c:/path/ works like a charm under cygwin(win32?) so use it */
175 while( ( p = strchr( base, '\\' ) ) )
176 *p = '/';
177 #else
178 strcpy( base, "/tmp" );
179 #endif
180 /* I prefer to remove evntual last '/' (for cygwin) */
181 if( base[strlen(base)-1] == '/' )
182 base[strlen(base)-1] = '\0';
184 snprintf( path, 512, "%s/hb.%d", base, hb_get_pid( h ) );
187 /************************************************************************
188 * Get a tempory filename for HB
189 ***********************************************************************/
190 void hb_get_tempory_filename( hb_handle_t * h, char name[1024],
191 char *fmt, ... )
193 va_list args;
195 hb_get_tempory_directory( h, name );
196 strcat( name, "/" );
198 va_start( args, fmt );
199 vsnprintf( &name[strlen(name)], 1024 - strlen(name), fmt, args );
200 va_end( args );
203 /************************************************************************
204 * hb_mkdir
205 ************************************************************************
206 * Wrapper to the real mkdir, needed only because it doesn't take a
207 * second argument on Win32. Grrr.
208 ***********************************************************************/
209 void hb_mkdir( char * name )
211 //#ifdef SYS_CYGWIN
212 // mkdir( name );
213 //#else
214 mkdir( name, 0755 );
215 //#endif
218 /************************************************************************
219 * Portable thread implementation
220 ***********************************************************************/
221 struct hb_thread_s
223 char * name;
224 int priority;
225 void (* function) ( void * );
226 void * arg;
228 hb_lock_t * lock;
229 int exited;
231 #if defined( SYS_BEOS )
232 thread_id thread;
233 #elif USE_PTHREAD
234 pthread_t thread;
235 //#elif defined( SYS_CYGWIN )
236 // HANDLE thread;
237 #endif
240 /************************************************************************
241 * hb_thread_func()
242 ************************************************************************
243 * We use it as the root routine for any thread, for two reasons:
244 * + To set the thread priority on OS X (pthread_setschedparam() could
245 * be called from hb_thread_init(), but it's nicer to do it as we
246 * are sure it is done before the real routine starts)
247 * + Get informed when the thread exits, so we know whether
248 * hb_thread_close() will block or not.
249 ***********************************************************************/
250 static void hb_thread_func( void * _t )
252 hb_thread_t * t = (hb_thread_t *) _t;
254 #if defined( SYS_DARWIN )
255 /* Set the thread priority */
256 struct sched_param param;
257 memset( &param, 0, sizeof( struct sched_param ) );
258 param.sched_priority = t->priority;
259 pthread_setschedparam( pthread_self(), SCHED_OTHER, &param );
260 #endif
262 #if defined( SYS_BEOS )
263 signal( SIGINT, SIG_IGN );
264 #endif
266 /* Start the actual routine */
267 t->function( t->arg );
269 /* Inform that the thread can be joined now */
270 hb_log( "thread %d exited (\"%s\")", t->thread, t->name );
271 hb_lock( t->lock );
272 t->exited = 1;
273 hb_unlock( t->lock );
276 /************************************************************************
277 * hb_thread_init()
278 ************************************************************************
279 * name: user-friendly name
280 * function: the thread routine
281 * arg: argument of the routine
282 * priority: HB_LOW_PRIORITY or HB_NORMAL_PRIORITY
283 ***********************************************************************/
284 hb_thread_t * hb_thread_init( char * name, void (* function)(void *),
285 void * arg, int priority )
287 hb_thread_t * t = calloc( sizeof( hb_thread_t ), 1 );
289 t->name = strdup( name );
290 t->function = function;
291 t->arg = arg;
292 t->priority = priority;
294 t->lock = hb_lock_init();
296 /* Create and start the thread */
297 #if defined( SYS_BEOS )
298 t->thread = spawn_thread( (thread_func) hb_thread_func,
299 name, priority, t );
300 resume_thread( t->thread );
302 #elif USE_PTHREAD
303 pthread_create( &t->thread, NULL,
304 (void * (*)( void * )) hb_thread_func, t );
306 //#elif defined( SYS_CYGWIN )
307 // t->thread = CreateThread( NULL, 0,
308 // (LPTHREAD_START_ROUTINE) hb_thread_func, t, 0, NULL );
310 // /* Maybe use THREAD_PRIORITY_LOWEST instead */
311 // if( priority == HB_LOW_PRIORITY )
312 // SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL );
313 #endif
315 hb_log( "thread %d started (\"%s\")", t->thread, t->name );
316 return t;
319 /************************************************************************
320 * hb_thread_close()
321 ************************************************************************
322 * Joins the thread and frees memory.
323 ***********************************************************************/
324 void hb_thread_close( hb_thread_t ** _t )
326 hb_thread_t * t = *_t;
328 /* Join the thread */
329 #if defined( SYS_BEOS )
330 long exit_value;
331 wait_for_thread( t->thread, &exit_value );
333 #elif USE_PTHREAD
334 pthread_join( t->thread, NULL );
336 //#elif defined( SYS_CYGWIN )
337 // WaitForSingleObject( t->thread, INFINITE );
338 #endif
340 hb_log( "thread %d joined (\"%s\")",
341 t->thread, t->name );
343 hb_lock_close( &t->lock );
344 free( t->name );
345 free( t );
346 *_t = NULL;
349 /************************************************************************
350 * hb_thread_has_exited()
351 ************************************************************************
352 * Returns 1 if the thread can be joined right away, 0 otherwise.
353 ***********************************************************************/
354 int hb_thread_has_exited( hb_thread_t * t )
356 int exited;
358 hb_lock( t->lock );
359 exited = t->exited;
360 hb_unlock( t->lock );
362 return exited;
365 /************************************************************************
366 * Portable mutex implementation
367 ***********************************************************************/
368 struct hb_lock_s
370 #if defined( SYS_BEOS )
371 sem_id sem;
372 #elif USE_PTHREAD
373 pthread_mutex_t mutex;
374 //#elif defined( SYS_CYGWIN )
375 // HANDLE mutex;
376 #endif
379 /************************************************************************
380 * hb_lock_init()
381 * hb_lock_close()
382 * hb_lock()
383 * hb_unlock()
384 ************************************************************************
385 * Basic wrappers to OS-specific semaphore or mutex functions.
386 ***********************************************************************/
387 hb_lock_t * hb_lock_init()
389 hb_lock_t * l = calloc( sizeof( hb_lock_t ), 1 );
391 #if defined( SYS_BEOS )
392 l->sem = create_sem( 1, "sem" );
393 #elif USE_PTHREAD
394 pthread_mutex_init( &l->mutex, NULL );
395 //#elif defined( SYS_CYGWIN )
396 // l->mutex = CreateMutex( 0, FALSE, 0 );
397 #endif
399 return l;
402 void hb_lock_close( hb_lock_t ** _l )
404 hb_lock_t * l = *_l;
406 #if defined( SYS_BEOS )
407 delete_sem( l->sem );
408 #elif USE_PTHREAD
409 pthread_mutex_destroy( &l->mutex );
410 //#elif defined( SYS_CYGWIN )
411 // CloseHandle( l->mutex );
412 #endif
413 free( l );
415 *_l = NULL;
418 void hb_lock( hb_lock_t * l )
420 #if defined( SYS_BEOS )
421 acquire_sem( l->sem );
422 #elif USE_PTHREAD
423 pthread_mutex_lock( &l->mutex );
424 //#elif defined( SYS_CYGWIN )
425 // WaitForSingleObject( l->mutex, INFINITE );
426 #endif
429 void hb_unlock( hb_lock_t * l )
431 #if defined( SYS_BEOS )
432 release_sem( l->sem );
433 #elif USE_PTHREAD
434 pthread_mutex_unlock( &l->mutex );
435 //#elif defined( SYS_CYGWIN )
436 // ReleaseMutex( l->mutex );
437 #endif
440 /************************************************************************
441 * Portable condition variable implementation
442 ***********************************************************************/
443 struct hb_cond_s
445 #if defined( SYS_BEOS )
446 int thread;
447 #elif USE_PTHREAD
448 pthread_cond_t cond;
449 //#elif defined( SYS_CYGWIN )
450 // HANDLE event;
451 #endif
454 /************************************************************************
455 * hb_cond_init()
456 * hb_cond_close()
457 * hb_cond_wait()
458 * hb_cond_signal()
459 ************************************************************************
460 * Win9x is not supported by this implementation (SignalObjectAndWait()
461 * only available on Windows 2000/XP).
462 ***********************************************************************/
463 hb_cond_t * hb_cond_init()
465 hb_cond_t * c = calloc( sizeof( hb_cond_t ), 1 );
467 #if defined( SYS_BEOS )
468 c->thread = -1;
469 #elif USE_PTHREAD
470 pthread_cond_init( &c->cond, NULL );
471 //#elif defined( SYS_CYGWIN )
472 // c->event = CreateEvent( NULL, FALSE, FALSE, NULL );
473 #endif
475 return c;
478 void hb_cond_close( hb_cond_t ** _c )
480 hb_cond_t * c = *_c;
482 #if defined( SYS_BEOS )
483 #elif USE_PTHREAD
484 pthread_cond_destroy( &c->cond );
485 //#elif defined( SYS_CYGWIN )
486 // CloseHandle( c->event );
487 #endif
488 free( c );
490 *_c = NULL;
493 void hb_cond_wait( hb_cond_t * c, hb_lock_t * lock )
495 #if defined( SYS_BEOS )
496 c->thread = find_thread( NULL );
497 release_sem( lock->sem );
498 suspend_thread( c->thread );
499 acquire_sem( lock->sem );
500 c->thread = -1;
501 #elif USE_PTHREAD
502 pthread_cond_wait( &c->cond, &lock->mutex );
503 //#elif defined( SYS_CYGWIN )
504 // SignalObjectAndWait( lock->mutex, c->event, INFINITE, FALSE );
505 // WaitForSingleObject( lock->mutex, INFINITE );
506 #endif
509 void hb_cond_signal( hb_cond_t * c )
511 #if defined( SYS_BEOS )
512 while( c->thread != -1 )
514 thread_info info;
515 get_thread_info( c->thread, &info );
516 if( info.state == B_THREAD_SUSPENDED )
518 resume_thread( c->thread );
519 break;
521 /* Looks like we have been called between hb_cond_wait's
522 release_sem() and suspend_thread() lines. Wait until the
523 thread is actually suspended before we resume it */
524 snooze( 5000 );
526 #elif USE_PTHREAD
527 pthread_cond_signal( &c->cond );
528 //#elif defined( SYS_CYGWIN )
529 // PulseEvent( c->event );
530 #endif
533 /************************************************************************
534 * Network
535 ***********************************************************************/
537 struct hb_net_s
539 int socket;
542 hb_net_t * hb_net_open( char * address, int port )
544 hb_net_t * n = calloc( sizeof( hb_net_t ), 1 );
546 struct sockaddr_in sock;
547 struct hostent * host;
549 /* TODO: find out why this doesn't work on Win32 */
550 if( !( host = gethostbyname( address ) ) )
552 hb_log( "gethostbyname failed (%s)", address );
553 free( n );
554 return NULL;
557 memset( &sock, 0, sizeof( struct sockaddr_in ) );
558 sock.sin_family = host->h_addrtype;
559 sock.sin_port = htons( port );
560 memcpy( &sock.sin_addr, host->h_addr, host->h_length );
562 if( ( n->socket = socket( host->h_addrtype, SOCK_STREAM, 0 ) ) < 0 )
564 hb_log( "socket failed" );
565 free( n );
566 return NULL;
569 if( connect( n->socket, (struct sockaddr *) &sock,
570 sizeof( struct sockaddr_in ) ) < 0 )
572 hb_log( "connect failed" );
573 free( n );
574 return NULL;
577 return n;
580 int hb_net_send( hb_net_t * n, char * buffer )
582 return send( n->socket, buffer, strlen( buffer ), 0 );
585 int hb_net_recv( hb_net_t * n, char * buffer, int size )
587 return recv( n->socket, buffer, size - 1, 0 );
590 void hb_net_close( hb_net_t ** _n )
592 hb_net_t * n = (hb_net_t *) *_n;
593 close( n->socket );
594 free( n );
595 *_n = NULL;