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. */
10 #if defined( SYS_BEOS )
13 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
15 #elif defined( SYS_CYGWIN )
23 #include <sys/types.h>
24 #include <sys/socket.h>
26 #include <netinet/in.h>
31 /************************************************************************
33 ************************************************************************
34 * Returns the current date in milliseconds.
35 * On Win32, we implement a gettimeofday emulation here because
36 * libdvdread and libmp4v2 use it without checking.
37 ************************************************************************/
43 int gettimeofday( struct timeval * tv, struct timezone * tz )
46 tick = GetTickCount();
47 tv->tv_sec = tick / 1000;
48 tv->tv_usec = ( tick % 1000 ) * 1000;
53 uint64_t hb_get_date()
56 gettimeofday( &tv, NULL );
57 return( (uint64_t) tv.tv_sec * 1000 + (uint64_t) tv.tv_usec / 1000 );
60 /************************************************************************
62 ************************************************************************
63 * Waits <delay> milliseconds.
64 ************************************************************************/
65 void hb_snooze( int delay )
71 #if defined( SYS_BEOS )
72 snooze( 1000 * delay );
73 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
74 usleep( 1000 * delay );
75 #elif defined( SYS_CYGWIN )
80 /************************************************************************
82 ************************************************************************
83 * Whenever possible, returns the number of CPUs on the current
84 * computer. Returns 1 otherwise.
85 * The detection is actually only performed on the first call.
86 ************************************************************************/
87 int hb_get_cpu_count()
89 static int cpu_count = 0;
97 #if defined( SYS_BEOS )
100 get_system_info( &info );
101 cpu_count = info.cpu_count;
104 #elif defined( SYS_DARWIN ) || defined( SYS_FREEBSD )
108 if( ( info = popen( "/usr/sbin/sysctl hw.ncpu", "r" ) ) )
110 memset( buffer, 0, 16 );
111 if( fgets( buffer, 15, info ) )
113 if( sscanf( buffer, "hw.ncpu: %d", &cpu_count ) != 1 )
121 #elif defined( SYS_LINUX )
126 if( ( info = popen( "grep -c '^processor' /proc/cpuinfo",
129 memset( buffer, 0, 8 );
130 if( fgets( buffer, 7, info ) )
132 if( sscanf( buffer, "%d", &cpu_count ) != 1 )
141 #elif defined( SYS_CYGWIN )
143 GetSystemInfo( &cpuinfo );
144 cpu_count = cpuinfo.dwNumberOfProcessors;
147 cpu_count = MAX( 1, cpu_count );
148 cpu_count = MIN( cpu_count, 8 );
153 /************************************************************************
154 * Get a tempory directory for HB
155 ***********************************************************************/
156 void hb_get_tempory_directory( hb_handle_t * h, char path[512] )
160 /* Create the base */
163 int i_size = GetTempPath( 512, base );
164 if( i_size <= 0 || i_size >= 512 )
166 if( getcwd( base, 512 ) == NULL )
167 strcpy( base, "c:" ); /* Bad fallback but ... */
170 /* c:/path/ works like a charm under cygwin(win32?) so use it */
171 while( ( p = strchr( base, '\\' ) ) )
174 strcpy( base, "/tmp" );
176 /* I prefer to remove evntual last '/' (for cygwin) */
177 if( base[strlen(base)-1] == '/' )
178 base[strlen(base)-1] = '\0';
180 snprintf( path, 512, "%s/hb.%d", base, hb_get_pid( h ) );
183 /************************************************************************
184 * Get a tempory filename for HB
185 ***********************************************************************/
186 void hb_get_tempory_filename( hb_handle_t * h, char name[1024],
191 hb_get_tempory_directory( h, name );
194 va_start( args, fmt );
195 vsnprintf( &name[strlen(name)], 1024 - strlen(name), fmt, args );
199 /************************************************************************
201 ************************************************************************
202 * Wrapper to the real mkdir, needed only because it doesn't take a
203 * second argument on Win32. Grrr.
204 ***********************************************************************/
205 void hb_mkdir( char * name )
214 /************************************************************************
215 * Portable thread implementation
216 ***********************************************************************/
221 void (* function) ( void * );
227 #if defined( SYS_BEOS )
229 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
231 #elif defined( SYS_CYGWIN )
236 /************************************************************************
238 ************************************************************************
239 * We use it as the root routine for any thread, for two reasons:
240 * + To set the thread priority on OS X (pthread_setschedparam() could
241 * be called from hb_thread_init(), but it's nicer to do it as we
242 * are sure it is done before the real routine starts)
243 * + Get informed when the thread exits, so we know whether
244 * hb_thread_close() will block or not.
245 ***********************************************************************/
246 static void hb_thread_func( void * _t )
248 hb_thread_t * t = (hb_thread_t *) _t;
250 #if defined( SYS_DARWIN )
251 /* Set the thread priority */
252 struct sched_param param;
253 memset( ¶m, 0, sizeof( struct sched_param ) );
254 param.sched_priority = t->priority;
255 pthread_setschedparam( pthread_self(), SCHED_OTHER, ¶m );
258 #if defined( SYS_BEOS )
259 signal( SIGINT, SIG_IGN );
262 /* Start the actual routine */
263 t->function( t->arg );
265 /* Inform that the thread can be joined now */
266 hb_log( "thread %d exited (\"%s\")", t->thread, t->name );
269 hb_unlock( t->lock );
272 /************************************************************************
274 ************************************************************************
275 * name: user-friendly name
276 * function: the thread routine
277 * arg: argument of the routine
278 * priority: HB_LOW_PRIORITY or HB_NORMAL_PRIORITY
279 ***********************************************************************/
280 hb_thread_t * hb_thread_init( char * name, void (* function)(void *),
281 void * arg, int priority )
283 hb_thread_t * t = calloc( sizeof( hb_thread_t ), 1 );
285 t->name = strdup( name );
286 t->function = function;
288 t->priority = priority;
290 t->lock = hb_lock_init();
292 /* Create and start the thread */
293 #if defined( SYS_BEOS )
294 t->thread = spawn_thread( (thread_func) hb_thread_func,
296 resume_thread( t->thread );
298 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
299 pthread_create( &t->thread, NULL,
300 (void * (*)( void * )) hb_thread_func, t );
302 #elif defined( SYS_CYGWIN )
303 t->thread = CreateThread( NULL, 0,
304 (LPTHREAD_START_ROUTINE) hb_thread_func, t, 0, NULL );
306 /* Maybe use THREAD_PRIORITY_LOWEST instead */
307 if( priority == HB_LOW_PRIORITY )
308 SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL );
311 hb_log( "thread %d started (\"%s\")", t->thread, t->name );
315 /************************************************************************
317 ************************************************************************
318 * Joins the thread and frees memory.
319 ***********************************************************************/
320 void hb_thread_close( hb_thread_t ** _t )
322 hb_thread_t * t = *_t;
324 /* Join the thread */
325 #if defined( SYS_BEOS )
327 wait_for_thread( t->thread, &exit_value );
329 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
330 pthread_join( t->thread, NULL );
332 #elif defined( SYS_CYGWIN )
333 WaitForSingleObject( t->thread, INFINITE );
336 hb_log( "thread %d joined (\"%s\")",
337 t->thread, t->name );
339 hb_lock_close( &t->lock );
345 /************************************************************************
346 * hb_thread_has_exited()
347 ************************************************************************
348 * Returns 1 if the thread can be joined right away, 0 otherwise.
349 ***********************************************************************/
350 int hb_thread_has_exited( hb_thread_t * t )
356 hb_unlock( t->lock );
361 /************************************************************************
362 * Portable mutex implementation
363 ***********************************************************************/
366 #if defined( SYS_BEOS )
368 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
369 pthread_mutex_t mutex;
370 #elif defined( SYS_CYGWIN )
375 /************************************************************************
380 ************************************************************************
381 * Basic wrappers to OS-specific semaphore or mutex functions.
382 ***********************************************************************/
383 hb_lock_t * hb_lock_init()
385 hb_lock_t * l = calloc( sizeof( hb_lock_t ), 1 );
387 #if defined( SYS_BEOS )
388 l->sem = create_sem( 1, "sem" );
389 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
390 pthread_mutex_init( &l->mutex, NULL );
391 #elif defined( SYS_CYGWIN )
392 l->mutex = CreateMutex( 0, FALSE, 0 );
398 void hb_lock_close( hb_lock_t ** _l )
402 #if defined( SYS_BEOS )
403 delete_sem( l->sem );
404 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
405 pthread_mutex_destroy( &l->mutex );
406 #elif defined( SYS_CYGWIN )
407 CloseHandle( l->mutex );
414 void hb_lock( hb_lock_t * l )
416 #if defined( SYS_BEOS )
417 acquire_sem( l->sem );
418 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
419 pthread_mutex_lock( &l->mutex );
420 #elif defined( SYS_CYGWIN )
421 WaitForSingleObject( l->mutex, INFINITE );
425 void hb_unlock( hb_lock_t * l )
427 #if defined( SYS_BEOS )
428 release_sem( l->sem );
429 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
430 pthread_mutex_unlock( &l->mutex );
431 #elif defined( SYS_CYGWIN )
432 ReleaseMutex( l->mutex );
436 /************************************************************************
437 * Portable condition variable implementation
438 ***********************************************************************/
441 #if defined( SYS_BEOS )
443 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
445 #elif defined( SYS_CYGWIN )
450 /************************************************************************
455 ************************************************************************
456 * Win9x is not supported by this implementation (SignalObjectAndWait()
457 * only available on Windows 2000/XP).
458 ***********************************************************************/
459 hb_cond_t * hb_cond_init()
461 hb_cond_t * c = calloc( sizeof( hb_cond_t ), 1 );
463 #if defined( SYS_BEOS )
465 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
466 pthread_cond_init( &c->cond, NULL );
467 #elif defined( SYS_CYGWIN )
468 c->event = CreateEvent( NULL, FALSE, FALSE, NULL );
474 void hb_cond_close( hb_cond_t ** _c )
478 #if defined( SYS_BEOS )
479 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
480 pthread_cond_destroy( &c->cond );
481 #elif defined( SYS_CYGWIN )
482 CloseHandle( c->event );
489 void hb_cond_wait( hb_cond_t * c, hb_lock_t * lock )
491 #if defined( SYS_BEOS )
492 c->thread = find_thread( NULL );
493 release_sem( lock->sem );
494 suspend_thread( c->thread );
495 acquire_sem( lock->sem );
497 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
498 pthread_cond_wait( &c->cond, &lock->mutex );
499 #elif defined( SYS_CYGWIN )
500 SignalObjectAndWait( lock->mutex, c->event, INFINITE, FALSE );
501 WaitForSingleObject( lock->mutex, INFINITE );
505 void hb_cond_signal( hb_cond_t * c )
507 #if defined( SYS_BEOS )
508 while( c->thread != -1 )
511 get_thread_info( c->thread, &info );
512 if( info.state == B_THREAD_SUSPENDED )
514 resume_thread( c->thread );
517 /* Looks like we have been called between hb_cond_wait's
518 release_sem() and suspend_thread() lines. Wait until the
519 thread is actually suspended before we resume it */
522 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD )
523 pthread_cond_signal( &c->cond );
524 #elif defined( SYS_CYGWIN )
525 PulseEvent( c->event );
529 /************************************************************************
531 ***********************************************************************/
538 hb_net_t * hb_net_open( char * address, int port )
540 hb_net_t * n = calloc( sizeof( hb_net_t ), 1 );
542 struct sockaddr_in sock;
543 struct hostent * host;
545 /* TODO: find out why this doesn't work on Win32 */
546 if( !( host = gethostbyname( address ) ) )
548 hb_log( "gethostbyname failed (%s)", address );
553 memset( &sock, 0, sizeof( struct sockaddr_in ) );
554 sock.sin_family = host->h_addrtype;
555 sock.sin_port = htons( port );
556 memcpy( &sock.sin_addr, host->h_addr, host->h_length );
558 if( ( n->socket = socket( host->h_addrtype, SOCK_STREAM, 0 ) ) < 0 )
560 hb_log( "socket failed" );
565 if( connect( n->socket, (struct sockaddr *) &sock,
566 sizeof( struct sockaddr_in ) ) < 0 )
568 hb_log( "connect failed" );
576 int hb_net_send( hb_net_t * n, char * buffer )
578 return send( n->socket, buffer, strlen( buffer ), 0 );
581 int hb_net_recv( hb_net_t * n, char * buffer, int size )
583 return recv( n->socket, buffer, size - 1, 0 );
586 void hb_net_close( hb_net_t ** _n )
588 hb_net_t * n = (hb_net_t *) *_n;