

// This program is intended to demonstrate a possible problem in
// al_detach_voice().

#include <allegro5/allegro.h>
#include <allegro5/allegro_audio.h>
#include <stdio.h>
#include <iostream>
#include <cassert>



int main(int argc, char** argv )
{
  //std::cout << "Starting tests ..." << std::endl;

  // Initialize Allegro Base.
  double delaytime = 0.01;
  if(argc == 2)
	  delaytime = strtod(argv[1],0);

  if(!al_init())
  {
    std::cout << "al_init() failed.";
    return -1;
  }

  // Initialize Allegro Audio add-on.
  if(!al_install_audio())
  {
    std::cout << "al_install_audio() failed.";
    return -1;
  }

  // Sanity checks.
  assert(al_is_system_installed());
  assert(al_is_audio_installed());

  ALLEGRO_VOICE* pVoice = 0;
  ALLEGRO_MIXER* pMixer = 0;

  // Configuration variables.
  const unsigned int frequency = 44100;
  const ALLEGRO_CHANNEL_CONF channel_conf = ALLEGRO_CHANNEL_CONF_2;
  const ALLEGRO_AUDIO_DEPTH audio_depth = ALLEGRO_AUDIO_DEPTH_FLOAT32;

  // Create the voice and mixer.
  pVoice = al_create_voice(frequency, audio_depth, channel_conf);

  if(!pVoice)
  {
    std::cout << "al_create_voice() failed." << std::endl;
    return -1;
  }

  assert(pVoice);

  pMixer = al_create_mixer(frequency, audio_depth, channel_conf);

  if(!pMixer)
  {
    std::cout << "al_create_mixer() failed." << std::endl;
    return -1;
  }

  // Sanity checks.
  assert(pMixer);
  assert(pVoice);

  // Perform one initial attach/detach before the main test loop. Sometimes the
  // program will hang on the very first call to al_detach_voice() or
  // al_detach_mixer().
  {
   // std::cout << "Test #0 ... ";
   // std::cout.flush();
    bool result = al_attach_mixer_to_voice(pMixer, pVoice);
    assert(result);
    al_detach_voice(pVoice);
    assert(!al_get_mixer_attached(pMixer));
   // std::cout << "\tsucceeded." << std::endl;
  }



  // Begin testing al_attach_mixer_to_voice() and al_detach_voice() multiple
  // times ...
  for(int i = 1; i <= 1000; ++i)
  {
  // std::cout << "Test #" << i << " ... ";
  // std::cout.flush();
	printf("Test #%d\r",i);
	fflush(stdout);
    bool result = al_attach_mixer_to_voice(pMixer, pVoice);
    assert(result);

    al_rest(delaytime);
    // Here is one of the troublesome functions. It hangs within its call stack.
    al_detach_voice(pVoice);

    // Calling this function instead of al_detach_voice() also demonstrates the
    // same problem.
    // al_detach_mixer(pMixer);
    al_rest(delaytime);

    assert(!al_get_mixer_attached(pMixer));
   // std::cout << "\tsucceeded." << std::endl;
  }



  // Clean up.
  assert(pMixer);
  assert(pVoice);
  al_destroy_mixer(pMixer);
  pMixer = 0;
  al_destroy_voice(pVoice);
  pVoice = 0;

  // Shutdown Allegro Audio add-on; Allegro Base.
  al_uninstall_audio();
  al_uninstall_system();

  // Sanity checks.
  assert(!al_is_system_installed());
  assert(!al_is_audio_installed());
 // std::cout << "Tests finished." << std::endl;
  return 0;
}
