Пример #1
0
ALenum NewThunkEntry(ALuint *index)
{
    void *NewList;
    ALuint i;

    ReadLock(&ThunkLock);
    for(i = 0;i < ThunkArraySize;i++)
    {
        if(ATOMIC_EXCHANGE(ALenum, &ThunkArray[i], AL_TRUE, almemory_order_acq_rel) == AL_FALSE)
        {
            ReadUnlock(&ThunkLock);
            *index = i+1;
            return AL_NO_ERROR;
        }
    }
    ReadUnlock(&ThunkLock);

    WriteLock(&ThunkLock);
    /* Double-check that there's still no free entries, in case another
     * invocation just came through and increased the size of the array.
     */
    for(;i < ThunkArraySize;i++)
    {
        if(ATOMIC_EXCHANGE(ALenum, &ThunkArray[i], AL_TRUE, almemory_order_acq_rel) == AL_FALSE)
        {
            WriteUnlock(&ThunkLock);
            *index = i+1;
            return AL_NO_ERROR;
        }
    }

    NewList = al_calloc(16, ThunkArraySize*2 * sizeof(*ThunkArray));
    if(!NewList)
    {
        WriteUnlock(&ThunkLock);
        ERR("Realloc failed to increase to %u entries!\n", ThunkArraySize*2);
        return AL_OUT_OF_MEMORY;
    }
    memcpy(NewList, ThunkArray, ThunkArraySize*sizeof(*ThunkArray));
    al_free(ThunkArray);
    ThunkArray = NewList;
    ThunkArraySize *= 2;

    ATOMIC_STORE_SEQ(&ThunkArray[i], AL_TRUE);
    WriteUnlock(&ThunkLock);

    *index = i+1;
    return AL_NO_ERROR;
}
Пример #2
0
void *
xrealloc (void *ptr, size_t n)
{
  if (ptr == NULL) return xmalloc (n);
  if (n == 0) {
    al_free (ptr);
    return NULL;
  }

  void *_ptr = al_realloc (ptr, n);
  if (! _ptr)
    error (-1, 0, "%s (%p, %u): cannot reallocate memory", __func__, ptr,
           (unsigned int) n);
  return _ptr;
}
Пример #3
0
static void set_cursor_data(ALLEGRO_DISPLAY_RASPBERRYPI *d, uint32_t *data, int width, int height)
{
    al_free(d->cursor_data);
    int spitch = sizeof(uint32_t) * width;
    int dpitch = pot(spitch);
    d->cursor_data = al_malloc(dpitch * height);
    int y;
    for (y = 0; y < height; y++) {
        uint8_t *p1 = (uint8_t *)d->cursor_data + y * dpitch;
        uint8_t *p2 = (uint8_t *)data + y * spitch;
        memcpy(p1, p2, spitch);
    }
    d->cursor_width = width;
    d->cursor_height = height;
}
Пример #4
0
void t3f_destroy_animation(T3F_ANIMATION * ap)
{
	int i;

	for(i = 0; i < ap->frames; i++)
	{
		al_free(ap->frame[i]);
	}
	if(!(ap->flags & T3F_ANIMATION_FLAG_EXTERNAL_BITMAPS))
	{
		for(i = 0; i < ap->bitmaps->count; i++)
		{
			/* Attempt to destroy resource. If it fails, that means the user
			 * probably constructed the animation manually, so destroy the bitmap
			 * directly. */
			if(!t3f_destroy_resource(ap->bitmaps->bitmap[i]))
			{
				al_destroy_bitmap(ap->bitmaps->bitmap[i]);
			}
		}
		al_free(ap->bitmaps);
	}
	al_free(ap);
}
Пример #5
0
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
{
    ALsizei pos;
    for(pos = 0;pos < Context->EffectSlotMap.size;pos++)
    {
        ALeffectslot *temp = Context->EffectSlotMap.array[pos].value;
        Context->EffectSlotMap.array[pos].value = NULL;

        DELETE_OBJ(temp->EffectState);

        FreeThunkEntry(temp->id);
        memset(temp, 0, sizeof(ALeffectslot));
        al_free(temp);
    }
}
Пример #6
0
/* Test al_ustr_new_from_buffer, al_cstr_dup. */
static void t39(void)
{
   const char s1[] = "Корабът ми на въздушна възглавница\0е пълен със змиорки";
   ALLEGRO_USTR *us;
   char *s2;

   us = al_ustr_new_from_buffer(s1, sizeof(s1) - 1); /* missing NUL term. */
   s2 = al_cstr_dup(us);
   al_ustr_free(us);

   CHECK(0 == strcmp(s1, s2));
   CHECK(0 == memcmp(s1, s2, sizeof(s1))); /* including NUL terminator */

   al_free(s2);
}
Пример #7
0
char
menu_enum (struct menu_item *menu, char *prefix)
{
  int i = 0;
  char *menu_str = NULL, *tmp_str = NULL;
  while (menu[i].key) {
    if (menu_str) {
      tmp_str = menu_str;
      xasprintf (&menu_str, "%s%c", menu_str, menu[i].key);
    } else {
      xasprintf (&menu_str, "%s%c", prefix ? prefix : "", menu[i].key);
    }
    if (tmp_str) al_free (tmp_str);
    i++;
  }
  if (menu_str) {
    tmp_str = menu_str;
    xasprintf (&menu_str, "%s%c", menu_str, '?');
  }
  if (tmp_str) al_free (tmp_str);
  char c = menu_opt (menu, menu_str);
  al_free (menu_str);
  return c;
}
Пример #8
0
void ImGui_ImplAllegro5_Shutdown()
{
    ImGui_ImplAllegro5_InvalidateDeviceObjects();

    g_Display = NULL;
    g_Time = 0.0;

    if (g_VertexDecl)
        al_destroy_vertex_decl(g_VertexDecl);
    g_VertexDecl = NULL;

    if (g_ClipboardTextData)
        al_free(g_ClipboardTextData);
    g_ClipboardTextData = NULL;
}
Пример #9
0
static void pulseaudio_deallocate_voice(ALLEGRO_VOICE *voice)
{
   PULSEAUDIO_VOICE *pv = voice->extra;

   /* We do NOT hold the voice mutex here, so this does NOT result in a
    * deadlock when the thread calls _al_voice_update.
    */
   al_set_thread_should_stop(pv->poll_thread);
   al_join_thread(pv->poll_thread, NULL);
   al_destroy_thread(pv->poll_thread);

   al_destroy_mutex(pv->buffer_mutex);

   pa_simple_free(pv->s);
   al_free(pv);
}
Пример #10
0
/* [user thread] */
static void xgtk_destroy_display_hook(ALLEGRO_DISPLAY *display, bool is_last)
{
   ALLEGRO_DISPLAY_XGLX *d = (ALLEGRO_DISPLAY_XGLX *)display;
   ARGS_DESTROY args;

   if (!_al_gtk_init_args(&args, sizeof(args)))
      return;

   args.display = d;
   args.is_last = is_last;

   _al_gtk_wait_for_args(do_destroy_display_hook, &args);

   al_free(d->gtk);
   d->gtk = NULL;
}
Пример #11
0
void DeinitEffectSlot(ALeffectslot *slot)
{
    struct ALeffectslotProps *props;

    props = ATOMIC_LOAD_SEQ(&slot->Update);
    if(props)
    {
        if(props->State) ALeffectState_DecRef(props->State);
        TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", props);
        al_free(props);
    }

    ALeffectState_DecRef(slot->Effect.State);
    if(slot->Params.EffectState)
        ALeffectState_DecRef(slot->Params.EffectState);
}
Пример #12
0
/* Function: al_destroy_voice
 */
