Esempio n. 1
0
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    = 0;       // minimum data size required before playback starts
   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->frame_size = ss.channels * al_get_audio_depth_size(voice->depth);
   pv->status = PV_STOPPED;
   pv->buffer_mutex = al_create_mutex();

   pv->poll_thread = al_create_thread(pulseaudio_update, (void*)voice);
   al_start_thread(pv->poll_thread);

   return 0;
}
Esempio n. 2
0
static int pulseaudio_allocate_recorder(ALLEGRO_AUDIO_RECORDER *r)
{
   PULSEAUDIO_RECORDER *pa;
   
   pa = al_calloc(1, sizeof(*pa));
   if (!pa) {
     ALLEGRO_ERROR("Unable to allocate memory for PULSEAUDIO_RECORDER.\n");
     return 1;
   }
   
   pa->ss.channels = al_get_channel_count(r->chan_conf);
   pa->ss.rate = r->frequency;

   if (r->depth == ALLEGRO_AUDIO_DEPTH_UINT8) 
      pa->ss.format = PA_SAMPLE_U8;
   else if (r->depth == ALLEGRO_AUDIO_DEPTH_INT16)
      pa->ss.format = PA_SAMPLE_S16NE;
#if PA_API_VERSION > 11
   else if (r->depth == ALLEGRO_AUDIO_DEPTH_INT24)
      pa->ss.format = PA_SAMPLE_S24NE;
#endif
   else if (r->depth == ALLEGRO_AUDIO_DEPTH_FLOAT32)
      pa->ss.format = PA_SAMPLE_FLOAT32NE;
   else {
      ALLEGRO_ERROR("Unsupported PulseAudio sound format (depth).\n");
      al_free(pa);
      return 1;
   }
   
   /* maximum length of the PulseAudio buffer. -1 => let the server decide. */
   pa->ba.maxlength = -1;
   
   /* fragment size (bytes) controls how much data is returned back per read. 
      The documentation recommends -1 for default behavior, but that sets a
      latency of around 2 seconds. Lower value decreases latency but increases
      overhead. 
      
      The following attempts to set it (the base latency) to 1/8 of a second. 
    */
   pa->ba.fragsize = (r->sample_size * r->frequency) / 8;
   
   pa->s = pa_simple_new(NULL, al_get_app_name(), PA_STREAM_RECORD, NULL, "Allegro Audio Recorder", &pa->ss, NULL, &pa->ba, NULL);
   if (!pa->s) {
      ALLEGRO_ERROR("pa_simple_new() failed.\n");
      al_free(pa);
      return 1;
   }
   
   r->thread = al_create_thread(pulse_audio_update_recorder, r);
   r->extra = pa;
   
   return 0;   
};
Esempio n. 3
0
/* Function: al_install_system
 */
bool al_install_system(int version, int (*atexit_ptr)(void (*)(void)))
{
   ALLEGRO_SYSTEM bootstrap;
   ALLEGRO_SYSTEM *real_system;
   int library_version = al_get_allegro_version();

   if (active_sysdrv) {
      return true;
   }

   /* Note: We cannot call logging functions yet.
    * TODO: Maybe we want to do the check after the "bootstrap" system
    * is available at least?
    */
   if (!compatible_versions(version, library_version))
      return false;

   _al_tls_init_once();

   _al_vector_init(&_al_system_interfaces, sizeof(ALLEGRO_SYSTEM_INTERFACE *));

   /* Set up a bootstrap system so the calls expecting it don't freak out */
   memset(&bootstrap, 0, sizeof(bootstrap));
   active_sysdrv = &bootstrap;
   read_allegro_cfg();

#ifdef ALLEGRO_BCC32
   /* This supresses exceptions on floating point divide by zero */
   _control87(MCW_EM, MCW_EM);
#endif

   /* Register builtin system drivers */
   _al_register_system_interfaces();

   /* Check for a user-defined system driver first */
   real_system = find_system(&_user_system_interfaces);

   /* If a user-defined driver is not found, look for a builtin one */
   if (real_system == NULL) {
      real_system = find_system(&_al_system_interfaces);
   }

   if (real_system == NULL) {
      active_sysdrv = NULL;
      return false;
   }
   
   active_sysdrv = real_system;
   active_sysdrv->mouse_wheel_precision = 1;

   ALLEGRO_INFO("Allegro version: %s\n", ALLEGRO_VERSION_STR);

   if (strcmp(al_get_app_name(), "") == 0) {
      al_set_app_name(NULL);
   }

   _al_add_exit_func(shutdown_system_driver, "shutdown_system_driver");

   _al_dtor_list = _al_init_destructors();

   _al_init_events();

   _al_init_pixels();

   _al_init_iio_table();
   
   _al_init_convert_bitmap_list();

   _al_init_timers();

#ifdef ALLEGRO_CFG_SHADER_GLSL
   _al_glsl_init_shaders();
#endif

   if (active_sysdrv->vt->heartbeat_init)
      active_sysdrv->vt->heartbeat_init();

   if (atexit_ptr && atexit_virgin) {
#ifndef ALLEGRO_ANDROID
      atexit_ptr(al_uninstall_system);
#endif
      atexit_virgin = false;
   }

   /* Clear errnos set while searching for config files. */
   al_set_errno(0);

   active_sysdrv->installed = true;

   _al_srand(time(NULL));

   return true;
}
Esempio n. 4
0
/* _al_win_get_path:
 *  Returns full path to various system and user diretories
 */
