/* stream_free:
 *  This function is ALLEGRO_MIXER aware and frees the memory associated with
 *  the sample or mixer, and detaches any attached streams or mixers.
 */
static void stream_free(ALLEGRO_SAMPLE_INSTANCE *spl)
{
   if (spl) {
      /* Make sure we free the mixer buffer and de-reference the attached
       * streams if this is a mixer stream.
       */
      if (spl->is_mixer) {
         ALLEGRO_MIXER *mixer = (ALLEGRO_MIXER *)spl;
         int i;

         _al_kcm_stream_set_mutex(&mixer->ss, NULL);

         for (i = _al_vector_size(&mixer->streams) - 1; i >= 0; i--) {
            ALLEGRO_SAMPLE_INSTANCE **slot = _al_vector_ref(&mixer->streams, i);
            ALLEGRO_SAMPLE_INSTANCE *spl = *slot;
            spl->parent.u.ptr = NULL;
         }

         _al_vector_free(&mixer->streams);

         if (spl->spl_data.buffer.ptr) {
            ASSERT(spl->spl_data.free_buf);
            al_free(spl->spl_data.buffer.ptr);
            spl->spl_data.buffer.ptr = NULL;
         }
         spl->spl_data.free_buf = false;
      }

      ASSERT(! spl->spl_data.free_buf);

      al_free(spl);
   }
}
Ejemplo n.º 2
0
/* Function: al_detach_voice
 */
void al_detach_voice(ALLEGRO_VOICE *voice)
{
   ASSERT(voice);

   if (!voice->attached_stream) {
      return;
   }

   al_lock_mutex(voice->mutex);

   if (!voice->is_streaming) {
      ALLEGRO_SAMPLE_INSTANCE *spl = voice->attached_stream;

      spl->pos = voice->driver->get_voice_position(voice);
      spl->is_playing = voice->driver->voice_is_playing(voice);

      voice->driver->stop_voice(voice);
      voice->driver->unload_voice(voice);
   }
   else {
      voice->driver->stop_voice(voice);
   }

   _al_kcm_stream_set_mutex(voice->attached_stream, NULL);
   voice->attached_stream->parent.u.voice = NULL;
   voice->attached_stream->spl_read = NULL;
   voice->attached_stream = NULL;

   al_unlock_mutex(voice->mutex);
}
Ejemplo n.º 3
0
/* Function: al_attach_mixer_to_voice
 */
bool al_attach_mixer_to_voice(ALLEGRO_MIXER *mixer, ALLEGRO_VOICE *voice)
{
   bool ret;

   ASSERT(voice);
   ASSERT(mixer);
   ASSERT(mixer->ss.is_mixer);

   if (voice->attached_stream)
      return false;
   if (mixer->ss.parent.u.ptr)
      return false;

   if (voice->chan_conf != mixer->ss.spl_data.chan_conf ||
         voice->frequency != mixer->ss.spl_data.frequency) {
      return false;
   }

   al_lock_mutex(voice->mutex);

   voice->attached_stream = &mixer->ss;
   ASSERT(mixer->ss.spl_read == NULL);
   mixer->ss.spl_read = _al_kcm_mixer_read;

   _al_kcm_stream_set_mutex(&mixer->ss, voice->mutex);

   mixer->ss.parent.u.voice = voice;
   mixer->ss.parent.is_voice = true;

   voice->is_streaming = true;
   voice->num_buffers = 0;
   voice->buffer_size = 0;

   if (voice->driver->start_voice(voice) != 0) {
      voice->attached_stream = NULL;
      _al_kcm_stream_set_mutex(&mixer->ss, NULL);
      mixer->ss.parent.u.voice = NULL;
      ret = false;
   }
   else {
      ret = true;
   }

   al_unlock_mutex(voice->mutex);

   return ret;
}
/* _al_kcm_stream_set_mutex:
 *  This function sets a sample's mutex pointer to the specified value. It is
 *  ALLEGRO_MIXER aware, and will recursively set any attached streams' mutex
 *  to the same value.
 */
void _al_kcm_stream_set_mutex(ALLEGRO_SAMPLE_INSTANCE *stream, ALLEGRO_MUTEX *mutex)
{
   ASSERT(stream);

   if (stream->mutex == mutex)
      return;
   stream->mutex = mutex;

   /* If this is a mixer, we need to make sure all the attached streams also
    * set the same mutex.
    */
   if (stream->is_mixer) {
      ALLEGRO_MIXER *mixer = (ALLEGRO_MIXER *)stream;
      int i;

      for (i = _al_vector_size(&mixer->streams) - 1; i >= 0; i--) {
         ALLEGRO_SAMPLE_INSTANCE **slot = _al_vector_ref(&mixer->streams, i);
         ALLEGRO_SAMPLE_INSTANCE *spl = *slot;
         _al_kcm_stream_set_mutex(spl, mutex);
      }
   }
}
Ejemplo n.º 5
0
/* _al_kcm_detach_from_parent:
 *  This detaches the sample, stream, or mixer from anything it may be attached
 *  to.
 */
