Click here to Skip to main content
15,885,435 members
Articles / Desktop Programming / Windows Forms

Animated Eye Candy for Programmers

Rate me:
Please Sign up or sign in to vote.
4.93/5 (82 votes)
16 Apr 2010LGPL317 min read 86.1K   7.4K   164  
A class library that allows (almost) any Control to show animations
/*
 * Audio - Audio allows sound to be played during a animation.
 * 
 * Author: Phillip Piper
 * Date: 18/01/2010 5:29 PM
 *
 * Change log:
 * 2010-01-18   JPP  - Initial version
 *
 * To do:
 *
 * Copyright (C) 2010 Phillip Piper
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * If you wish to use this code in a closed source application, please contact phillip_piper@bigfoot.com.
 */

using System;
using System.Collections.Generic;
using System.Media;
using System.IO;
using System.Reflection;
using System.Threading;

namespace BrightIdeasSoftware
{
    /// <summary>
    /// Instances of this class allow sound to be played at specified
    /// points within a animation.
    /// </summary>
    /// <remarks>
    /// <para>
    /// This class uses the SoundPlayer class internally, and thus can
    /// only handle system sounds and WAV sound files.
    /// </para>
    /// <para>A sound that is already playing cannot be paused.</para>
    /// </remarks>
    public class Audio : Animateable
    {
        #region Life and death

        /// <summary>
        /// Load a sound from a named resource.
        /// </summary>
        /// <param name="resourceName">The name of the resource including the trailing ".wav"</param>
        /// <remarks>To embed a wav file, simple add it to the project, and change "Build Action"
        /// to "Embedded Resource".</remarks>
        /// <see cref="http://msdn.microsoft.com/en-us/library/ms950960.aspx"/>
        public static Audio FromResource(string resourceName) {
            Audio sound = new Audio();
            sound.ResourceName = resourceName;
            return sound;
        }

        /// <summary>
        /// Create an empty Audio object
        /// </summary>
        public Audio() {
        }

        /// <summary>
        /// Creates an Audio object that will play the given "wav" file
        /// </summary>
        /// <param name="fileName"></param>
        public Audio(string fileName) {
            this.FileName = fileName;
        }

        /// <summary>
        /// Creates an Audio object that will play the given system sound
        /// </summary>
        /// <param name="sound"></param>
        public Audio(SystemSound sound) {
            this.SystemSound = sound;
        }

        #endregion

        #region Implementation properties

        /// <summary>
        /// Gets or sets the name of the audio file that will be played.
        /// </summary>
        protected string FileName { get; set; }
        protected SoundPlayer Player { get; set; }
        protected string ResourceName { get; set; }
        protected SystemSound SystemSound { get; set; }

        #endregion

        #region Animation methods

        /// <summary>
        /// Start the sound playing
        /// </summary>
        public override void Start() {
            // If we are supposed to play an application resource, try to load it
            if (!String.IsNullOrEmpty(this.ResourceName)) {
                Assembly executingAssembly = Assembly.GetExecutingAssembly();
                string assemblyName = executingAssembly.GetName().Name;
                Stream stream = executingAssembly.GetManifestResourceStream(assemblyName + "." + this.ResourceName);
                if (stream != null) 
                    this.Player = new SoundPlayer(stream);
            }

            if (!String.IsNullOrEmpty(this.FileName)) {
                this.Player = new SoundPlayer(this.FileName);
            }

            // We could just use Play() and let the player handle the threading for us, but:
            // - there is no builtin way to know when the sound has finished
            // - on XP (at least), using Play() on a Stream gives noise -- but PlaySync() works fine.

            this.done = false;
            Thread newThread = new Thread((ThreadStart)delegate {
                if (this.SystemSound != null)
                    this.SystemSound.Play();
                else {
                    if (this.Player != null)
                        this.Player.PlaySync();
                }
                this.done = true;
            });
            newThread.Start();
        }
        bool done;

        /// <summary>
        /// Advance the audio and return if it is done.
        /// </summary>
        /// <param name="elapsed"></param>
        /// <returns></returns>
        public override bool Tick(long elapsed) {
            return !this.done;
        }

        /// <summary>
        /// Stop the sound
        /// </summary>
        public override void Stop() {
            if (this.SystemSound != null) 
                return;

            if (this.Player != null) {
                this.Player.Stop();
                this.Player.Dispose();
                this.Player = null;
            }
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Team Leader
Australia Australia
Phillip has been playing with computers since the Apple II was the hottest home computer available. He learned the fine art of C programming and Guru meditation on the Amiga.

C# and Python are his languages of choice. Smalltalk is his mentor for simplicity and beauty. C++ is to programming what drills are to visits to the dentist.

He worked for longer than he cares to remember as Lead Programmer and System Architect of the Objective document management system. (www.objective.com)

He has lived for 10 years in northern Mozambique, teaching in villages.

He has developed high volume trading software, low volume FX trading software, and is currently working for Atlassian on HipChat.

Comments and Discussions