void al_destroy_voice(ALLEGRO_VOICE *voice)
{
   if (voice) {
      _al_kcm_unregister_destructor(voice);

      al_detach_voice(voice);
      ASSERT(al_get_voice_playing(voice) == false);

      /* We do NOT lock the voice mutex when calling this method. */
      voice->driver->deallocate_voice(voice);
      al_destroy_mutex(voice->mutex);
      al_destroy_cond(voice->cond);

      al_free(voice);
   }
}
Пример #13
0
static void *al_init(const char *device, unsigned rate, unsigned latency)
{
   al_t *al;

   (void)device;

   al = (al_t*)calloc(1, sizeof(al_t));
   if (!al)
      return NULL;

   al->handle = alcOpenDevice(NULL);
   if (!al->handle)
      goto error;

   al->ctx = alcCreateContext(al->handle, NULL);
   if (!al->ctx)
      goto error;

   alcMakeContextCurrent(al->ctx);

   al->rate = rate;

   /* We already use one buffer for tmpbuf. */
   al->num_buffers = (latency * rate * 2 * sizeof(int16_t)) / (1000 * BUFSIZE) - 1;
   if (al->num_buffers < 2)
      al->num_buffers = 2;

   RARCH_LOG("[OpenAL]: Using %u buffers of %u bytes.\n", (unsigned)al->num_buffers, BUFSIZE);

   al->buffers = (ALuint*)calloc(al->num_buffers, sizeof(ALuint));
   al->res_buf = (ALuint*)calloc(al->num_buffers, sizeof(ALuint));
   if (al->buffers == NULL || al->res_buf == NULL)
      goto error;

   alGenSources(1, &al->source);
   alGenBuffers(al->num_buffers, al->buffers);

   memcpy(al->res_buf, al->buffers, al->num_buffers * sizeof(ALuint));
   al->res_ptr = al->num_buffers;

   return al;

error:
   al_free(al);
   return NULL;
}
Пример #14
0
static void *pulse_audio_update_recorder(ALLEGRO_THREAD *t, void *data)
{
   ALLEGRO_AUDIO_RECORDER *r = (ALLEGRO_AUDIO_RECORDER *) data;
   PULSEAUDIO_RECORDER *pa = (PULSEAUDIO_RECORDER *) r->extra;
   ALLEGRO_EVENT user_event;
   uint8_t *null_buffer;
   unsigned int fragment_i = 0;
   
   null_buffer = al_malloc(1024);
   if (!null_buffer) {
      ALLEGRO_ERROR("Unable to create buffer for draining PulseAudio.\n");
      return NULL;
   }
   
   while (!al_get_thread_should_stop(t))
   {
      al_lock_mutex(r->mutex);
      if (!r->is_recording) {
         /* Even if not recording, we still want to read from the PA server.
            Otherwise it will buffer everything and spit it all out whenever
            the recording resumes. */
         al_unlock_mutex(r->mutex);
         pa_simple_read(pa->s, null_buffer, 1024, NULL);
      }
      else {
         ALLEGRO_AUDIO_RECORDER_EVENT *e;
         al_unlock_mutex(r->mutex);
         if (pa_simple_read(pa->s, r->fragments[fragment_i], r->fragment_size, NULL) >= 0) {
            user_event.user.type = ALLEGRO_EVENT_AUDIO_RECORDER_FRAGMENT;
            e = al_get_audio_recorder_event(&user_event);
            e->buffer = r->fragments[fragment_i];
            e->samples = r->samples;           
            al_emit_user_event(&r->source, &user_event, NULL);
         
            if (++fragment_i == r->fragment_count) {
               fragment_i = 0;
            }
         }
      }
   }

   al_free(null_buffer);
   return NULL;
};
static void xglx_shutdown_system(void)
{
   ALLEGRO_SYSTEM *s = al_get_system_driver();
   ALLEGRO_SYSTEM_XGLX *sx = (void *)s;

   ALLEGRO_INFO("shutting down.\n");

   if (sx->x11display) {
      /* Events thread only runs if we are connected to an X server. */
      _al_thread_join(&sx->thread);
   }

   /* Close all open displays. */
   while (_al_vector_size(&s->displays) > 0) {
      ALLEGRO_DISPLAY **dptr = _al_vector_ref(&s->displays, 0);
      ALLEGRO_DISPLAY *d = *dptr;
      _al_destroy_display_bitmaps(d);
      al_destroy_display(d);
   }
   _al_vector_free(&s->displays);

   // Makes sure we wait for any commands sent to the X server when destroying the displays.
   // Should make sure we don't shutdown before modes are restored.
   if (sx->x11display) {
      XSync(sx->x11display, False);
   }
   
   _al_xsys_mmon_exit(sx);

   if (sx->x11display) {
      XCloseDisplay(sx->x11display);
      sx->x11display = None;
      ALLEGRO_DEBUG("xsys: close x11display.\n");
   }

   if (sx->gfxdisplay) {
      /* XXX for some reason, crashes if both XCloseDisplay calls are made */
      /* XCloseDisplay(sx->gfxdisplay); */
      sx->gfxdisplay = None;
   }

   al_free(sx);
}
Пример #16
0
static bool ogl_lock_region_nonbb_readwrite_nonfbo(
   ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap,
   int x, int gl_y, int w, int h, int format)
{
   /* No FBO - fallback to reading the entire texture */
   const int pixel_size = al_get_pixel_size(format);
   const int pitch = ogl_pitch(ogl_bitmap->true_w, pixel_size);
   GLenum e;
   bool ok;
   (void) w;

   ogl_bitmap->lock_buffer = al_malloc(pitch * ogl_bitmap->true_h);
   if (ogl_bitmap->lock_buffer == NULL) {
      return false;
   }

   ok = true;

   glBindTexture(GL_TEXTURE_2D, ogl_bitmap->texture);
   glGetTexImage(GL_TEXTURE_2D, 0,
      get_glformat(format, 2),
      get_glformat(format, 1),
      ogl_bitmap->lock_buffer);

   e = glGetError();
   if (e) {
      ALLEGRO_ERROR("glGetTexImage for format %s failed (%s).\n",
         _al_pixel_format_name(format), _al_gl_error_string(e));
      al_free(ogl_bitmap->lock_buffer);
      ogl_bitmap->lock_buffer = NULL;
      ok = false;
   }

   if (ok) {
      bitmap->locked_region.data = ogl_bitmap->lock_buffer +
         pitch * (gl_y + h - 1) + pixel_size * x;
      bitmap->locked_region.format = format;
      bitmap->locked_region.pitch = -pitch;
      bitmap->locked_region.pixel_size = pixel_size;
   }

   return ok;
}
Пример #17
0
/* sys_linux_message:
 *  Display a message on our original console.
 */
