/* Copyright (C) 2008 Hans Baier 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. 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, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. $Id$ */ #ifndef MIDNAM_PATCH_H_ #define MIDNAM_PATCH_H_ #include #include #include #include #include "pbd/stateful.h" #include "midi++/event.h" #include "pbd/xml++.h" namespace MIDI { namespace Name { struct PatchPrimaryKey { public: int msb; int lsb; int program_number; PatchPrimaryKey(int a_msb = -1, int a_lsb = -1, int a_program_number = -1) { msb = a_msb; lsb = a_lsb; program_number = a_program_number; } bool is_sane() { return ((msb >= 0) && (msb <= 127) && (lsb >= 0) && (lsb <= 127) && (program_number >=0 ) && (program_number <= 127)); } inline PatchPrimaryKey& operator=(const PatchPrimaryKey& id) { msb = id.msb; lsb = id.lsb; program_number = id.program_number; return *this; } inline bool operator==(const PatchPrimaryKey& id) const { return (msb == id.msb && lsb == id.lsb && program_number == id.program_number); } /** * obey strict weak ordering or crash in STL containers */ inline bool operator<(const PatchPrimaryKey& id) const { if (msb < id.msb) { return true; } else if (msb == id.msb && lsb < id.lsb) { return true; } else if (lsb == id.lsb && program_number < id.program_number) { return true; } return false; } }; class PatchBank; class Patch : public PBD::Stateful { public: Patch(PatchBank* a_bank = 0) : _bank(a_bank) {}; Patch(string a_number, string a_name, PatchBank* a_bank = 0) : _number(a_number), _name(a_name), _bank(a_bank) {}; virtual ~Patch() {}; const string& name() const { return _name; } void set_name(const string a_name) { _name = a_name; } const string& number() const { return _number; } void set_number(const string a_number) { _number = a_number; } const PatchPrimaryKey& patch_primary_key() const { return _id; } XMLNode& get_state (void); int set_state (const XMLNode& a_node); private: string _number; string _name; // cannot use a boost::shared_ptr here in order to avoid retain cycles PatchBank* _bank; PatchPrimaryKey _id; }; class PatchBank : public PBD::Stateful { public: typedef std::list > PatchNameList; PatchBank() : _id(0) {}; PatchBank(string a_name, PatchPrimaryKey* an_id = 0) : _name(a_name), _id(an_id) {}; virtual ~PatchBank() { delete _id; }; const string& name() const { return _name; } void set_name(const string a_name) { _name = a_name; } const PatchNameList& patch_name_list() const { return _patch_name_list; } const PatchPrimaryKey* patch_primary_key() const { return _id; } XMLNode& get_state (void); int set_state (const XMLNode& a_node); private: string _name; PatchNameList _patch_name_list; PatchPrimaryKey* _id; }; #include class ChannelNameSet : public PBD::Stateful { public: typedef std::set AvailableForChannels; typedef std::list > PatchBanks; typedef std::map > PatchMap; typedef std::list PatchList; ChannelNameSet() {}; virtual ~ChannelNameSet() {}; ChannelNameSet(string a_name) : _name(a_name) {}; const string& name() const { return _name; } void set_name(const string a_name) { _name = a_name; } const PatchBanks& patch_banks() const { return _patch_banks; } bool available_for_channel(uint8_t channel) const { return _available_for_channels.find(channel) != _available_for_channels.end(); } boost::shared_ptr find_patch(PatchPrimaryKey& key) { assert(key.is_sane()); return _patch_map[key]; } boost::shared_ptr previous_patch(PatchPrimaryKey& key) { assert(key.is_sane()); std::cerr << "finding patch with " << key.msb << "/" << key.lsb << "/" <(); } boost::shared_ptr next_patch(PatchPrimaryKey& key) { assert(key.is_sane()); std::cerr << "finding patch with " << key.msb << "/" << key.lsb << "/" <(); } XMLNode& get_state (void); int set_state (const XMLNode& a_node); private: string _name; AvailableForChannels _available_for_channels; PatchBanks _patch_banks; PatchMap _patch_map; PatchList _patch_list; }; class Note : public PBD::Stateful { public: Note() {}; Note(string a_number, string a_name) : _number(a_number), _name(a_name) {}; ~Note() {}; const string& name() const { return _name; } void set_name(const string a_name) { _name = a_name; } const string& number() const { return _number; } void set_number(const string a_number) { _number = a_number; } XMLNode& get_state (void); int set_state (const XMLNode& a_node); private: string _number; string _name; }; class NoteNameList : public PBD::Stateful { public: typedef std::list > Notes; NoteNameList() {}; NoteNameList(string a_name) : _name(a_name) {}; ~NoteNameList() {}; const string& name() const { return _name; } void set_name(const string a_name) { _name = a_name; } const Notes& notes() const { return _notes; } XMLNode& get_state (void); int set_state (const XMLNode& a_node); private: string _name; Notes _notes; }; class CustomDeviceMode : public PBD::Stateful { public: CustomDeviceMode() {}; virtual ~CustomDeviceMode() {}; const string& name() const { return _name; } void set_name(const string a_name) { _name = a_name; } XMLNode& get_state (void); int set_state (const XMLNode& a_node); string channel_name_set_name_by_channel(uint8_t channel) { assert(channel <= 15); return _channel_name_set_assignments[channel]; } private: /// array index = channel number /// string contents = name of channel name set string _name; string _channel_name_set_assignments[16]; }; class MasterDeviceNames : public PBD::Stateful { public: typedef std::list Models; /// maps name to CustomDeviceMode typedef std::map > CustomDeviceModes; typedef std::list CustomDeviceModeNames; /// maps name to ChannelNameSet typedef std::map > ChannelNameSets; typedef std::list > NoteNameLists; MasterDeviceNames() {}; virtual ~MasterDeviceNames() {}; const string& manufacturer() const { return _manufacturer; } void set_manufacturer(const string a_manufacturer) { _manufacturer = a_manufacturer; } const Models& models() const { return _models; } void set_models(const Models some_models) { _models = some_models; } const CustomDeviceModeNames& custom_device_mode_names() const { return _custom_device_mode_names; } boost::shared_ptr custom_device_mode_by_name(string mode_name) { assert(mode_name != ""); return _custom_device_modes[mode_name]; } boost::shared_ptr channel_name_set_by_device_mode_and_channel(string mode, uint8_t channel) { return _channel_name_sets[custom_device_mode_by_name(mode)->channel_name_set_name_by_channel(channel)]; } boost::shared_ptr find_patch(string mode, uint8_t channel, PatchPrimaryKey& key) { return channel_name_set_by_device_mode_and_channel(mode, channel)->find_patch(key); } XMLNode& get_state (void); int set_state (const XMLNode& a_node); private: string _manufacturer; Models _models; CustomDeviceModes _custom_device_modes; CustomDeviceModeNames _custom_device_mode_names; ChannelNameSets _channel_name_sets; NoteNameLists _note_name_lists; }; class MIDINameDocument : public PBD::Stateful { public: // Maps Model names to MasterDeviceNames typedef std::map > MasterDeviceNamesList; MIDINameDocument() {}; MIDINameDocument(const string &filename) : _document(XMLTree(filename)) { set_state(*_document.root()); }; virtual ~MIDINameDocument() {}; const string& author() const { return _author; } void set_author(const string an_author) { _author = an_author; } const MasterDeviceNamesList& master_device_names_by_model() const { return _master_device_names_list; } const MasterDeviceNames::Models& all_models() const { return _all_models; } XMLNode& get_state (void); int set_state (const XMLNode& a_node); private: string _author; MasterDeviceNamesList _master_device_names_list; XMLTree _document; MasterDeviceNames::Models _all_models; }; } } #endif /*MIDNAM_PATCH_H_*/