ALLEGRO_PATH *_al_win_get_path(int id)
{
    char path[MAX_PATH];
    wchar_t pathw[MAX_PATH];
    ALLEGRO_USTR *pathu;
    uint32_t csidl = 0;
    HRESULT ret = 0;
    ALLEGRO_PATH *cisdl_path = NULL;

    switch (id) {
    case ALLEGRO_TEMP_PATH: {
        /* Check: TMP, TMPDIR, TEMP or TEMPDIR */

        DWORD ret = GetTempPathW(MAX_PATH, pathw);
        if (ret > MAX_PATH) {
            /* should this ever happen, windows is more broken than I ever thought */
            return NULL;
        }
        pathu = al_ustr_new_from_utf16(pathw);
        al_ustr_to_buffer(pathu, path, sizeof path);
        al_ustr_free(pathu);
        return al_create_path_for_directory(path);

    }
    break;

    case ALLEGRO_RESOURCES_PATH: { /* where the program is in */
        HANDLE process = GetCurrentProcess();
        char *ptr;

        GetModuleFileNameExW(process, NULL, pathw, MAX_PATH);
        pathu = al_ustr_new_from_utf16(pathw);
        al_ustr_to_buffer(pathu, path, sizeof path);
        al_ustr_free(pathu);
        ptr = strrchr(path, '\\');
        if (!ptr) { /* shouldn't happen */
            return NULL;
        }

        /* chop off everything including and after the last slash */
        /* should this not chop the slash? */
        *ptr = '\0';

        return al_create_path_for_directory(path);
    }
    break;

    case ALLEGRO_USER_DATA_PATH: /* CSIDL_APPDATA */
    case ALLEGRO_USER_SETTINGS_PATH:
        csidl = CSIDL_APPDATA;
        break;

    case ALLEGRO_USER_HOME_PATH: /* CSIDL_PROFILE */
        csidl = CSIDL_PROFILE;
        break;

    case ALLEGRO_USER_DOCUMENTS_PATH: /* CSIDL_PERSONAL */
        csidl = CSIDL_PERSONAL;
        break;

    case ALLEGRO_EXENAME_PATH: { /* full path to the exe including its name */
        HANDLE process = GetCurrentProcess();

        GetModuleFileNameExW(process, NULL, pathw, MAX_PATH);
        pathu = al_ustr_new_from_utf16(pathw);
        al_ustr_to_buffer(pathu, path, sizeof path);
        al_ustr_free(pathu);

        return al_create_path(path);
    }
    break;

    default:
        return NULL;
    }

    ret = SHGetFolderPathW(NULL, csidl, NULL, SHGFP_TYPE_CURRENT, pathw);
    if (ret != S_OK) {
        return NULL;
    }

    pathu = al_ustr_new_from_utf16(pathw);
    al_ustr_to_buffer(pathu, path, sizeof path);
    al_ustr_free(pathu);

    cisdl_path = al_create_path_for_directory(path);
    if (!cisdl_path)
        return NULL;

    if (csidl == CSIDL_APPDATA) {
        const char *org_name = al_get_org_name();
        const char *app_name = al_get_app_name();

        if (!app_name || !app_name[0]) {
            /* this shouldn't ever happen. */
            al_destroy_path(cisdl_path);
            return NULL;
        }

        if (org_name && org_name[0]) {
            al_append_path_component(cisdl_path, org_name);
        }

        al_append_path_component(cisdl_path, app_name);
    }

    return cisdl_path;
}
Esempio n. 5
0
static mrb_value
app_name_getter(mrb_state *mrb, mrb_value self)
{
  return mrb_str_new_cstr(mrb, al_get_app_name());
}
Esempio n. 6
0
static int pulseaudio_open(void)
{
   /* Use PA_CONTEXT_NOAUTOSPAWN to see if a PA server is running.
    * If not, fail - we're better off using ALSA/OSS.
    * 
    * Also check for suspended PA - again better using ALSA/OSS in
    * that case (pa_simple_write just blocks until PA is unsuspended
    * otherwise).
    * 
    * TODO: Maybe we should have a force flag to the audio driver
    * open method, which in the case of PA would spawn a server if
    * none is running (and also unsuspend?).
    */

   pa_mainloop *mainloop = pa_mainloop_new();
   pa_context *c = pa_context_new(pa_mainloop_get_api(mainloop),
      al_get_app_name());
   if (!c) {
      pa_mainloop_free(mainloop);
      return 1;
   }

   pa_context_connect(c, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL);

   while (1) {
      /* Don't block or it will hang if there is no server to connect to. */
      const int blocking = 0;
      if (pa_mainloop_iterate(mainloop, blocking, NULL) < 0) {
         ALLEGRO_ERROR("pa_mainloop_iterate failed\n");
         pa_context_disconnect(c);
         pa_mainloop_free(mainloop);
         break;
      }
      pa_context_state_t s = pa_context_get_state(c);
      if (s == PA_CONTEXT_READY) {
         ALLEGRO_DEBUG("PA_CONTEXT_READY\n");
         break;
      }
      if (s == PA_CONTEXT_FAILED) {
         ALLEGRO_ERROR("PA_CONTEXT_FAILED\n");
         pa_context_disconnect(c);
         pa_mainloop_free(mainloop);
         return 1;
      }
   }

   pa_sink_state_t state = 0;
   pa_operation *op = pa_context_get_sink_info_list(c, sink_info_cb, &state);
   while (pa_operation_get_state(op) == PA_OPERATION_RUNNING) {
      pa_mainloop_iterate(mainloop, 1, NULL);
   }
   /*if (state == PA_SINK_SUSPENDED) {
      pa_context_disconnect(c);
      pa_mainloop_free(mainloop);
      return 1;
   }*/
   pa_operation_unref(op);
   pa_context_disconnect(c);
   pa_context_unref(c);
   pa_mainloop_free(mainloop);
   return 0;
}
ALLEGRO_PATH *_al_unix_get_path(int id)
{
   switch (id) {
      case ALLEGRO_TEMP_PATH: {
         /* Check: TMP, TMPDIR, TEMP or TEMPDIR */
         char *envs[] = { "TMP", "TMPDIR", "TEMP", "TEMPDIR", NULL};
         uint32_t i = 0;
         for (; envs[i] != NULL; ++i) {
            char *tmp = getenv(envs[i]);
            if (tmp) {
               return al_create_path_for_directory(tmp);
            }
         }

         /* next try: /tmp /var/tmp /usr/tmp */
         char *paths[] = { "/tmp/", "/var/tmp/", "/usr/tmp/", NULL };
         for (i=0; paths[i] != NULL; ++i) {
            ALLEGRO_FS_ENTRY *fse = al_create_fs_entry(paths[i]);
            bool found = (al_get_fs_entry_mode(fse) & ALLEGRO_FILEMODE_ISDIR) != 0;
            al_destroy_fs_entry(fse);
            if (found) {
               return al_create_path_for_directory(paths[i]);
            }
         }

         /* Give up? */
         return NULL;
      } break;

      case ALLEGRO_RESOURCES_PATH: {
         ALLEGRO_PATH *exe = get_executable_name();
         exe = follow_symlinks(exe);
         al_set_path_filename(exe, NULL);
         return exe;

      } break;

      case ALLEGRO_USER_DATA_PATH:
      case ALLEGRO_USER_SETTINGS_PATH: {
         ALLEGRO_PATH *local_path = NULL;
         const char *org_name = al_get_org_name();
         const char *app_name = al_get_app_name();
         
         /* to avoid writing directly into the user's directory, require at least an app name */
         if (!app_name)
            return NULL;
         
         /* find the appropriate path from the xdg environment variables, if possible */
         if (id == ALLEGRO_USER_DATA_PATH) {
            const char *xdg_data_home = getenv("XDG_DATA_HOME");
            local_path = al_create_path_for_directory(xdg_data_home ? xdg_data_home : ".local/share");
         }
         else {
            const char *xdg_config_home = getenv("XDG_CONFIG_HOME");
            local_path = al_create_path_for_directory(xdg_config_home ? xdg_config_home : ".config");
         }
         
         if (!local_path) 
            return NULL;
         
         /* if the path is relative, prepend the user's home directory */
         if (al_path_cstr(local_path, '/')[0] != '/') {
            ALLEGRO_PATH *home_path = _unix_find_home();
            if (!home_path)
               return NULL;
            
            al_rebase_path(home_path, local_path);
            al_destroy_path(home_path);
         }

         /* only add org name if not blank */
         if (org_name && org_name[0]) {              
            al_append_path_component(local_path, al_get_org_name());
         }
         
         al_append_path_component(local_path, al_get_app_name());

        return local_path;
      } break;

      case ALLEGRO_USER_HOME_PATH:
         return _unix_find_home();
         
      case ALLEGRO_USER_DOCUMENTS_PATH: {
         ALLEGRO_PATH *local_path = _get_xdg_path("DOCUMENTS");
         return local_path ? local_path : _unix_find_home();
      } break;

      case ALLEGRO_EXENAME_PATH:
         return get_executable_name();
         break;

      default:
         return NULL;
   }

   return NULL;
}