static void sys_linux_message (const char *msg)
{
   char *tmp;
   int ret;
   ASSERT(msg);

   tmp = al_malloc(ALLEGRO_MESSAGE_SIZE);
   msg = uconvert(msg, U_UTF8, tmp, U_ASCII, ALLEGRO_MESSAGE_SIZE);

   do {
      ret = write(STDERR_FILENO, msg, strlen(msg));
      if ((ret < 0) && (errno != EINTR))
	 break;
   } while (ret < (int)strlen(msg));

   __al_linux_got_text_message = true;

   al_free(tmp);
}
/* Function: al_emit_user_event
 */
bool al_emit_user_event(ALLEGRO_EVENT_SOURCE *src,
   ALLEGRO_EVENT *event, void (*dtor)(ALLEGRO_USER_EVENT *))
{
   size_t num_queues;
   bool rc;

   ASSERT(src);
   ASSERT(event);
   ASSERT(ALLEGRO_EVENT_TYPE_IS_USER(event->any.type));

   if (dtor) {
      ALLEGRO_USER_EVENT_DESCRIPTOR *descr = al_malloc(sizeof(*descr));
      descr->refcount = 0;
      descr->dtor = dtor;
      event->user.__internal__descr = descr;
   }
   else {
      event->user.__internal__descr = NULL;
   }

   _al_event_source_lock(src);
   {
      ALLEGRO_EVENT_SOURCE_REAL *rsrc = (ALLEGRO_EVENT_SOURCE_REAL *)src;

      num_queues = _al_vector_size(&rsrc->queues);
      if (num_queues > 0) {
         event->user.timestamp = al_get_time();
         _al_event_source_emit_event(src, event);
         rc = true;
      }
      else {
         rc = false;
      }
   }
   _al_event_source_unlock(src);

   if (dtor && !rc) {
      dtor(&event->user);
      al_free(event->user.__internal__descr);
   }

   return rc;
}
Пример #19
0
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots)
{
    ALCcontext *context;
    ALeffectslot *slot;
    ALsizei i;

    context = GetContextRef();
    if(!context) return;

    LockEffectSlotList(context);
    if(n < 0)
        SETERR_GOTO(context, AL_INVALID_VALUE, done, "Deleting %d effect slots", n);
    if(n == 0) goto done;

    for(i = 0;i < n;i++)
    {
        if((slot=LookupEffectSlot(context, effectslots[i])) == NULL)
            SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u",
                        effectslots[i]);
        if(ReadRef(&slot->ref) != 0)
            SETERR_GOTO(context, AL_INVALID_NAME, done, "Deleting in-use effect slot %u",
                        effectslots[i]);
    }

    // All effectslots are valid
    RemoveActiveEffectSlots(effectslots, n, context);
    for(i = 0;i < n;i++)
    {
        if((slot=LookupEffectSlot(context, effectslots[i])) == NULL)
            continue;
        VECTOR_ELEM(context->EffectSlotList, effectslots[i]-1) = NULL;

        DeinitEffectSlot(slot);

        memset(slot, 0, sizeof(*slot));
        al_free(slot);
    }