void _al_kcm_detach_from_parent(ALLEGRO_SAMPLE_INSTANCE *spl)
{
    ALLEGRO_MIXER *mixer;
    int i;

    if (!spl || !spl->parent.u.ptr)
        return;

    if (spl->parent.is_voice) {
        al_detach_voice(spl->parent.u.voice);
        return;
    }

    mixer = spl->parent.u.mixer;

    /* Search through the streams and check for this one */
    for (i = _al_vector_size(&mixer->streams) - 1; i >= 0; i--) {
        ALLEGRO_SAMPLE_INSTANCE **slot = _al_vector_ref(&mixer->streams, i);

        if (*slot == spl) {
            maybe_lock_mutex(mixer->ss.mutex);

            _al_vector_delete_at(&mixer->streams, i);
            spl->parent.u.mixer = NULL;
            _al_kcm_stream_set_mutex(spl, NULL);

            if (spl->spl_read != _al_kcm_mixer_read)
                spl->spl_read = NULL;

            maybe_unlock_mutex(mixer->ss.mutex);

            break;
        }
    }

    free(spl->matrix);
    spl->matrix = NULL;
}
Ejemplo n.º 6
0
/* Function: al_attach_audio_stream_to_voice
 */
bool al_attach_audio_stream_to_voice(ALLEGRO_AUDIO_STREAM *stream,
   ALLEGRO_VOICE *voice)
{
   bool ret;

   ASSERT(voice);
   ASSERT(stream);

   if (voice->attached_stream) {
      _al_set_error(ALLEGRO_INVALID_OBJECT,
         "Attempted to attach to a voice that already has an attachment");
      return false;
   }

   if (stream->spl.parent.u.ptr) {
      _al_set_error(ALLEGRO_INVALID_OBJECT,
         "Attempted to attach a stream that is already attached");
      return false;
   }

   if (voice->chan_conf != stream->spl.spl_data.chan_conf ||
      voice->frequency != stream->spl.spl_data.frequency ||
      voice->depth != stream->spl.spl_data.depth)
   {
      _al_set_error(ALLEGRO_INVALID_OBJECT,
         "Stream settings do not match voice settings");
      return false;
   }

   al_lock_mutex(voice->mutex);

   voice->attached_stream = &stream->spl;

   _al_kcm_stream_set_mutex(&stream->spl, voice->mutex);

   stream->spl.parent.u.voice = voice;
   stream->spl.parent.is_voice = true;

   voice->is_streaming = true;
   voice->num_buffers = stream->buf_count;
   voice->buffer_size = (stream->spl.spl_data.len) *
                        al_get_channel_count(stream->spl.spl_data.chan_conf) *
                        al_get_audio_depth_size(stream->spl.spl_data.depth);

   ASSERT(stream->spl.spl_read == NULL);
   stream->spl.spl_read = stream_read;

   if (voice->driver->start_voice(voice) != 0) {
      voice->attached_stream = NULL;
      _al_kcm_stream_set_mutex(&stream->spl, NULL);
      stream->spl.parent.u.voice = NULL;
      stream->spl.spl_read = NULL;

      _al_set_error(ALLEGRO_GENERIC_ERROR, "Unable to start stream");
      ret = false;
   }
   else {
      ret = true;
   }

   al_unlock_mutex(voice->mutex);

   return ret;
}
Ejemplo n.º 7
0
/* Function: al_attach_sample_instance_to_voice
 */
bool al_attach_sample_instance_to_voice(ALLEGRO_SAMPLE_INSTANCE *spl,
   ALLEGRO_VOICE *voice)
{
   bool ret;

   ASSERT(voice);
   ASSERT(spl);

   if (voice->attached_stream) {
      ALLEGRO_WARN(
         "Attempted to attach to a voice that already has an attachment\n");
      _al_set_error(ALLEGRO_INVALID_OBJECT,
         "Attempted to attach to a voice that already has an attachment");
      return false;
   }

   if (spl->parent.u.ptr) {
      ALLEGRO_WARN("Attempted to attach a sample that is already attached\n");
      _al_set_error(ALLEGRO_INVALID_OBJECT,
         "Attempted to attach a sample that is already attached");
      return false;
   }

   if (voice->chan_conf != spl->spl_data.chan_conf ||
      voice->frequency != spl->spl_data.frequency ||
      voice->depth != spl->spl_data.depth)
   {
      ALLEGRO_WARN("Sample settings do not match voice settings\n");
      _al_set_error(ALLEGRO_INVALID_OBJECT,
         "Sample settings do not match voice settings");
      return false;
   }

   al_lock_mutex(voice->mutex);

   voice->attached_stream = spl;

   voice->is_streaming = false;
   voice->num_buffers = 1;
   voice->buffer_size = (spl->spl_data.len) *
                        al_get_channel_count(voice->chan_conf) *
                        al_get_audio_depth_size(voice->depth);

   spl->spl_read = NULL;
   _al_kcm_stream_set_mutex(spl, voice->mutex);

   spl->parent.u.voice = voice;
   spl->parent.is_voice = true;

   if (voice->driver->load_voice(voice, spl->spl_data.buffer.ptr) != 0 ||
      (spl->is_playing && voice->driver->start_voice(voice) != 0))
   {      
      voice->attached_stream = NULL;
      spl->spl_read = NULL;
      _al_kcm_stream_set_mutex(spl, NULL);
      spl->parent.u.voice = NULL;

      ALLEGRO_ERROR("Unable to load sample into voice\n");
      ret = false;
   }
   else {
      ret = true;
   }

   al_unlock_mutex(voice->mutex);

   return ret;
}