// -*- c-indentation-style:"stroustrup" c-basic-offset: 4 -*- /* Rosegarden A sequencer and musical notation editor. This program is Copyright 2000-2008 Guillaume Laurent <glaurent@telegraph-road.org>, Chris Cannam <cannam@all-day-breakfast.com>, Richard Bown <bownie@bownie.com> The moral right of the authors to claim authorship of this work has been asserted. 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 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #ifndef _ROSEGARDEN_MIDI_FILE_H_ #define _ROSEGARDEN_MIDI_FILE_H_ #include <fstream> #include <string> #include <list> #include <map> #include <tqobject.h> #include "Midi.h" #include "MidiEvent.h" #include "Composition.h" #include "SoundFile.h" // Conversion class for Composition to and // from MIDI Files. Despite the fact you can reuse this // object it's probably safer just to create it for a // single way conversion and then throw it away (MIDI // to Composition conversion invalidates the internal // MIDI model). // // Derived from SoundFile but still had some features // in common with it which could theoretically be moved // up into the base for use in other derived classes. // // [rwb] // // namespace Rosegarden { // Our internal MIDI structure is just a list of MidiEvents. // We use a list and not a set because we want the order of // the events to be arbitrary until we explicitly sort them // (necessary when converting Composition absolute times to // MIDI delta times). // typedef std::vector<MidiEvent *> MidiTrack; typedef std::map<unsigned int, MidiTrack> MidiComposition; class Studio; class MidiFile : public TQObject, public SoundFile { Q_OBJECT public: typedef enum { MIDI_SINGLE_TRACK_FILE = 0x00, MIDI_SIMULTANEOUS_TRACK_FILE = 0x01, MIDI_SEQUENTIAL_TRACK_FILE = 0x02, MIDI_CONVERTED_TO_APPLICATION = 0xFE, MIDI_FILE_NOT_LOADED = 0xFF } MIDIFileFormatType; typedef enum { CONVERT_REPLACE, CONVERT_AUGMENT, CONVERT_APPEND } ConversionType; MidiFile(Studio *studio); MidiFile (const std::string &fn, Studio *studio); ~MidiFile(); // Declare our virtuals // virtual bool open(); virtual bool write(); virtual void close(); int timingDivision() { return m_timingDivision; } MIDIFileFormatType format() { return m_format; } unsigned int numberOfTracks() { return m_numberOfTracks; } bool hasTimeChanges() { return m_containsTimeChanges; } // If a file open or save failed std::string getError() { return m_error; } /** * Convert a MIDI file to a Rosegarden composition. Return true * for success. */ bool convertToRosegarden(Composition &c, ConversionType type); /** * Convert a Rosegarden composition to MIDI format, storing the * result internally for later writing. */ void convertToMidi(Composition &comp); signals: void setProgress(int); void incrementProgress(int); private: int m_timingDivision; // pulses per quarter note MIDIFileFormatType m_format; unsigned int m_numberOfTracks; bool m_containsTimeChanges; // Internal counters // long m_trackByteCount; bool m_decrementCount; // Internal MidiComposition // MidiComposition m_midiComposition; std::map<int, int> m_trackChannelMap; // Clear the m_midiComposition // void clearMidiComposition(); // Split the tasks up with these top level private methods // bool parseHeader(const std::string& midiHeader); bool parseTrack(std::ifstream* midiFile, unsigned int &trackNum); bool writeHeader(std::ofstream* midiFile); bool writeTrack(std::ofstream* midiFile, unsigned int trackNum); bool consolidateNoteOffEvents(TrackId track); // Internal convenience functions // int midiBytesToInt(const std::string& bytes); long midiBytesToLong(const std::string& bytes); long getNumberFromMidiBytes(std::ifstream* midiFile, int firstByte = -1); MidiByte getMidiByte(std::ifstream* midiFile); std::string getMidiBytes(std::ifstream* midiFile, unsigned long bytes); bool skipToNextTrack(std::ifstream *midiFile); void intToMidiBytes(std::ofstream* midiFile, int number); void longToMidiBytes(std::ofstream* midiFile, unsigned long number); std::string longToVarBuffer(unsigned long number); // The pointer to the Studio for Instrument stuff // Studio *m_studio; std::string m_error; }; } #endif // _ROSEGARDEN_MIDI_FILE_H_