/* Initializes the XInput haptic system. */ static bool hapxi_init_haptic(void) { int i; ASSERT(hapxi_mutex == NULL); ASSERT(hapxi_thread == NULL); ASSERT(hapxi_cond == NULL); /* Create the mutex and a condition vaiable. */ hapxi_mutex = al_create_mutex_recursive(); if (!hapxi_mutex) return false; hapxi_cond = al_create_cond(); if (!hapxi_cond) return false; al_lock_mutex(hapxi_mutex); for (i = 0; i < HAPTICS_MAX; i++) { haptics[i].active = false; } /* Now start a polling background thread, since XInput is a polled API, and also to make it possible for effects to stop running when their duration has passed. */ hapxi_thread = al_create_thread(hapxi_poll_thread, NULL); al_unlock_mutex(hapxi_mutex); if (hapxi_thread) al_start_thread(hapxi_thread); return(hapxi_thread != NULL); }
ALLEGRO_COND * create_cond (void) { ALLEGRO_COND *cond = al_create_cond (); if (! cond) error (-1, 0, "%s (void): failed to create condition variable", __func__); return cond; }
/* [user thread] */ static void *create_args(void) { ARGS *args = al_malloc(sizeof(*args)); if (args) { args->mutex = al_create_mutex(); args->cond = al_create_cond(); args->done = false; args->response = true; } return args; }
/* ljoy_init_joystick: [primary thread] * Initialise the joystick driver. */ static bool ljoy_init_joystick(void) { _al_vector_init(&joysticks, sizeof(ALLEGRO_JOYSTICK_LINUX *)); num_joysticks = 0; if (!(config_mutex = al_create_mutex())) { return false; } // Scan for joysticks ljoy_scan(false); ljoy_merge(); #ifdef SUPPORT_HOTPLUG if (!(hotplug_mutex = al_create_mutex())) { al_destroy_mutex(config_mutex); return false; } if (!(hotplug_cond = al_create_cond())) { al_destroy_mutex(config_mutex); al_destroy_mutex(hotplug_mutex); return false; } if (!(hotplug_thread = al_create_thread(hotplug_proc, NULL))) { al_destroy_mutex(config_mutex); al_destroy_mutex(hotplug_mutex); al_destroy_cond(hotplug_cond); return false; } al_start_thread(hotplug_thread); inotify_fd = inotify_init(); if (inotify_fd != -1) { fcntl(inotify_fd, F_SETFL, O_NONBLOCK); /* Modern Linux probably only needs to monitor /dev/input. */ inotify_add_watch(inotify_fd, "/dev/input", IN_CREATE|IN_DELETE); _al_unix_start_watching_fd(inotify_fd, ljoy_config_dev_changed, NULL); ALLEGRO_INFO("Hotplugging enabled\n"); } else { ALLEGRO_WARN("Hotplugging not enabled\n"); if (inotify_fd != -1) { close(inotify_fd); inotify_fd = -1; } } #endif return true; }
/* Function: al_open_native_text_log */ ALLEGRO_TEXTLOG *al_open_native_text_log(char const *title, int flags) { ALLEGRO_NATIVE_DIALOG *textlog = NULL; /* Avoid warnings when log windows are unimplemented. */ (void)title; (void)flags; textlog = al_calloc(1, sizeof *textlog); textlog->title = al_ustr_new(title); textlog->flags = flags; if (TEXT_LOG_EXTRA_THREAD) { textlog->tl_thread = al_create_thread(text_log_thread_proc, textlog); } textlog->tl_text_cond = al_create_cond(); textlog->tl_text_mutex = al_create_mutex(); textlog->tl_pending_text = al_ustr_new(""); al_init_user_event_source(&textlog->tl_events); textlog->tl_init_error = false; textlog->tl_done = false; if (TEXT_LOG_EXTRA_THREAD) { /* Unlike the other dialogs, this one never blocks as the intended * use case is a log window running in the background for debugging * purposes when no console can be used. Therefore we have it run * in a separate thread. */ al_start_thread(textlog->tl_thread); al_lock_mutex(textlog->tl_text_mutex); while (!textlog->tl_done && !textlog->tl_init_error) { al_wait_cond(textlog->tl_text_cond, textlog->tl_text_mutex); } al_unlock_mutex(textlog->tl_text_mutex); } else { textlog->tl_init_error = !_al_open_native_text_log(textlog); } if (textlog->tl_init_error) { al_close_native_text_log((ALLEGRO_TEXTLOG *)textlog); return NULL; } _al_register_destructor(_al_dtor_list, textlog, (void (*)(void *))al_close_native_text_log); return (ALLEGRO_TEXTLOG *)textlog; }
/* [user thread] */ bool _al_gtk_init_args(void *ptr, size_t size) { ARGS_BASE *args = (ARGS_BASE *)ptr; memset(args, 0, size); args->mutex = al_create_mutex(); if (!args->mutex) { return false; } args->cond = al_create_cond(); if (!args->cond) { al_destroy_mutex(args->mutex); return false; } args->done = false; args->response = true; return args; }
/* al_init will call this. */ ALLEGRO_SYSTEM *iphone_initialize(int flags) { (void)flags; iphone = al_calloc(1, sizeof *iphone); ALLEGRO_SYSTEM *sys = &iphone->system; iphone->mutex = al_create_mutex(); iphone->cond = al_create_cond(); sys->vt = _al_get_iphone_system_interface(); _al_vector_init(&sys->displays, sizeof (ALLEGRO_DISPLAY_IPHONE *)); _al_unix_init_time(); _al_iphone_init_path(); return sys; }
/* Function: al_create_voice */ ALLEGRO_VOICE *al_create_voice(unsigned int freq, ALLEGRO_AUDIO_DEPTH depth, ALLEGRO_CHANNEL_CONF chan_conf) { ALLEGRO_VOICE *voice = NULL; if (!freq) { _al_set_error(ALLEGRO_INVALID_PARAM, "Invalid Voice Frequency"); return NULL; } voice = al_calloc(1, sizeof(*voice)); if (!voice) { return NULL; } voice->depth = depth; voice->chan_conf = chan_conf; voice->frequency = freq; voice->mutex = al_create_mutex(); voice->cond = al_create_cond(); /* XXX why is this needed? there should only be one active driver */ voice->driver = _al_kcm_driver; ASSERT(_al_kcm_driver); if (_al_kcm_driver->allocate_voice(voice) != 0) { al_destroy_mutex(voice->mutex); al_destroy_cond(voice->cond); al_free(voice); return NULL; } _al_kcm_register_destructor("voice", voice, (void (*)(void *)) al_destroy_voice); return voice; }
int main(void) { ALLEGRO_THREAD *thread[NUM_THREADS]; ALLEGRO_DISPLAY *display; ALLEGRO_TIMER *timer; ALLEGRO_EVENT_QUEUE *queue; ALLEGRO_EVENT event; bool need_draw; int i; for (i = 0; i < 256; i++) { sin_lut[i] = 128 + (int) (127.0 * sin(i / 8.0)); } if (!al_init()) { abort_example("Could not init Allegro.\n"); return 1; } al_install_keyboard(); al_install_mouse(); display = al_create_display(W * IMAGES_PER_ROW, H * NUM_THREADS / IMAGES_PER_ROW); if (!display) { abort_example("Error creating display\n"); return 1; } timer = al_install_timer(1.0/3); if (!timer) { abort_example("Error creating timer\n"); return 1; } queue = al_create_event_queue(); if (!queue) { abort_example("Error creating event queue\n"); return 1; } al_register_event_source(queue, al_get_display_event_source(display)); al_register_event_source(queue, al_get_keyboard_event_source()); al_register_event_source(queue, al_get_mouse_event_source()); al_register_event_source(queue, al_get_timer_event_source(timer)); /* Note: * Right now, A5 video displays can only be accessed from the thread which * created them (at lesat for OpenGL). To lift this restriction, we could * keep track of the current OpenGL context for each thread and make all * functions accessing the display check for it.. not sure it's worth the * additional complexity though. */ al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_RGB_888); al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP); for (i = 0; i < NUM_THREADS; i++) { thread_info[i].bitmap = al_create_bitmap(W, H); if (!thread_info[i].bitmap) { goto Error; } thread_info[i].mutex = al_create_mutex(); if (!thread_info[i].mutex) { goto Error; } thread_info[i].cond = al_create_cond(); if (!thread_info[i].cond) { goto Error; } thread_info[i].is_paused = false; thread_info[i].random_seed = i; thread[i] = al_create_thread(thread_func, &thread_info[i]); if (!thread[i]) { goto Error; } } set_target(0, -0.56062033041600878303, -0.56064322926933807256); set_target(1, -0.57798076669230014080, -0.63449861991138123418); set_target(2, 0.36676836392830602929, -0.59081385302214906030); set_target(3, -1.48319283039401317303, -0.00000000200514696273); set_target(4, -0.74052910500707636032, 0.18340899525730713915); set_target(5, 0.25437906525768350097, -0.00046678223345789554); set_target(6, -0.56062033041600878303, 0.56064322926933807256); set_target(7, -0.57798076669230014080, 0.63449861991138123418); set_target(8, 0.36676836392830602929, 0.59081385302214906030); for (i = 0; i < NUM_THREADS; i++) { al_start_thread(thread[i]); } al_start_timer(timer); need_draw = true; while (true) { if (need_draw && al_event_queue_is_empty(queue)) { show_images(); need_draw = false; } al_wait_for_event(queue, &event); if (event.type == ALLEGRO_EVENT_TIMER) { need_draw = true; } else if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) { int n = (event.mouse.y / H) * IMAGES_PER_ROW + (event.mouse.x / W); if (n < NUM_THREADS) { double x = event.mouse.x - (event.mouse.x / W) * W; double y = event.mouse.y - (event.mouse.y / H) * H; /* Center to the mouse click position. */ if (thread_info[n].is_paused) { thread_info[n].target_x = x / W - 0.5; thread_info[n].target_y = y / H - 0.5; } toggle_pausedness(n); } } else if (event.type == ALLEGRO_EVENT_DISPLAY_EXPOSE) { need_draw = true; } else if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { break; } else if (event.type == ALLEGRO_EVENT_KEY_DOWN) { if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { break; } need_draw = true; } } for (i = 0; i < NUM_THREADS; i++) { /* Set the flag to stop the thread. The thread might be waiting on a * condition variable, so signal the condition to force it to wake up. */ al_set_thread_should_stop(thread[i]); al_lock_mutex(thread_info[i].mutex); al_broadcast_cond(thread_info[i].cond); al_unlock_mutex(thread_info[i].mutex); /* al_destroy_thread() implicitly joins the thread, so this call is not * strictly necessary. */ al_join_thread(thread[i], NULL); al_destroy_thread(thread[i]); } al_destroy_event_queue(queue); al_uninstall_timer(timer); al_destroy_display(display); return 0; Error: return 1; }
static void packet_queue_init(PacketQueue * q) { memset(q, 0, sizeof(PacketQueue)); q->mutex = al_create_mutex(); q->cond = al_create_cond(); }
static bool open_video(ALLEGRO_VIDEO *video) { VideoState *is = av_mallocz(sizeof *is); int i; AVRational fps; is->video = video; init(); video->data = is; strncpy(is->filename, al_path_cstr(video->filename, '/'), sizeof(is->filename)); is->av_sync_type = DEFAULT_AV_SYNC_TYPE; // Open video file #ifdef FFMPEG_0_8 if (avformat_open_input(&is->format_context, is->filename, NULL, NULL) != 0) { #else if (av_open_input_file(&is->format_context, is->filename, NULL, 0, NULL) != 0) { #endif av_free(is); return false; } if (av_find_stream_info(is->format_context) < 0) { av_free(is); return false; } is->video_index = -1; is->audio_index = -1; for (i = 0; i < (int)is->format_context->nb_streams; i++) { if (is->format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && is->video_index < 0) { is->video_index = i; } if (is->format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && is->audio_index < 0) { is->audio_index = i; } } fps = is->format_context->streams[is->video_index]->r_frame_rate; video->fps = (double)fps.num / fps.den; video->audio_rate = is->format_context->streams[is->audio_index]-> codec->sample_rate; video->width = is->format_context->streams[is->video_index]->codec->width; video->height = is->format_context->streams[is->video_index]->codec->height; is->pictq_mutex = al_create_mutex(); is->pictq_cond = al_create_cond(); is->timer_mutex = al_create_mutex(); is->timer_cond = al_create_cond(); return true; } static bool close_video(ALLEGRO_VIDEO *video) { VideoState *is = video->data; is->quit = true; if (is->timer_thread) { al_lock_mutex(is->timer_mutex); al_signal_cond(is->timer_cond); al_unlock_mutex(is->timer_mutex); al_join_thread(is->timer_thread, NULL); } if (is->parse_thread) { al_join_thread(is->parse_thread, NULL); } al_destroy_mutex(is->timer_mutex); al_destroy_cond(is->timer_cond); av_free(is); return true; }
static int pulseaudio_allocate_voice(ALLEGRO_VOICE *voice) { PULSEAUDIO_VOICE *pv = al_malloc(sizeof(PULSEAUDIO_VOICE)); pa_sample_spec ss; pa_buffer_attr ba; ss.channels = al_get_channel_count(voice->chan_conf); ss.rate = voice->frequency; if (voice->depth == ALLEGRO_AUDIO_DEPTH_UINT8) ss.format = PA_SAMPLE_U8; else if (voice->depth == ALLEGRO_AUDIO_DEPTH_INT16) ss.format = PA_SAMPLE_S16NE; #if PA_API_VERSION > 11 else if (voice->depth == ALLEGRO_AUDIO_DEPTH_INT24) ss.format = PA_SAMPLE_S24NE; #endif else if (voice->depth == ALLEGRO_AUDIO_DEPTH_FLOAT32) ss.format = PA_SAMPLE_FLOAT32NE; else { ALLEGRO_ERROR("Unsupported PulseAudio sound format.\n"); al_free(pv); return 1; } ba.maxlength = 0x10000; // maximum length of buffer ba.tlength = 0x2000; // target length of buffer ba.prebuf = -1; // minimum data size required before playback starts // set to -1 to work with the simple API. ba.minreq = 0; // minimum size of request ba.fragsize = -1; // fragment size (recording) pv->s = pa_simple_new( NULL, // Use the default server. al_get_app_name(), PA_STREAM_PLAYBACK, NULL, // Use the default device. "Allegro Voice", &ss, NULL, // Use default channel map &ba, NULL // Ignore error code. ); if (!pv->s) { al_free(pv); return 1; } voice->extra = pv; pv->buffer_size_in_frames = get_buffer_size(al_get_system_config()); pv->frame_size_in_bytes = ss.channels * al_get_audio_depth_size(voice->depth); pv->status = PV_IDLE; //pv->status_mutex = al_create_mutex(); pv->status_cond = al_create_cond(); pv->buffer_mutex = al_create_mutex(); pv->poll_thread = al_create_thread(pulseaudio_update, (void*)voice); al_start_thread(pv->poll_thread); return 0; }
DATA() : mutex(al_create_mutex()), cond(al_create_cond()), posiX (0), posiY (0), modi_X(false), ready (false) {}