static DFBResult system_initialize( CoreDFB *core, void **ret_data ) { DFBResult ret; AndroidData *android; AndroidDataShared *shared; FusionSHMPoolShared *pool; D_ASSERT( m_data == NULL ); android = D_CALLOC( 1, sizeof(AndroidData) ); if (!android) return D_OOM(); android->core = core; pool = dfb_core_shmpool( core ); shared = SHCALLOC( pool, 1, sizeof(AndroidDataShared) ); if (!shared) { D_FREE( android ); return D_OOSHM(); } shared->shmpool = pool; android->shared = shared; m_data = android; ret = InitLocal( android ); if (ret) return ret; *ret_data = m_data; dfb_surface_pool_initialize( core, &androidSurfacePoolFuncs, &shared->pool ); android->screen = dfb_screens_register( NULL, android, androidScreenFuncs ); android->layer = dfb_layers_register( android->screen, android, androidLayerFuncs ); android->java_vm = native_data.app->activity->vm; android->app_path = D_STRDUP( native_data.app->activity->internalDataPath) ; core_arena_add_shared_field( core, "android", shared ); return DFB_OK; }
void direct_thread_set_name( const char *name ) { char *copy; DirectThread *thread; D_DEBUG_AT( Direct_Thread, "%s( '%s' )\n", __FUNCTION__, name ); direct_once( &thread_init_once, init_once ); thread = pthread_getspecific( thread_key ); /* Support this function for non-direct threads. */ if (!thread) { D_DEBUG_AT( Direct_Thread, " -> attaching unknown thread %d\n", direct_gettid() ); thread = D_CALLOC( 1, sizeof(DirectThread) ); if (!thread) { D_OOM(); return; } thread->handle.thread = pthread_self(); thread->tid = direct_gettid(); D_MAGIC_SET( thread, DirectThread ); pthread_setspecific( thread_key, thread ); } else D_DEBUG_AT( Direct_Thread, " -> was '%s' (%d)\n", thread->name, direct_gettid() ); /* Duplicate string. */ copy = D_STRDUP( name ); if (!copy) { D_OOM(); return; } /* Free old string. */ if (thread->name) D_FREE( thread->name ); /* Keep the copy. */ thread->name = copy; }
static DirectResult join_pool( FusionSHM *shm, FusionSHMPool *pool, FusionSHMPoolShared *shared ) { DirectResult ret; FusionWorld *world; char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32]; D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared ); D_MAGIC_ASSERT( shm, FusionSHM ); D_MAGIC_ASSERT( shm->shared, FusionSHMShared ); D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); #if !DIRECT_BUILD_DEBUGS if (shared->debug) { D_ERROR( "Fusion/SHM: Can't join debug enabled pool with pure-release library!\n" ); return DR_UNSUPPORTED; } #endif world = shm->world; D_MAGIC_ASSERT( world, FusionWorld ); /* Generate filename. */ snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs, fusion_world_index( shm->world ), shared->pool_id ); /* Join the heap. */ ret = __shmalloc_join_heap( shm, buf, shared->addr_base, shared->max_size ); if (ret) return ret; /* Initialize local data. */ pool->attached = true; pool->shm = shm; pool->shared = shared; pool->pool_id = shared->pool_id; pool->filename = D_STRDUP( buf ); D_MAGIC_SET( pool, FusionSHMPool ); return DR_OK; }
static void config_allocate( void ) { if (fusiondale_config) return; fusiondale_config = D_CALLOC( 1, sizeof(FusionDaleConfig) ); fusiondale_config->session = 5; // FIXME!!! fusiondale_config->banner = true; fusiondale_config->coma_shmpool_size = 16 * 1024 * 1024; #if FUSIONDALE_USE_ONE fusiondale_config->remote.host = D_STRDUP( "%" ); #endif }
DirectResult fs_config_set( const char *name, const char *value ) { if (!strcmp( name, "driver" )) { if (value) { if (fs_config->driver) D_FREE( fs_config->driver ); fs_config->driver = D_STRDUP( value ); } else { D_ERROR( "FusionSound/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (!strcmp( name, "device" )) { if (value) { if (fs_config->device) D_FREE( fs_config->device ); fs_config->device = D_STRDUP( value ); } else { D_ERROR( "FusionSound/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (!strcmp( name, "channels" )) { if (value) { int channels; if (sscanf( value, "%d", &channels ) < 1) { D_ERROR( "FusionSound/Config '%s': Could not parse value!\n", name ); return DR_INVARG; } else if (channels < 1 || channels > FS_MAX_CHANNELS) { D_ERROR( "FusionSound/Config '%s': Unsupported value '%d'!\n", name, channels ); return DR_INVARG; } fs_config->channelmode = fs_mode_for_channels( channels ); } else { D_ERROR( "FusionSound/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (!strcmp( name, "channelmode" )) { if (value) { FSChannelMode mode; mode = parse_modestring( value ); if (mode == FSCM_UNKNOWN) { D_ERROR( "FusionSound/Config '%s': Could not parse value!\n", name ); return DR_INVARG; } fs_config->channelmode = mode; } else { D_ERROR( "FusionSound/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (!strcmp( name, "sampleformat" )) { if (value) { FSSampleFormat format; format = parse_sampleformat( value ); if (format == FSSF_UNKNOWN) { D_ERROR( "FusionSound/Config '%s': Could not parse value!\n", name ); return DR_INVARG; } fs_config->sampleformat = format; } else { D_ERROR( "FusionSound/Config '%s': No format specified!\n", name ); return DR_INVARG; } } else if (!strcmp( name, "samplerate" )) { if (value) { int rate; if (sscanf( value, "%d", &rate ) < 1) { D_ERROR( "FusionSound/Config 'samplerate': " "Could not parse value!\n" ); return DR_INVARG; } else if (rate < 1) { D_ERROR( "FusionSound/Config '%s': Unsupported value '%d'!\n", name, rate ); return DR_INVARG; } fs_config->samplerate = rate; } else { D_ERROR( "FusionSound/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (!strcmp( name, "buffertime" )) { if (value) { int time; if (sscanf( value, "%d", &time ) < 1) { D_ERROR( "FusionSound/Config 'buffertime': " "Could not parse value!\n" ); return DR_INVARG; } else if (time < 1 || time > 5000) { D_ERROR( "FusionSound/Config '%s': Unsupported value '%d'!\n", name, time ); return DR_INVARG; } fs_config->buffertime = time; } else { D_ERROR( "FusionSound/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (!strcmp( name, "session" )) { if (value) { int session; if (sscanf( value, "%d", &session ) < 1) { D_ERROR( "FusionSound/Config '%s': Could not parse value!\n", name ); return DR_INVARG; } fs_config->session = session; } else { D_ERROR( "FusionSound/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (!strcmp (name, "remote" )) { if (value) { char host[128]; int session = 0; if (sscanf( value, "%127s:%d", host, &session ) < 1) { D_ERROR( "FusionSound/Config '%s': " "Could not parse value (format is <host>[:<session>])!\n", name ); return DR_INVARG; } if (fs_config->remote.host) D_FREE( fs_config->remote.host ); fs_config->remote.host = D_STRDUP( host ); fs_config->remote.session = session; } else { D_ERROR( "FusionSound/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (!strcmp( name, "remote-compression" )) { if (value) { if (!strcasecmp( value, "none" )) { fs_config->remote_compression = FSRM_NONE; } else if (!strcasecmp( value, "dpack" )) { fs_config->remote_compression = FSRM_DPACK; } else { D_ERROR( "FusionSound/Config '%s': Unsupported value '%s'!\n", name, value ); return DR_INVARG; } } else { D_ERROR( "FusionSound/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (!strcmp( name, "banner" )) { fs_config->banner = true; } else if (!strcmp( name, "no-banner" )) { fs_config->banner = false; } else if (!strcmp( name, "wait" )) { fs_config->wait = true; } else if (!strcmp( name, "no-wait" )) { fs_config->wait = false; } else if (!strcmp( name, "deinit-check" )) { fs_config->deinit_check = true; } else if (!strcmp( name, "no-deinit-check" )) { fs_config->deinit_check = false; } else if (!strcmp( name, "dither" )) { fs_config->dither = true; } else if (!strcmp( name, "no-dither" )) { fs_config->dither = false; } else if (!strcmp( name, "dma" )) { fs_config->dma = true; } else if (!strcmp( name, "no-dma" )) { fs_config->dma = false; } else if (fusion_config_set( name, value ) && direct_config_set( name, value )) return DR_UNSUPPORTED; return DR_OK; }
static DirectResult init_pool( FusionSHM *shm, FusionSHMPool *pool, FusionSHMPoolShared *shared, const char *name, unsigned int max_size, bool debug ) { DirectResult ret; int size; long page_size; int pool_id; unsigned int pool_max_size; void *pool_addr_base = NULL; FusionWorld *world; char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32]; D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p, '%s', %d, %sdebug )\n", __FUNCTION__, shm, pool, shared, name, max_size, debug ? "" : "non-" ); D_MAGIC_ASSERT( shm, FusionSHM ); D_MAGIC_ASSERT( shm->shared, FusionSHMShared ); D_ASSERT( name != NULL ); D_ASSERT( max_size > sizeof(shmalloc_heap) ); world = shm->world; D_MAGIC_ASSERT( world, FusionWorld ); D_ASSERT( pool != NULL ); D_ASSERT( shared != NULL ); page_size = direct_pagesize(); pool_id = ++world->shared->pool_ids; pool_max_size = max_size + BLOCKALIGN(sizeof(shmalloc_heap)) + BLOCKALIGN( (max_size + BLOCKSIZE-1) / BLOCKSIZE * sizeof(shmalloc_info) ); pool_addr_base = world->shared->pool_base; world->shared->pool_base += ((pool_max_size + page_size - 1) & ~(page_size - 1)) + page_size; /* Exceeded limit? */ if (world->shared->pool_base > world->shared->pool_max) return DR_NOSHAREDMEMORY; /* Generate filename. */ snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs, fusion_world_index( world ), pool_id ); /* Initialize the heap. */ ret = __shmalloc_init_heap( shm, buf, pool_addr_base, max_size, &size ); if (ret) return ret; /* initialize local data. */ pool->attached = true; pool->shm = shm; pool->shared = shared; pool->pool_id = pool_id; pool->filename = D_STRDUP( buf ); /* Initialize shared data. */ shared->active = true; shared->debug = debug; shared->shm = shm->shared; shared->max_size = pool_max_size; shared->pool_id = pool_id; shared->addr_base = pool_addr_base; shared->heap = pool_addr_base; shared->heap->pool = shared; fusion_skirmish_init( &shared->lock, name, world ); D_MAGIC_SET( pool, FusionSHMPool ); D_MAGIC_SET( shared, FusionSHMPoolShared ); shared->name = SHSTRDUP( shared, name ); return DR_OK; }
static DirectResult init_pool( FusionSHM *shm, FusionSHMPool *pool, FusionSHMPoolShared *shared, const char *name, unsigned int max_size, bool debug ) { DirectResult ret; int size; FusionWorld *world; FusionSHMPoolNew pool_new = { .pool_id = 0 }; FusionSHMPoolAttach pool_attach = { .pool_id = 0 }; FusionEntryInfo info; char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32]; D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p, '%s', %d, %sdebug )\n", __FUNCTION__, shm, pool, shared, name, max_size, debug ? "" : "non-" ); D_MAGIC_ASSERT( shm, FusionSHM ); D_MAGIC_ASSERT( shm->shared, FusionSHMShared ); D_ASSERT( name != NULL ); D_ASSERT( max_size > sizeof(shmalloc_heap) ); world = shm->world; D_MAGIC_ASSERT( world, FusionWorld ); D_ASSERT( pool != NULL ); D_ASSERT( shared != NULL ); /* Fill out information for new pool. */ pool_new.max_size = max_size; pool_new.max_size += BLOCKALIGN(sizeof(shmalloc_heap)) + BLOCKALIGN( (max_size + BLOCKSIZE-1) / BLOCKSIZE * sizeof(shmalloc_info) ); /* Create the new pool. */ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_NEW, &pool_new )) { if (errno == EINTR) continue; D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_NEW failed!\n" ); return DR_FUSION; } /* Set the pool info. */ info.type = FT_SHMPOOL; info.id = pool_new.pool_id; snprintf( info.name, sizeof(info.name), "%s", name ); ioctl( world->fusion_fd, FUSION_ENTRY_SET_INFO, &info ); fusion_entry_add_permissions( world, FT_SHMPOOL, pool_new.pool_id, 0, FUSION_SHMPOOL_ATTACH, FUSION_SHMPOOL_DETACH, 0 ); /* Set pool to attach to. */ pool_attach.pool_id = pool_new.pool_id; /* Attach to the pool. */ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_ATTACH, &pool_attach )) { if (errno == EINTR) continue; D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_ATTACH failed!\n" ); while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) { if (errno != EINTR) { D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DESTROY failed!\n" ); break; } } return DR_FUSION; } /* Generate filename. */ snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs, fusion_world_index( shm->world ), pool_new.pool_id ); /* Initialize the heap. */ ret = __shmalloc_init_heap( shm, buf, pool_new.addr_base, max_size, &size ); if (ret) { while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) { if (errno != EINTR) { D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DESTROY failed!\n" ); break; } } return ret; } /* Initialize local data. */ pool->attached = true; pool->shm = shm; pool->shared = shared; pool->pool_id = pool_new.pool_id; pool->filename = D_STRDUP( buf ); /* Initialize shared data. */ shared->active = true; shared->debug = debug; shared->shm = shm->shared; shared->max_size = pool_new.max_size; shared->pool_id = pool_new.pool_id; shared->addr_base = pool_new.addr_base; shared->heap = pool_new.addr_base; shared->heap->pool = shared; fusion_skirmish_init2( &shared->lock, name, world, fusion_config->secure_fusion ); D_MAGIC_SET( pool, FusionSHMPool ); D_MAGIC_SET( shared, FusionSHMPoolShared ); shared->name = SHSTRDUP( shared, name ); return DR_OK; } static DirectResult join_pool( FusionSHM *shm, FusionSHMPool *pool, FusionSHMPoolShared *shared ) { DirectResult ret; FusionWorld *world; FusionSHMPoolAttach pool_attach = { .pool_id = 0 }; char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32]; D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared ); D_MAGIC_ASSERT( shm, FusionSHM ); D_MAGIC_ASSERT( shm->shared, FusionSHMShared ); D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); #if !DIRECT_BUILD_DEBUGS if (shared->debug) { D_ERROR( "Fusion/SHM: Can't join debug enabled pool with pure-release library!\n" ); return DR_UNSUPPORTED; } #endif world = shm->world; D_MAGIC_ASSERT( world, FusionWorld ); /* Set pool to attach to. */ pool_attach.pool_id = shared->pool_id; /* Attach to the pool. */ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_ATTACH, &pool_attach )) { if (errno == EINTR) continue; D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_ATTACH failed!\n" ); return DR_FUSION; } /* Generate filename. */ snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs, fusion_world_index( shm->world ), shared->pool_id ); /* Join the heap. */ ret = __shmalloc_join_heap( shm, buf, pool_attach.addr_base, shared->max_size, !fusion_config->secure_fusion ); if (ret) { while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DETACH, &shared->pool_id )) { if (errno != EINTR) { D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DETACH failed!\n" ); break; } } return ret; } /* Initialize local data. */ pool->attached = true; pool->shm = shm; pool->shared = shared; pool->pool_id = shared->pool_id; pool->filename = D_STRDUP( buf ); D_MAGIC_SET( pool, FusionSHMPool ); return DR_OK; } static void leave_pool( FusionSHM *shm, FusionSHMPool *pool, FusionSHMPoolShared *shared ) { FusionWorld *world; D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared ); D_MAGIC_ASSERT( shm, FusionSHM ); D_MAGIC_ASSERT( pool, FusionSHMPool ); D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); world = shm->world; D_MAGIC_ASSERT( world, FusionWorld ); while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DETACH, &shared->pool_id )) { if (errno != EINTR) { D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DETACH failed!\n" ); break; } } if (munmap( shared->addr_base, shared->max_size )) D_PERROR( "Fusion/SHM: Could not munmap shared memory file '%s'!\n", pool->filename ); pool->attached = false; D_FREE( pool->filename ); D_MAGIC_CLEAR( pool ); } static void shutdown_pool( FusionSHM *shm, FusionSHMPool *pool, FusionSHMPoolShared *shared ) { FusionWorld *world; D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared ); D_MAGIC_ASSERT( shm, FusionSHM ); D_MAGIC_ASSERT( pool, FusionSHMPool ); D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); world = shm->world; D_MAGIC_ASSERT( world, FusionWorld ); SHFREE( shared, shared->name ); fusion_dbg_print_memleaks( shared ); while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) { if (errno != EINTR) { D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DESTROY failed!\n" ); break; } } if (munmap( shared->addr_base, shared->max_size )) D_PERROR( "Fusion/SHM: Could not munmap shared memory file '%s'!\n", pool->filename ); if (unlink( pool->filename )) D_PERROR( "Fusion/SHM: Could not unlink shared memory file '%s'!\n", pool->filename ); shared->active = false; pool->attached = false; D_FREE( pool->filename ); D_MAGIC_CLEAR( pool ); fusion_skirmish_destroy( &shared->lock ); D_MAGIC_CLEAR( shared ); }
DirectThread * direct_thread_create( DirectThreadType thread_type, DirectThreadMainFunc thread_main, void *arg, const char *name ) { DirectThread *thread; pthread_attr_t attr; struct sched_param param; int policy; int priority; size_t stack_size; D_ASSERT( thread_main != NULL ); D_ASSERT( name != NULL ); D_DEBUG_AT( Direct_Thread, "%s( %s, %p(%p), '%s' )\n", __FUNCTION__, direct_thread_type_name(thread_type), thread_main, arg, name ); /* Create the key for the TSD (thread specific data). */ pthread_mutex_lock( &key_lock ); if (thread_key == -1) pthread_key_create( &thread_key, NULL ); pthread_mutex_unlock( &key_lock ); /* Allocate thread structure. */ thread = D_CALLOC( 1, sizeof(DirectThread) ); if (!thread) { D_OOM(); return NULL; } /* Write thread information to structure. */ thread->name = D_STRDUP( name ); thread->type = thread_type; thread->main = thread_main; thread->arg = arg; /* Initialize to -1 for synchronization. */ thread->thread = (pthread_t) -1; thread->tid = (pid_t) -1; /* Initialize mutex and condition. */ direct_util_recursive_pthread_mutex_init( &thread->lock ); pthread_cond_init( &thread->cond, NULL ); D_MAGIC_SET( thread, DirectThread ); /* Initialize scheduling and other parameters. */ pthread_attr_init( &attr ); pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ); /* Select scheduler. */ switch (direct_config->thread_scheduler) { case DCTS_FIFO: policy = SCHED_FIFO; break; case DCTS_RR: policy = SCHED_RR; break; default: policy = SCHED_OTHER; break; } if (pthread_attr_setschedpolicy( &attr, policy )) D_PERROR( "Direct/Thread: Could not set scheduling policy to %s!\n", direct_thread_policy_name(policy) ); /* Read (back) value. */ pthread_attr_getschedpolicy( &attr, &policy ); /* Select priority. */ switch (thread->type) { case DTT_CLEANUP: case DTT_INPUT: case DTT_OUTPUT: case DTT_MESSAGING: case DTT_CRITICAL: priority = thread->type * direct_config->thread_priority_scale / 100; break; default: priority = direct_config->thread_priority; break; } D_DEBUG_AT( Direct_ThreadInit, " -> %s (%d) [%d;%d]\n", direct_thread_policy_name(policy), priority, sched_get_priority_min( policy ), sched_get_priority_max( policy ) ); if (priority < sched_get_priority_min( policy )) priority = sched_get_priority_min( policy ); if (priority > sched_get_priority_max( policy )) priority = sched_get_priority_max( policy ); param.sched_priority = priority; if (pthread_attr_setschedparam( &attr, ¶m )) D_PERROR( "Direct/Thread: Could not set scheduling priority to %d!\n", priority ); /* Select stack size? */ if (direct_config->thread_stack_size > 0) { if (pthread_attr_setstacksize( &attr, direct_config->thread_stack_size )) D_PERROR( "Direct/Thread: Could not set stack size to %d!\n", direct_config->thread_stack_size ); } /* Read (back) value. */ pthread_attr_getstacksize( &attr, &stack_size ); /* Lock the thread mutex. */ D_DEBUG_AT( Direct_ThreadInit, " -> locking...\n" ); pthread_mutex_lock( &thread->lock ); /* Create and run the thread. */ D_DEBUG_AT( Direct_ThreadInit, " -> creating...\n" ); pthread_create( &thread->thread, &attr, direct_thread_main, thread ); pthread_attr_destroy( &attr ); pthread_getschedparam( thread->thread, &policy, ¶m ); D_INFO( "Direct/Thread: Started '%s' (%d) [%s %s/%s %d/%d] <%zu>...\n", name, thread->tid, direct_thread_type_name(thread_type), direct_thread_policy_name(policy), direct_thread_scheduler_name(direct_config->thread_scheduler), param.sched_priority, priority, stack_size ); #ifdef DIRECT_THREAD_WAIT_INIT /* Wait for completion of the thread's initialization. */ while (!thread->init) { D_DEBUG_AT( Direct_ThreadInit, " -> waiting...\n" ); pthread_cond_wait( &thread->cond, &thread->lock ); } D_DEBUG_AT( Direct_ThreadInit, " -> ...thread is running.\n" ); #endif /* Unlock the thread mutex. */ D_DEBUG_AT( Direct_ThreadInit, " -> unlocking...\n" ); pthread_mutex_unlock( &thread->lock ); D_DEBUG_AT( Direct_ThreadInit, " -> returning %p\n", thread ); return thread; }
DirectResult voodoo_client_create( const char *host, int port, VoodooClient **ret_client ) { DirectResult ret; VoodooPlayInfo info; VoodooClient *client; VoodooPlayer *player; char buf[100] = { 0 }; const char *hostname = host; bool raw = true; D_ASSERT( ret_client != NULL ); if (!host) host = ""; if (!port) port = 2323; D_DEBUG_AT( Voodoo_Client, "%s( '%s', %d )\n", __FUNCTION__, host, port ); if (port != 2323) { D_DEBUG_AT( Voodoo_Client, " -> port != 2323, using PACKET mode right away\n" ); raw = false; } direct_list_foreach (client, m_clients) { if (!strcmp( client->host, host ) && client->port == port) { D_INFO( "Voodoo/Client: Reconnecting to '%s', increasing ref count of existing connection!\n", host ); client->refs++; *ret_client = client; return DR_OK; } } /* * Get the player singleton */ ret = voodoo_player_create( NULL, &player ); if (ret) { D_DERROR( ret, "Voodoo/Client: Could not create the player!\n" ); return ret; } /* * If we got a hostname or address try to lookup the player info */ // FIXME: resolve first, not late in voodoo_link_init_connect if (hostname && hostname[0]) { ret = voodoo_player_lookup_by_address( player, hostname, &info ); if (ret == DR_OK) { if (info.flags & VPIF_PACKET) raw = false; } } else { /* * Start discovery and use first host visible */ ret = discover_host( player, NULL, &info, buf, sizeof(buf) ); if (ret == DR_OK) { if (info.flags & VPIF_PACKET) raw = false; hostname = buf; } } if (!hostname || !hostname[0]) { D_ERROR( "Voodoo/Client: Did not find any other player!\n" ); return DR_ITEMNOTFOUND; } /* Allocate client structure. */ client = D_CALLOC( 1, sizeof(VoodooClient) ); if (!client) return D_OOM(); raw = !voodoo_config->link_packet && (voodoo_config->link_raw || raw); /* Create a link to the other player. */ ret = voodoo_link_init_connect( &client->vl, hostname, port, raw ); if (ret) { D_DERROR( ret, "Voodoo/Client: Failed to initialize Voodoo Link!\n" ); D_FREE( client ); return ret; } D_INFO( "Voodoo/Client: Fetching player information...\n" ); if (raw) { // FIXME: send_discover_and_receive_info() only does RAW, but we don't need it for packet connection, yet VoodooPlayVersion version; VoodooPlayInfo info; ret = send_discover_and_receive_info( &client->vl, &version, &info ); if (ret) { D_DEBUG_AT( Voodoo_Client, " -> Failed to receive player info via TCP!\n" ); D_INFO( "Voodoo/Client: No player information from '%s', trying to discover via UDP!\n", host ); /* * Fallback to UDP discovery */ ret = discover_host( player, hostname, &info, buf, sizeof(buf) ); if (ret == DR_OK) { if (info.flags & VPIF_PACKET) raw = false; } } else { D_INFO( "Voodoo/Client: Connected to '%s' (%-15s) %s " "=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x= " "(vendor: %s, model: %s)\n", info.name, host, (info.flags & VPIF_LEVEL2) ? "*" : " ", info.uuid[0], info.uuid[1], info.uuid[2], info.uuid[3], info.uuid[4], info.uuid[5], info.uuid[6], info.uuid[7], info.uuid[8], info.uuid[9], info.uuid[10], info.uuid[11], info.uuid[12], info.uuid[13], info.uuid[14], info.uuid[15], info.vendor, info.model ); if (raw && !voodoo_config->link_raw) { /* * Switch to packet mode? */ if (info.flags & VPIF_PACKET) raw = false; } } /* * Switch to packet mode? */ if (!raw) { D_INFO( "Voodoo/Client: Switching to packet mode!\n" ); client->vl.Close( &client->vl ); /* Create another link to the other player. */ ret = voodoo_link_init_connect( &client->vl, hostname, port, false ); if (ret) { D_DERROR( ret, "Voodoo/Client: Failed to initialize second Voodoo Link!\n" ); D_FREE( client ); return ret; } } } /* Create the manager. */ ret = voodoo_manager_create( &client->vl, client, NULL, &client->manager ); if (ret) { client->vl.Close( &client->vl ); D_FREE( client ); return ret; } client->refs = 1; client->host = D_STRDUP( host ); client->port = port; direct_list_prepend( &m_clients, &client->link ); /* Return the new client. */ *ret_client = client; D_DEBUG_AT( Voodoo_Client, " => client %p\n", client ); return DR_OK; }
DirectResult fd_config_set( const char *name, const char *value ) { if (!strcmp( name, "session" )) { if (value) { int session; if (sscanf( value, "%d", &session ) < 1) { D_ERROR( "FusionDale/Config 'session': " "Could not parse value!\n"); return DR_INVARG; } fusiondale_config->session = session; if (fusiondale_config->remote.host) { D_FREE( fusiondale_config->remote.host ); fusiondale_config->remote.host = NULL; } } else { D_ERROR( "FusionDale/Config 'session': " "No value specified!\n" ); return DR_INVARG; } } else if (strcmp (name, "remote" ) == 0) { if (value) { char host[128]; int session = 0; if (sscanf( value, "%127s:%d", host, &session ) < 1) { D_ERROR("FusionDale/Config 'remote': " "Could not parse value (format is <host>[:<session>])!\n"); return DR_INVARG; } if (fusiondale_config->remote.host) D_FREE( fusiondale_config->remote.host ); fusiondale_config->remote.host = D_STRDUP( host ); fusiondale_config->remote.session = session; } else { fusiondale_config->remote.host = D_STRDUP( "" ); fusiondale_config->remote.session = 0; } } else if (!strcmp( name, "coma-shmpool-size" )) { if (value) { int size_kb; if (sscanf( value, "%d", &size_kb ) < 1) { D_ERROR( "FusionDale/Config '%s': Could not parse value!\n", name); return DR_INVARG; } fusiondale_config->coma_shmpool_size = size_kb * 1024; } else { D_ERROR( "FusionDale/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (!strcmp( name, "banner" )) { fusiondale_config->banner = true; } else if (!strcmp( name, "no-banner" )) { fusiondale_config->banner = false; } else if (strcmp ( name, "force-slave" ) == 0) { fusiondale_config->force_slave = true; } else if (strcmp ( name, "no-force-slave" ) == 0) { fusiondale_config->force_slave = false; } #if !DIRECTFB_BUILD_PURE_VOODOO else if (strcmp ( name, "coma-allow" ) == 0) { if (value) { coma_policy_config( value, true ); } else { fusiondale_config->coma_policy = true; } } else if (strcmp ( name, "coma-deny" ) == 0) { if (value) { coma_policy_config( value, false ); } else { fusiondale_config->coma_policy = false; } } else #endif if (fusion_config_set( name, value ) && direct_config_set( name, value )) return DR_UNSUPPORTED; return DR_OK; }
DirectResult fusion_config_set( const char *name, const char *value ) { if (strcmp (name, "tmpfs" ) == 0) { if (value) { if (fusion_config->tmpfs) D_FREE( fusion_config->tmpfs ); fusion_config->tmpfs = D_STRDUP( value ); } else { D_ERROR("Fusion/Config 'tmpfs': No directory specified!\n"); return DR_INVARG; } } else if (strcmp (name, "shmfile-group" ) == 0) { if (value) { struct group *group_info; group_info = getgrnam( value ); if (group_info) fusion_config->shmfile_gid = group_info->gr_gid; else D_PERROR("Fusion/Config 'shmfile-group': Group '%s' not found!\n", value); } else { D_ERROR("Fusion/Config 'shmfile-group': No file group name specified!\n"); return DR_INVARG; } } else if (strcmp (name, "force-slave" ) == 0) { fusion_config->force_slave = true; } else if (strcmp (name, "no-force-slave" ) == 0) { fusion_config->force_slave = false; } else if (strcmp (name, "debugshm" ) == 0) { fusion_config->debugshm = true; } else if (strcmp (name, "no-debugshm" ) == 0) { fusion_config->debugshm = false; } else if (strcmp (name, "madv-remove" ) == 0) { fusion_config->madv_remove = true; fusion_config->madv_remove_force = true; } else if (strcmp (name, "no-madv-remove" ) == 0) { fusion_config->madv_remove = false; fusion_config->madv_remove_force = true; } else if (strcmp (name, "secure-fusion" ) == 0) { fusion_config->secure_fusion = true; } else if (strcmp (name, "no-secure-fusion" ) == 0) { fusion_config->secure_fusion = false; } else if (strcmp (name, "trace-ref" ) == 0) { if (value) { if (sscanf( value, "%x", &fusion_config->trace_ref ) != 1) { D_ERROR( "Fusion/Config '%s': Invalid value!\n", name ); return DR_INVARG; } } else { D_ERROR( "Fusion/Config '%s': No ID specified!\n", name ); return DR_INVARG; } } else if (direct_config_set( name, value )) return DR_UNSUPPORTED; return DR_OK; }
DirectResult voodoo_config_set( const char *name, const char *value ) { if (strcmp (name, "player-name" ) == 0) { if (value) { direct_snputs( voodoo_config->play_info.name, value, VOODOO_PLAYER_NAME_LENGTH ); } else { D_ERROR( "Voodoo/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (strcmp (name, "player-vendor" ) == 0) { if (value) { direct_snputs( voodoo_config->play_info.vendor, value, VOODOO_PLAYER_VENDOR_LENGTH ); } else { D_ERROR( "Voodoo/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (strcmp (name, "player-model" ) == 0) { if (value) { direct_snputs( voodoo_config->play_info.model, value, VOODOO_PLAYER_MODEL_LENGTH ); } else { D_ERROR( "Voodoo/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (strcmp (name, "player-uuid" ) == 0) { if (value) { sscanf( value, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", (unsigned int*)&voodoo_config->play_info.uuid[0], (unsigned int*)&voodoo_config->play_info.uuid[1], (unsigned int*)&voodoo_config->play_info.uuid[2], (unsigned int*)&voodoo_config->play_info.uuid[3], (unsigned int*)&voodoo_config->play_info.uuid[4], (unsigned int*)&voodoo_config->play_info.uuid[5], (unsigned int*)&voodoo_config->play_info.uuid[6], (unsigned int*)&voodoo_config->play_info.uuid[7], (unsigned int*)&voodoo_config->play_info.uuid[8], (unsigned int*)&voodoo_config->play_info.uuid[9], (unsigned int*)&voodoo_config->play_info.uuid[10], (unsigned int*)&voodoo_config->play_info.uuid[11], (unsigned int*)&voodoo_config->play_info.uuid[12], (unsigned int*)&voodoo_config->play_info.uuid[13], (unsigned int*)&voodoo_config->play_info.uuid[14], (unsigned int*)&voodoo_config->play_info.uuid[15] ); } else { D_ERROR( "Voodoo/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (strcmp (name, "proxy-memory-max" ) == 0) { if (value) { unsigned int max; if (direct_sscanf( value, "%u", &max ) != 1) { D_ERROR( "Voodoo/Config '%s': Invalid value specified!\n", name ); return DR_INVARG; } voodoo_config->memory_max = max * 1024; } else { D_ERROR( "Voodoo/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (strcmp (name, "proxy-surface-max" ) == 0) { if (value) { unsigned int max; if (direct_sscanf( value, "%u", &max ) != 1) { D_ERROR( "Voodoo/Config '%s': Invalid value specified!\n", name ); return DR_INVARG; } voodoo_config->surface_max = max * 1024; } else { D_ERROR( "Voodoo/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (strcmp (name, "proxy-layer-mask" ) == 0) { if (value) { unsigned int mask; if (direct_sscanf( value, "%u", &mask ) != 1) { D_ERROR( "Voodoo/Config '%s': Invalid value specified!\n", name ); return DR_INVARG; } voodoo_config->layer_mask = mask; } else { D_ERROR( "Voodoo/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (strcmp (name, "proxy-stacking-mask" ) == 0) { if (value) { unsigned int mask; if (direct_sscanf( value, "%u", &mask ) != 1) { D_ERROR( "Voodoo/Config '%s': Invalid value specified!\n", name ); return DR_INVARG; } voodoo_config->stacking_mask = mask; } else { D_ERROR( "Voodoo/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (strcmp (name, "proxy-resource-id" ) == 0) { if (value) { unsigned int resource_id; if (direct_sscanf( value, "%u", &resource_id ) != 1) { D_ERROR( "Voodoo/Config '%s': Invalid value specified!\n", name ); return DR_INVARG; } voodoo_config->resource_id = resource_id; } else { D_ERROR( "Voodoo/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (strcmp (name, "server-fork" ) == 0) { voodoo_config->server_fork = true; } else if (strcmp (name, "no-server-fork" ) == 0) { voodoo_config->server_fork = false; } else if (strcmp (name, "server-single" ) == 0) { if (value) { if (voodoo_config->server_single) D_FREE( voodoo_config->server_single ); voodoo_config->server_single = D_STRDUP( value ); if (!voodoo_config->server_single) D_OOM(); } else { D_ERROR( "Voodoo/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (strcmp (name, "play-broadcast" ) == 0) { if (value) { if (voodoo_config->play_broadcast) D_FREE( voodoo_config->play_broadcast ); voodoo_config->play_broadcast = D_STRDUP( value ); if (!voodoo_config->play_broadcast) D_OOM(); } else { D_ERROR( "Voodoo/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (strcmp (name, "compression-min" ) == 0) { if (value) { unsigned int min; if (direct_sscanf( value, "%u", &min ) != 1) { D_ERROR( "Voodoo/Config '%s': Invalid value specified!\n", name ); return DR_INVARG; } voodoo_config->compression_min = min; } else { D_ERROR( "Voodoo/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (strcmp (name, "link-raw" ) == 0) { voodoo_config->link_raw = true; } else if (strcmp (name, "no-link-raw" ) == 0) { voodoo_config->link_raw = false; } else if (strcmp (name, "link-packet" ) == 0) { voodoo_config->link_packet = true; } else if (strcmp (name, "no-link-packet" ) == 0) { voodoo_config->link_packet = false; } else return DR_UNSUPPORTED; return DR_OK; }
DirectResult direct_config_set( const char *name, const char *value ) { if (direct_strcmp (name, "disable-module" ) == 0) { if (value) { int n = 0; while (direct_config->disable_module && direct_config->disable_module[n]) n++; direct_config->disable_module = (char**) D_REALLOC( direct_config->disable_module, sizeof(char*) * (n + 2) ); direct_config->disable_module[n] = D_STRDUP( value ); direct_config->disable_module[n+1] = NULL; } else { D_ERROR("Direct/Config '%s': No module name specified!\n", name); return DR_INVARG; } } else if (direct_strcmp (name, "module-dir" ) == 0) { if (value) { if (direct_config->module_dir) D_FREE( direct_config->module_dir ); direct_config->module_dir = D_STRDUP( value ); } else { D_ERROR("Direct/Config 'module-dir': No directory name specified!\n"); return DR_INVARG; } } else if (direct_strcmp (name, "memcpy" ) == 0) { if (value) { if (direct_config->memcpy) D_FREE( direct_config->memcpy ); direct_config->memcpy = D_STRDUP( value ); } else { D_ERROR("Direct/Config '%s': No method specified!\n", name); return DR_INVARG; } } else if (direct_strcmp (name, "quiet" ) == 0 || strcmp (name, "no-quiet" ) == 0) { /* Enable/disable all at once by default. */ DirectMessageType type = DMT_ALL; /* Find out the specific message type being configured. */ if (value) { if (!strcmp( value, "info" )) type = DMT_INFO; else if (!strcmp( value, "warning" )) type = DMT_WARNING; else if (!strcmp( value, "error" )) type = DMT_ERROR; else if (!strcmp( value, "once" )) type = DMT_ONCE; else if (!strcmp( value, "untested" )) type = DMT_UNTESTED; else if (!strcmp( value, "unimplemented" )) type = DMT_UNIMPLEMENTED; else { D_ERROR( "DirectFB/Config '%s': Unknown message type '%s'!\n", name, value ); return DR_INVARG; } } /* Set/clear the corresponding flag in the configuration. */ if (name[0] == 'q') D_FLAGS_SET( direct_config->quiet, type ); else D_FLAGS_CLEAR( direct_config->quiet, type ); } else if (direct_strcmp (name, "no-quiet" ) == 0) { direct_config->quiet = DMT_NONE; } else if (direct_strcmp (name, "debug" ) == 0) { if (value) { DirectLogDomainConfig config = {0}; if (value[0] && value[1] == ':') { config.level = value[0] - '0' + DIRECT_LOG_DEBUG_0; value += 2; } else config.level = DIRECT_LOG_DEBUG; direct_log_domain_configure( value, &config ); } else if (direct_config->log_level < DIRECT_LOG_DEBUG) direct_config->log_level = DIRECT_LOG_DEBUG; } else if (direct_strcmp (name, "no-debug" ) == 0) { if (value) { DirectLogDomainConfig config = {0}; config.level = DIRECT_LOG_DEBUG_0; direct_log_domain_configure( value, &config ); } else if (direct_config->log_level > DIRECT_LOG_DEBUG_0) direct_config->log_level = DIRECT_LOG_DEBUG_0; } else if (direct_strcmp (name, "log-all" ) == 0) { direct_config->log_all = true; } else if (direct_strcmp (name, "log-none" ) == 0) { direct_config->log_none = true; } else if (direct_strcmp (name, "debugmem" ) == 0) { direct_config->debugmem = true; } else if (direct_strcmp (name, "no-debugmem" ) == 0) { direct_config->debugmem = false; } else if (direct_strcmp (name, "trace" ) == 0) { direct_config->trace = true; } else if (direct_strcmp (name, "no-trace" ) == 0) { direct_config->trace = false; } else if (direct_strcmp (name, "log-file" ) == 0 || strcmp (name, "log-udp" ) == 0) { if (value) { DirectResult ret; DirectLog *log; ret = direct_log_create( strcmp(name,"log-udp") ? DLT_FILE : DLT_UDP, value, &log ); if (ret) return ret; if (direct_config->log) direct_log_destroy( direct_config->log ); direct_config->log = log; direct_log_set_default( log ); } else { if (direct_strcmp(name,"log-udp")) D_ERROR("Direct/Config '%s': No file name specified!\n", name); else D_ERROR("Direct/Config '%s': No host and port specified!\n", name); return DR_INVARG; } } else if (direct_strcmp (name, "fatal-level" ) == 0) { if (direct_strcasecmp (value, "none" ) == 0) { direct_config->fatal = DCFL_NONE; } else if (direct_strcasecmp (value, "assert" ) == 0) { direct_config->fatal = DCFL_ASSERT; } else if (direct_strcasecmp (value, "assume" ) == 0) { direct_config->fatal = DCFL_ASSUME; } else { D_ERROR("Direct/Config '%s': Unknown level specified (use 'none', 'assert', 'assume')!\n", name); return DR_INVARG; } } else if (direct_strcmp (name, "fatal-break" ) == 0) { direct_config->fatal_break = true; } else if (direct_strcmp (name, "no-fatal-break" ) == 0) { direct_config->fatal_break = false; } else if (direct_strcmp (name, "sighandler" ) == 0) { direct_config->sighandler = true; } else if (direct_strcmp (name, "no-sighandler" ) == 0) { direct_config->sighandler = false; } else if (direct_strcmp (name, "dont-catch" ) == 0) { if (value) { char *signals = D_STRDUP( value ); char *p = NULL, *r, *s = signals; while ((r = direct_strtok_r( s, ",", &p ))) { char *error; unsigned long signum; direct_trim( &r ); signum = direct_strtoul( r, &error, 10 ); if (*error) { D_ERROR( "Direct/Config '%s': Error in number at '%s'!\n", name, error ); D_FREE( signals ); return DR_INVARG; } sigaddset( &direct_config->dont_catch, signum ); s = NULL; } D_FREE( signals ); } else { D_ERROR("Direct/Config '%s': No signals specified!\n", name); return DR_INVARG; } } else if (direct_strcmp (name, "thread_block_signals") == 0) { direct_config->thread_block_signals = true; } else if (direct_strcmp (name, "no-thread_block_signals") == 0) { direct_config->thread_block_signals = false; } else if (direct_strcmp (name, "thread-priority-scale" ) == 0) { if (value) { int scale; if (direct_sscanf( value, "%d", &scale ) < 1) { D_ERROR("Direct/Config '%s': Could not parse value!\n", name); return DR_INVARG; } direct_config->thread_priority_scale = scale; } else { D_ERROR("Direct/Config '%s': No value specified!\n", name); return DR_INVARG; } } else if (direct_strcmp (name, "thread-priority" ) == 0) { /* Must be moved to lib/direct/conf.c in trunk! */ if (value) { int priority; if (direct_sscanf( value, "%d", &priority ) < 1) { D_ERROR("Direct/Config '%s': Could not parse value!\n", name); return DR_INVARG; } direct_config->thread_priority = priority; } else { D_ERROR("Direct/Config '%s': No value specified!\n", name); return DR_INVARG; } } else if (direct_strcmp (name, "thread-scheduler" ) == 0) { /* Must be moved to lib/direct/conf.c in trunk! */ if (value) { if (direct_strcmp( value, "other" ) == 0) { direct_config->thread_scheduler = DCTS_OTHER; } else if (direct_strcmp( value, "fifo" ) == 0) { direct_config->thread_scheduler = DCTS_FIFO; } else if (direct_strcmp( value, "rr" ) == 0) { direct_config->thread_scheduler = DCTS_RR; } else { D_ERROR( "Direct/Config '%s': Unknown scheduler '%s'!\n", name, value ); return DR_INVARG; } } else { D_ERROR( "Direct/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else if (direct_strcmp (name, "thread-stacksize" ) == 0) { /* Must be moved to lib/direct/conf.c in trunk! */ if (value) { int size; if (direct_sscanf( value, "%d", &size ) < 1) { D_ERROR( "Direct/Config '%s': Could not parse value!\n", name ); return DR_INVARG; } direct_config->thread_stack_size = size; } else { D_ERROR( "Direct/Config '%s': No value specified!\n", name ); return DR_INVARG; } } else return DR_UNSUPPORTED; return DR_OK; }