/*
 * @(#)Panic.h 3.00 21 June 1999
 *
 * Copyright (c) 2000 Pete Goodliffe (pete@cthree.org)
 *
 * This file is part of TSE3 - the Trax Sequencer Engine version 3.00.
 *
 * This library is modifiable/redistributable under the terms of the GNU
 * General Public License.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; see the file COPYING. If not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 */

#ifndef TSE3_PANIC_H
#define TSE3_PANIC_H

#include "tse3/listen/Panic.h"

#include "tse3/Notifier.h"
#include "tse3/Midi.h"
#include "tse3/Playable.h"
#include "tse3/Serializable.h"

namespace TSE3
{
    /**
     * The Panic class encapsulates the playable 'panic' information that can
     * reset attached MIDI devices. This MIDI data stream is produced for a
     * single port number, which you can specify.
     *
     * Several different kinds of reset information can be sent:
     *   @li A basic MIDI reset sequence
     *   @li A GM format MIDI reset sequence
     *   @li A GS format MIDI reset sequence (to particular device IDs)
     *   @li An XG format MIDI reset sequence (to particular device IDs)
     *   @li Different MIDI protocol reset messages.
     *
     * @short   Playable 'panic' sequencer generator
     * @author  Pete Goodliffe
     * @version 3.00
     * @see     MidiData
     * @see     PhraseList
     */
    class Panic : public Playable,
                  public Notifier<PanicListener>
    {
        public:

            /**
             * Creates a Panic object with the default values. These are
             * to send basic MIDI reset and GM MIDI reset sequences.
             *
             * The default output port is MidiScheduler::AllPorts.
             */
            Panic();
            virtual ~Panic();

            /**
             * Returns the panic status: whether this panic sequence is
             * generated.
             *
             * This takes precidence over all of the other status settings;
             * if it is set to false, no MIDI events will be generated by
             * the Panic object.
             *
             * @return Whether panic sequence is generated
             * @see    setStatus
             */
            bool status() const { return _status; }

            /**
             * Sets the panic sequence.
             *
             * @param s New status value
             * @see   status
             */
            void setStatus(bool s);

            /**
             * Returns which port the object will produce output on.
             *
             * @return Output port number
             * @see    setPort
             */
            int port() const { return _port; }

            /**
             * Sets the output port for this object.
             *
             * @param port New port number
             * @see   port
             */
            void setPort(int port);

            /*
             * Various MIDI protocol reset messages
             */

            /**
             * Returns the basic MIDI reset status.
             *
             * @return Whether MIDI reset is generated
             * @see    setMidiReset
             */
            bool midiReset() const { return _midi; }

            /**
             * Sets the basic MIDI reset status.
             *
             * @param s New status value
             * @see   midiReset
             */
            void setMidiReset(bool s);

            /**
             * Returns the GM format MIDI reset status.
             *
             * @return Whether GM reset is generated
             * @see    setGmReset
             */
            bool gmReset() const { return _gm; }

            /**
             * Sets the GM format MIDI reset status.
             *
             * @param s New status value
             * @see   gmReset
             */
            void setGmReset(bool s);

            /**
             * Returns the GS format MIDI reset status.
             *
             * @return Whether GS reset is generated
             * @see    setGsReset
             */
            bool gsReset() const { return _gs; }

            /**
             * Sets the GS format MIDI reset status.
             *
             * @param s New status value
             * @see   gsReset
             */
            void setGsReset(bool s);

            /**
             * Returns the XG format MIDI reset status.
             *
             * @return Whether XG reset is generated
             * @see    setXgReset
             */
            bool xgReset() const { return _xg; }

            /**
             * Sets the XG format MIDI reset status.
             *
             * @param s New status value
             * @see   xgReset
             */
            void setXgReset(bool s);

            /**
             * Returns the device mask for a GS device.
             *
             * @param  device A GS device ID (0-31)
             * @return true if a GS reset is enabled for that device
             * @see    setGsIDMask
             */
            bool gsIDMask(size_t device) const;

            /**
             * Sets a GS device mask.
             *
             * @param s New status value
             * @see   gsIDMask
             */
            void setGsIDMask(size_t device, bool s);

            /**
             * Returns the device mask for an XG device.
             *
             * @param  device An XG device ID (0-31)
             * @return true if an XG reset is enabled for that device
             * @see    setXgIDMask
             */
            bool xgIDMask(size_t device) const;

            /**
             * Sets an XG device mask.
             *
             * @param s New status value
             * @see   xgIDMask
             */
            void setXgIDMask(size_t device, bool s);

            /*
             * MIDI protocol messages.
             */

            /**
             * Whether to send a MidiControl_AllNotesOff.
             *
             * @return Whether MidiControl_AllNotesOff is generated
             * @see    setAllNotesOff
             */
            bool allNotesOff() { return _allNotesOff; }

            /**
             * Set whether to send a MidiControl_AllNotesOff.
             *
             * @param s New status value
             * @see   allNotesOff
             */
            void setAllNotesOff(bool s);

            /**
             * Whether to send a MidiCommand_NoteOff for every note manually.
             *
             * @return Whether manual note offs are generated
             * @see    setAllNotesOffManually
             */
            bool allNotesOffManually() { return _allNotesOffManually; }

            /**
             * Set whether to send a MidiCommand_NoteOff for every note
             * manually.
             *
             * @param s New status value
             * @see   allNotesOffManually
             */
            void setAllNotesOffManually(bool s);

            /**
             * Whether to send a MidiControl_ModulationMSB/LSB zero.
             *
             * @return Whether MidiControl_ModulationMSB/LSB are generated
             * @see    setAllModsOff
             */
            bool allModsOff() { return _allModsOff; }

            /**
             * Set whether to send a MidiControl_ModulationMSB/LSB zero.
             *
             * @param s New status value
             * @see   allModsOff
             */
            void setAllModsOff(bool s);

            /**
             * Whether to send a MidiCommand_PitchBend zero.
             *
             * @return Whether MidiCommand_PitchBend zero is generated
             * @see    setAllPitchOff
             */
            bool allPitchOff() { return _allPitchOff; }

            /**
             * Set whether to send a MidiCommand_PitchBend zero.
             *
             * @param s New status value
             * @see   allPitchOff
             */
            void setAllPitchOff(bool s);

            /**
             * Whether to send a MidiControl_ResetAllControllers.
             *
             * @return Whether MidiControl_ResetAllControllers is generated
             * @see    setAllCtrlOff
             */
            bool allCtrlOff() { return _allCtrlOff; }

            /**
             * Set whether to send a MidiControl_ResetAllControllers.
             *
             * @param s New status value
             * @see   allCtrlOff
             */
            void setAllCtrlOff(bool s);

            /**
             * Whether to send a list MidiControl_SustainPedal.
             *
             * @return Whether MidiControll_SustainPedal lift is generated
             * @see    setLiftSustain
             */
            bool liftSustain() { return _liftSustain; }

            /**
             * Set whether to send a list MidiControl_SustainPedal.
             *
             * @param s New status value
             * @see   liftSustain
             */
            void setLiftSustain(bool s);

            /**
             * @reimplemented
             */
            virtual PlayableIterator *iterator(Clock index);

            /**
             * @reimplemented
             */
            virtual Clock lastClock() const;

        protected:

            bool _status;

            int _port;

            // Various MIDI protocol resets
            bool         _midi, _gm, _gs, _xg;
            unsigned int gsMask, xgMask;

            // MIDI protocol messages
            bool _allNotesOff;
            bool _allNotesOffManually;
            bool _allModsOff;
            bool _allPitchOff;
            bool _allCtrlOff;
            bool _liftSustain;

        private:

            Panic &operator=(const Panic &);
            Panic(const Panic &);
    };
}

#endif