done:
    UnlockEffectSlotList(context);
    ALCcontext_DecRef(context);
}
Пример #20
0
int t3f_animation_delete_frame(T3F_ANIMATION * ap, int frame)
{
	int i;

	if(frame < ap->frames)
	{
		al_free(ap->frame[frame]);
	}
	else
	{
		return 0;
	}
	for(i = frame; i < ap->frames - 1; i++)
	{
		ap->frame[i] = ap->frame[i + 1];
	}
	ap->frames--;
	t3f_animation_build_frame_list(ap);
	return 1;
}
Пример #21
0
static void _al_win_get_window_center(
   ALLEGRO_DISPLAY_WIN *win_display, int width, int height, int *out_x, int *out_y)
{
   int a = win_display->adapter;
   bool *is_fullscreen;
   ALLEGRO_MONITOR_INFO info;
   RECT win_size;

   ALLEGRO_SYSTEM *sys = al_get_system_driver();
   unsigned int num;
   unsigned int i;
   unsigned int fullscreen_found = 0;
   num = al_get_num_video_adapters();
   is_fullscreen = al_calloc(num, sizeof(bool));
   for (i = 0; i < sys->displays._size; i++) {
      ALLEGRO_DISPLAY **dptr = _al_vector_ref(&sys->displays, i);
      ALLEGRO_DISPLAY *d = *dptr;
      if (d->flags & ALLEGRO_FULLSCREEN) {
         ALLEGRO_DISPLAY_WIN *win_display = (ALLEGRO_DISPLAY_WIN *)d;
         is_fullscreen[win_display->adapter] = true;
         fullscreen_found++;
      }
   }
   if (fullscreen_found && fullscreen_found < num) {
      for (i = 0; i < num; i++) {
         if (is_fullscreen[i] == false) {
            a = i;
            break;
         }
      }
   }
   al_free(is_fullscreen);

   al_get_monitor_info(a, &info);

   win_size.left = info.x1 + (info.x2 - info.x1 - width) / 2;
   win_size.top = info.y1 + (info.y2 - info.y1 - height) / 2;

   *out_x = win_size.left;
   *out_y = win_size.top;
}
Пример #22
0
static void xglx_shutdown_system(void)
{
   ALLEGRO_SYSTEM *s = al_get_system_driver();
   ALLEGRO_SYSTEM_XGLX *sx = (void *)s;

   ALLEGRO_INFO("shutting down.\n");

   if (sx->have_xevents_thread) {
      _al_thread_join(&sx->xevents_thread);
      sx->have_xevents_thread = false;
   }

   /* Close all open displays. */
   while (_al_vector_size(&s->displays) > 0) {
      ALLEGRO_DISPLAY **dptr = _al_vector_ref(&s->displays, 0);
      ALLEGRO_DISPLAY *d = *dptr;
      al_destroy_display(d);
   }
   _al_vector_free(&s->displays);

   // Makes sure we wait for any commands sent to the X server when destroying the displays.
   // Should make sure we don't shutdown before modes are restored.
   if (sx->x11display) {
      XSync(sx->x11display, False);
   }

   _al_xsys_mmon_exit(sx);

   if (sx->x11display) {
      XCloseDisplay(sx->x11display);
      sx->x11display = None;
      ALLEGRO_DEBUG("xsys: close x11display.\n");
   }

   if (sx->gfxdisplay) {
      XCloseDisplay(sx->gfxdisplay);
      sx->gfxdisplay = None;
   }

   al_free(sx);
}
Пример #23
0
/* Function: al_open_video
 */
