// Copyright 2001-2005, Danger, Inc.  All Rights Reserved.
// This file is subject to the Danger, Inc. Sample Code License,
// which is provided in the file SAMPLE_CODE_LICENSE.
// Copies are also available from http://developer.danger.com/

package com.example.AudioDemo;

/**
 * This sample program has been developed specifically to demonstrate the
 * use of audio on the device.  It will not use or demonstrate full Application 
 * functionality.  This will keep the sample shorter and simpler, and more 
 * focused upon the interesting piece, the DemoSounds object.
 * For a more complete Application example, please refer to the 
 * HelloWorld/Template app.
 * 
 * This code base starts with the 1.1 variant of the OS, as the main source of the
 * code, then has a 2.0 variant to handle the OS differences.  The only file
 * in the project that changes is the MainWindow object. The DemoSounds object 
 * itself is compatible with all OS versions.  The primary difference from 1.1
 * to 2.* is how the audio Pause operation is handled.  Under 1.1 it is
 * necessary to have a Timer object to check for the MainWindow being 
 * deactivated.  Under 2.0 and above, there are WindowScreen methods for
 * onDeactivate that can be overridden.
 * 
 * Using the correct version of the source, different versions are compiled 
 * using build variables. 
 * (e.g. -DLIB_OS_VERSION="2.0" -DBUILD_NUMBER="82508" for a hiptop2.)
 * 
 *
 * When programming using Audio, the best practice is to program and test
 * directly upon the device, and avoid the simulator.  The simulator is
 * excellent for most things, but has limited audio support.  At least half
 * of the APIs will function incorrectly, which can lead to confusion and
 * wasted time.  When in doubt, test on the device.
 * 
 * In particular, the simulator does not support compressed sounds, which are
 * necessary on the device itself.  The simulator also does not change volume
 * correctly.  Numerous sound APIs will return with unexpected errors, or
 * will apparently function, but do nothing.  For a limited subset of audio
 * the simulator may work well enough to get development started.  In order
 * to enable audio in the simulator, there must be a sysinfo.properties file 
 * in the working directory, with a "com.danger.enable_sim_audio = 2" line.
 * 
 * This sample program will function correctly upon the device itself, but 
 * shows some of the difficulties with using the simulator.  It will play
 * the background MIDI file without trouble, and start and stop that music.
 * The Torpedo sound is compressed, and will not play upon the simulator.
 * The Muting and Unmuting of system clicks does not work upon the simulator.
 * Lastly, the volume of the background music will change at funny times,
 * because sometimes it respects the 30% volume setting, and sometimes it won't.
 * 
 * To repeat: When in doubt, test on the device.
 * 
 * 
 * This sample demonstrates the following Audio techniques:
 *  1) Proper Audio resource loading/unloading, of non system sounds.
 *  2) Proper Suspend/Resume behavior when playing Audio.
 *  3) How to Mute/Unmute conflicting system sounds (like keyclicks).
 *  4) A simple way to change playback pitch using setRate().
 *  5) Proper Audio Pause behavior when system dialogs preempt the application.
 *  6) OS Version specific Pause behavior.
 */

import danger.app.Application;
import danger.util.DEBUG;
import danger.audio.Meta;

// ------------------------------------------------------------------------

/**
 * Implements the main application class.
 */
public class AudioDemo extends Application implements Resources, Commands {

	/**
	 * All instance variables are private, unless there is a good reason not to
	 * be. Good programming habits help to avoid bugs. reference: "Writing Solid
	 * Code" by Steve Maguire. Also highly recommended: "Code Complete" by Steve
	 * McConnell.
	 */
	private MainWindow mWindow;

	/**
	 * Create the main application class, which merely creates the MainWindow
	 * class from the resource specification.
	 */
	public AudioDemo() {
		DEBUG.p("...................................Audio Demo startup");

		mWindow = (MainWindow) getResources().getScreen(ID_MAIN_SCREEN);
		mWindow.show();

		// Create the audio, and start background music.
		DemoSounds.setup();
	}

	/**
	 * Upon suspend, release the sound objects. This is important because the
	 * audio resources are relatively heavy-weight, and limited. In a worst
	 * case, if enough applications were hogging resources, it could block the
	 * phone from ringing.
	 * 
	 * Upon suspend, the key-click OS sound needs to be un-muted, so that it can
	 * go back to normal operation for other apps.
	 * 
	 * Muting and unmuting does not work on the simulator.
	 */
	public void suspend() {
		DemoSounds.cleanup();
		Meta.unmuteID(Meta.FEEDBACK_KEY_ONCE);
	}

	/**
	 * Upon resume, recreate the sound objects, and restart the looping
	 * background music. This rebuilds them from scratch, because it's more
	 * device friendly to do that, than to leave them around and restart them.
	 * This is why DemoSounds is accessed in a static fashion, because it is
	 * best to avoid having multiple sound objects floating around, all using
	 * resources.
	 * 
	 * The standard key click sounds are muted during operation to avoid having
	 * them sound at the same time as the Torpedo sound. This mute should be
	 * done the whole time the application is running, not just when sounds are
	 * being played.
	 * 
	 * Mute is one of those things that does not work in the simulator, but
	 * works as expected upon the device. Be wary. If something does not seem to
	 * work correctly, be sure to try it on a device.
	 */
	public void resume() {
		Meta.muteID(Meta.FEEDBACK_KEY_ONCE);
		DemoSounds.setup();
	}
}