ALLEGRO_VIDEO *al_open_video(char const *filename)
{
   ALLEGRO_VIDEO *video;

   video = al_calloc(1, sizeof *video);
   
   video->vtable = _al_video_vtable;
   
   video->filename = al_create_path(filename);

   if (!video->vtable->open_video(video)) {
      al_destroy_path(video->filename);
      al_free(video);
      return NULL;
   }
   
   al_init_user_event_source(&video->es);
   video->es_inited = true;
   
   return video;
}
Пример #24
0
static void pulseaudio_deallocate_voice(ALLEGRO_VOICE *voice)
{
   PULSEAUDIO_VOICE *pv = voice->extra;

   al_lock_mutex(voice->mutex);
   pv->status = PV_JOIN;
   al_broadcast_cond(pv->status_cond);
   al_unlock_mutex(voice->mutex);

   /* We do NOT hold the voice mutex here, so this does NOT result in a
    * deadlock when the thread calls _al_voice_update.
    */
   al_join_thread(pv->poll_thread, NULL);
   al_destroy_thread(pv->poll_thread);

   al_destroy_cond(pv->status_cond);
   al_destroy_mutex(pv->buffer_mutex);

   pa_simple_free(pv->s);
   al_free(pv);
}
Пример #25
0
/* [user thread] */
static bool wait_for_args(GSourceFunc func, void *data)
{
   ARGS *args = (ARGS *) data;
   bool response;
   
   al_lock_mutex(args->mutex);
   g_timeout_add(0, func, data);
   while (args->done == false) {
      al_wait_cond(args->cond, args->mutex);
   }
   al_unlock_mutex(args->mutex);
   
   response = args->response;
   
   al_destroy_mutex(args->mutex);
   al_destroy_cond(args->cond);
   
   al_free(args);
   
   return response;
}
Пример #26
0
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *context)
{
    ALeffectslotPtr *iter = VECTOR_BEGIN(context->EffectSlotList);
    ALeffectslotPtr *end = VECTOR_END(context->EffectSlotList);
    size_t leftover = 0;

    for(;iter != end;iter++)
    {
        ALeffectslot *slot = *iter;
        if(!slot) continue;
        *iter = NULL;

        DeinitEffectSlot(slot);

        memset(slot, 0, sizeof(*slot));
        al_free(slot);
        ++leftover;
    }
    if(leftover > 0)
        WARN("(%p) Deleted "SZFMT" AuxiliaryEffectSlot%s\n", context, leftover, (leftover==1)?"":"s");
}
Пример #27
0
static bool file_stdio_fclose(ALLEGRO_FILE *f)
{
   USERDATA *userdata = get_userdata(f);
   bool ret;

   if (userdata->fp == NULL) {
      /* This can happen in the middle of al_fopen_fd. */
      ret = true;
   }
   else if (fclose(userdata->fp) == 0) {
      ret = true;
   }
   else {
      al_set_errno(errno);
      ret = false;
   }

   al_free(userdata);

   return ret;
}
Пример #28
0
static ALLEGRO_EXTRA_DISPLAY_SETTINGS* read_pixel_format_old(int fmt, HDC dc)
{
   ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds = NULL;
   PIXELFORMATDESCRIPTOR pfd;
   int result;

   result = DescribePixelFormat(dc, fmt+1, sizeof(pfd), &pfd);
   if (!result) {
      ALLEGRO_WARN("DescribePixelFormat() failed. %s\n",
                    get_error_desc(GetLastError()));
      return NULL;
   }

   eds = al_calloc(1, sizeof *eds);
   if (!decode_pixel_format_old(&pfd, eds)) {
      al_free(eds);
      return NULL;
   }

   return eds;
}
Пример #29
0
static ALLEGRO_FS_ENTRY *fs_apk_create_entry(const char *path)
{
   ALLEGRO_FS_ENTRY_APK *e;
   ALLEGRO_USTR *us;

   e = al_calloc(1, sizeof *e);
   if (!e)
      return NULL;
   e->fs_entry.vtable = &fs_apk_vtable;

   us = apply_cwd(path);
   e->path = al_create_path(al_cstr(us));
   al_ustr_free(us);
   if (!e->path) {
      al_free(e);
      return NULL;
   }
   e->path_cstr = al_path_cstr(e->path, '/');
   
   return &e->fs_entry;
}
Пример #30
0
/* Function: al_destroy_menu
 */
void al_destroy_menu(ALLEGRO_MENU *menu)
{
   ALLEGRO_MENU_ITEM **slot;
   size_t i;
   ASSERT(menu);

   if (menu->parent) {
      /* If the menu is attached to a menu item, then this is equivelant to
         removing that menu item. */
      ALLEGRO_MENU *parent = menu->parent->parent;
      ASSERT(parent);

      for (i = 0; i < _al_vector_size(&parent->items); ++i) {
         slot = _al_vector_ref(&parent->items, i);
         if (*slot == menu->parent) {
            al_remove_menu_item(parent, 0 - (int) i);
            return;
         }
      }

      /* Should never get here. */
      ASSERT(false);
      return;
   }
   else if (menu->display && !menu->is_popup_menu) {
      /* This is an active, top-level menu. */
      al_remove_display_menu(menu->display);
   }

   /* Destroy each item associated with the menu. */
   while (_al_vector_size(&menu->items)) {
      slot = _al_vector_ref_back(&menu->items);
      destroy_menu_item(*slot);
   }

   _al_vector_free(&menu->items);

   al_disable_menu_event_source(menu);
   al_free(menu);
}