+/*
+ Copyright (C) 2012 Paul Davis
+ Author: 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.
+*/
+
#ifndef MIDNAM_PATCH_H_
#define MIDNAM_PATCH_H_
-#include "pbd/stateful.h"
-#include "midi++/event.h"
-#include "pbd/xml++.h"
-
+#include <algorithm>
+#include <iostream>
#include <string>
#include <list>
#include <set>
+#include <map>
+#include <vector>
+
+#include <stdint.h>
+
+#include "midi++/libmidi_visibility.h"
+#include "midi++/event.h"
+#include "pbd/xml++.h"
namespace MIDI
{
namespace Name
{
-class Patch : public PBD::Stateful
+struct LIBMIDIPP_API PatchPrimaryKey
{
public:
- typedef std::list<Evoral::Event> PatchMidiCommands;
+ int bank_number;
+ int program_number;
- Patch() {};
- Patch(string a_number, string a_name) : _number(a_number), _name(a_name) {};
- ~Patch() {};
+ PatchPrimaryKey (uint8_t a_program_number = 0, uint16_t a_bank_number = 0) {
+ bank_number = std::min (a_bank_number, (uint16_t) 16384);
+ program_number = std::min (a_program_number, (uint8_t) 127);
+ }
+
+ bool is_sane() const {
+ return ((bank_number >= 0) && (bank_number <= 16384) &&
+ (program_number >=0 ) && (program_number <= 127));
+ }
+
+ inline PatchPrimaryKey& operator=(const PatchPrimaryKey& id) {
+ bank_number = id.bank_number;
+ program_number = id.program_number;
+ return *this;
+ }
+
+ inline bool operator==(const PatchPrimaryKey& id) const {
+ return (bank_number == id.bank_number && program_number == id.program_number);
+ }
+
+ /**
+ * obey strict weak ordering or crash in STL containers
+ */
+ inline bool operator<(const PatchPrimaryKey& id) const {
+ if (bank_number < id.bank_number) {
+ return true;
+ } else if (bank_number == id.bank_number && program_number < id.program_number) {
+ return true;
+ }
+
+ return false;
+ }
+};
+
+class PatchBank;
+
+class LIBMIDIPP_API Patch
+{
+public:
+
+ Patch (std::string a_name = std::string(), uint8_t a_number = 0, uint16_t bank_number = 0);
+ virtual ~Patch() {};
+
+ const std::string& name() const { return _name; }
+ void set_name(const std::string& name) { _name = name; }
+
+ const std::string& note_list_name() const { return _note_list_name; }
- const string& name() const { return _name; }
- void set_name(const string a_name) { _name = a_name; }
+ uint8_t program_number() const { return _id.program_number; }
+ void set_program_number(uint8_t n) { _id.program_number = n; }
- const string& number() const { return _number; }
- void set_number(const string a_number) { _number = a_number; }
+ uint16_t bank_number() const { return _id.bank_number; }
+ void set_bank_number (uint16_t n) { _id.bank_number = n; }
- const PatchMidiCommands& patch_midi_commands() const { return _patch_midi_commands; }
+ const PatchPrimaryKey& patch_primary_key() const { return _id; }
XMLNode& get_state (void);
- int set_state (const XMLNode& a_node);
+ int set_state (const XMLTree&, const XMLNode&);
private:
- string _number;
- string _name;
- PatchMidiCommands _patch_midi_commands;
+ std::string _name;
+ PatchPrimaryKey _id;
+ std::string _note_list_name;
};
-class PatchBank : public PBD::Stateful
+typedef std::list<boost::shared_ptr<Patch> > PatchNameList;
+
+class LIBMIDIPP_API PatchBank
{
public:
- typedef std::list<Patch> PatchNameList;
+ PatchBank (uint16_t n = 0, std::string a_name = std::string()) : _name(a_name), _number (n) {};
+ virtual ~PatchBank() { }
- PatchBank() {};
- virtual ~PatchBank() {};
- PatchBank(string a_name) : _name(a_name) {};
+ const std::string& name() const { return _name; }
+ void set_name(const std::string& a_name) { _name = a_name; }
- const string& name() const { return _name; }
- void set_name(const string a_name) { _name = a_name; }
+ int number() const { return _number; }
const PatchNameList& patch_name_list() const { return _patch_name_list; }
+ const std::string& patch_list_name() const { return _patch_list_name; }
+
+ int set_patch_name_list (const PatchNameList&);
XMLNode& get_state (void);
- int set_state (const XMLNode& a_node);
+ int set_state (const XMLTree&, const XMLNode&);
private:
- string _name;
- PatchNameList _patch_name_list;
+ std::string _name;
+ uint16_t _number;
+ PatchNameList _patch_name_list;
+ std::string _patch_list_name;
};
-class ChannelNameSet : public PBD::Stateful
+class LIBMIDIPP_API ChannelNameSet
{
public:
- typedef std::set<uint8_t> AvailableForChannels;
- typedef std::list<PatchBank> PatchBanks;
+ typedef std::set<uint8_t> AvailableForChannels;
+ typedef std::list<boost::shared_ptr<PatchBank> > PatchBanks;
+ typedef std::map<PatchPrimaryKey, boost::shared_ptr<Patch> > PatchMap;
+ typedef std::list<PatchPrimaryKey> PatchList;
ChannelNameSet() {};
virtual ~ChannelNameSet() {};
- ChannelNameSet(string a_name) : _name(a_name) {};
+ ChannelNameSet(std::string& name) : _name(name) {};
- const string& name() const { return _name; }
- void set_name(const string a_name) { _name = a_name; }
+ const std::string& name() const { return _name; }
+ void set_name(const std::string& name) { _name = name; }
+
+ const PatchBanks& patch_banks() const { return _patch_banks; }
- const AvailableForChannels& available_for_channels() const { return _available_for_channels; }
- 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<Patch> find_patch(const PatchPrimaryKey& key) {
+ assert(key.is_sane());
+ return _patch_map[key];
+ }
+
+ boost::shared_ptr<Patch> previous_patch(const PatchPrimaryKey& key) {
+ assert(key.is_sane());
+ for (PatchList::const_iterator i = _patch_list.begin();
+ i != _patch_list.end();
+ ++i) {
+ if ((*i) == key) {
+ if (i != _patch_list.begin()) {
+ --i;
+ return _patch_map[*i];
+ }
+ }
+ }
+
+ return boost::shared_ptr<Patch>();
+ }
+
+ boost::shared_ptr<Patch> next_patch(const PatchPrimaryKey& key) {
+ assert(key.is_sane());
+ for (PatchList::const_iterator i = _patch_list.begin();
+ i != _patch_list.end();
+ ++i) {
+ if ((*i) == key) {
+ if (++i != _patch_list.end()) {
+ return _patch_map[*i];
+ } else {
+ --i;
+ }
+ }
+ }
+
+ return boost::shared_ptr<Patch>();
+ }
+
+ const std::string& note_list_name() const { return _note_list_name; }
+ const std::string& control_list_name() const { return _control_list_name; }
XMLNode& get_state (void);
- int set_state (const XMLNode& a_node);
+ int set_state (const XMLTree&, const XMLNode&);
+
+ void set_patch_banks (const PatchBanks&);
+ void use_patch_name_list (const PatchNameList&);
private:
- string _name;
+ friend std::ostream& operator<< (std::ostream&, const ChannelNameSet&);
+
+ std::string _name;
AvailableForChannels _available_for_channels;
PatchBanks _patch_banks;
+ PatchMap _patch_map;
+ PatchList _patch_list;
+ std::string _patch_list_name;
+ std::string _note_list_name;
+ std::string _control_list_name;
};
-class Note : public PBD::Stateful
+std::ostream& operator<< (std::ostream&, const ChannelNameSet&);
+
+class LIBMIDIPP_API Note
{
public:
- Note() {};
- Note(string a_number, string a_name) : _number(a_number), _name(a_name) {};
- ~Note() {};
+ Note() {}
+ Note(uint8_t number, const std::string& name) : _number(number), _name(name) {}
- const string& name() const { return _name; }
- void set_name(const string a_name) { _name = a_name; }
+ const std::string& name() const { return _name; }
+ void set_name(const std::string& name) { _name = name; }
- const string& number() const { return _number; }
- void set_number(const string a_number) { _number = a_number; }
+ uint8_t number() const { return _number; }
+ void set_number(uint8_t number) { _number = number; }
XMLNode& get_state (void);
- int set_state (const XMLNode& a_node);
+ int set_state (const XMLTree&, const XMLNode&);
+
+private:
+ uint8_t _number;
+ std::string _name;
+};
+
+class LIBMIDIPP_API NoteNameList
+{
+public:
+ typedef std::vector< boost::shared_ptr<Note> > Notes;
+
+ NoteNameList() { _notes.resize(128); }
+ NoteNameList (const std::string& name) : _name(name) { _notes.resize(128); }
+
+ const std::string& name() const { return _name; }
+ const Notes& notes() const { return _notes; }
+
+ void set_name(const std::string& name) { _name = name; }
+
+ XMLNode& get_state (void);
+ int set_state (const XMLTree&, const XMLNode&);
+
+private:
+ std::string _name;
+ Notes _notes;
+};
+
+class LIBMIDIPP_API Value
+{
+public:
+ Value() {}
+ Value(const uint16_t number,
+ const std::string& name)
+ : _number(number)
+ , _name(name)
+ {}
+
+ uint16_t number() const { return _number; }
+ const std::string& name() const { return _name; }
+
+ void set_number(uint16_t number) { _number = number; }
+ void set_name(const std::string& name) { _name = name; }
+
+ XMLNode& get_state(void);
+ int set_state(const XMLTree&, const XMLNode&);
+
+private:
+ uint16_t _number;
+ std::string _name;
+};
+
+class LIBMIDIPP_API ValueNameList
+{
+public:
+ typedef std::map<uint16_t, boost::shared_ptr<Value> > Values;
+
+ ValueNameList() {}
+ ValueNameList(const std::string& name) : _name(name) {}
+
+ const std::string& name() const { return _name; }
+
+ void set_name(const std::string& name) { _name = name; }
+
+ boost::shared_ptr<const Value> value(uint16_t num) const;
+ boost::shared_ptr<const Value> max_value_below(uint16_t num) const;
+
+ const Values& values() const { return _values; }
+
+ XMLNode& get_state(void);
+ int set_state(const XMLTree&, const XMLNode&);
+
+private:
+ std::string _name;
+ Values _values;
+};
+
+class LIBMIDIPP_API Control
+{
+public:
+ Control() {}
+ Control(const std::string& type,
+ const uint16_t number,
+ const std::string& name)
+ : _type(type)
+ , _number(number)
+ , _name(name)
+ {}
+
+ const std::string& type() const { return _type; }
+ uint16_t number() const { return _number; }
+ const std::string& name() const { return _name; }
+
+ const std::string& value_name_list_name() const { return _value_name_list_name; }
+ boost::shared_ptr<const ValueNameList> value_name_list() const { return _value_name_list; }
+
+ void set_type(const std::string& type) { _type = type; }
+ void set_number(uint16_t number) { _number = number; }
+ void set_name(const std::string& name) { _name = name; }
+
+ XMLNode& get_state(void);
+ int set_state(const XMLTree&, const XMLNode&);
+
+private:
+ std::string _type;
+ uint16_t _number;
+ std::string _name;
+
+ std::string _value_name_list_name; ///< Global, UsesValueNameList
+ boost::shared_ptr<ValueNameList> _value_name_list; ///< Local, ValueNameList
+};
+
+class LIBMIDIPP_API ControlNameList
+{
+public:
+ typedef std::map<uint16_t, boost::shared_ptr<Control> > Controls;
+
+ ControlNameList() {}
+ ControlNameList(const std::string& name) : _name(name) {}
+
+ const std::string& name() const { return _name; }
+
+ void set_name(const std::string& name) { _name = name; }
+
+ boost::shared_ptr<const Control> control(uint16_t num) const;
+
+ const Controls& controls() const { return _controls; }
+
+ XMLNode& get_state(void);
+ int set_state(const XMLTree&, const XMLNode&);
private:
- string _number;
- string _name;
+ std::string _name;
+ Controls _controls;
};
-class CustomDeviceMode : public PBD::Stateful
+class LIBMIDIPP_API CustomDeviceMode
{
public:
CustomDeviceMode() {};
virtual ~CustomDeviceMode() {};
- const string& name() const { return _name; }
- void set_name(const string a_name) { _name = a_name; }
+ const std::string& name() const { return _name; }
+ void set_name(const std::string& name) { _name = name; }
XMLNode& get_state (void);
- int set_state (const XMLNode& a_node);
+ int set_state (const XMLTree&, const XMLNode&);
+
+ /// Note: channel here is 0-based while in the MIDNAM-file it's 1-based
+ const std::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];
+ std::string _name;
+ std::string _channel_name_set_assignments[16];
};
-class MasterDeviceNames : public PBD::Stateful
+class LIBMIDIPP_API MasterDeviceNames
{
public:
- typedef std::list<ChannelNameSet> ChannelNameSets;
- typedef std::list<std::string> Models;
+ typedef std::set<std::string> Models;
+ /// maps name to CustomDeviceMode
+ typedef std::map<std::string, boost::shared_ptr<CustomDeviceMode> > CustomDeviceModes;
+ typedef std::list<std::string> CustomDeviceModeNames;
+ /// maps name to ChannelNameSet
+ typedef std::map<std::string, boost::shared_ptr<ChannelNameSet> > ChannelNameSets;
+ typedef std::map<std::string, boost::shared_ptr<NoteNameList> > NoteNameLists;
+ typedef std::map<std::string, boost::shared_ptr<ControlNameList> > ControlNameLists;
+ typedef std::map<std::string, boost::shared_ptr<ValueNameList> > ValueNameLists;
+ typedef std::map<std::string, PatchNameList> PatchNameLists;
MasterDeviceNames() {};
virtual ~MasterDeviceNames() {};
- const string& manufacturer() const { return _manufacturer; }
- void set_manufacturer(const string a_manufacturer) { _manufacturer = a_manufacturer; }
+ const std::string& manufacturer() const { return _manufacturer; }
+ void set_manufacturer(const std::string& manufacturer) { _manufacturer = manufacturer; }
const Models& models() const { return _models; }
void set_models(const Models some_models) { _models = some_models; }
+
+ const ControlNameLists& controls() const { return _control_name_lists; }
+ const ValueNameLists& values() const { return _value_name_lists; }
+
+ boost::shared_ptr<const ValueNameList> value_name_list_by_control(
+ const std::string& mode,
+ uint8_t channel,
+ uint8_t number);
+
+ const CustomDeviceModeNames& custom_device_mode_names() const { return _custom_device_mode_names; }
+ boost::shared_ptr<CustomDeviceMode> custom_device_mode_by_name(const std::string& mode_name);
+ boost::shared_ptr<ChannelNameSet> channel_name_set_by_channel(const std::string& mode, uint8_t channel);
+ boost::shared_ptr<Patch> find_patch(const std::string& mode, uint8_t channel, const PatchPrimaryKey& key);
+
+ boost::shared_ptr<ControlNameList> control_name_list(const std::string& name);
+ boost::shared_ptr<ValueNameList> value_name_list(const std::string& name);
+ boost::shared_ptr<NoteNameList> note_name_list(const std::string& name);
+ boost::shared_ptr<ChannelNameSet> channel_name_set(const std::string& name);
+
+ std::string note_name(const std::string& mode_name,
+ uint8_t channel,
+ uint16_t bank,
+ uint8_t program,
+ uint8_t number);
+
XMLNode& get_state (void);
- int set_state (const XMLNode& a_node);
+ int set_state (const XMLTree&, const XMLNode&);
private:
- string _manufacturer;
- Models _models;
- ChannelNameSets _channel_name_sets;
+ std::string _manufacturer;
+ Models _models;
+ CustomDeviceModes _custom_device_modes;
+ CustomDeviceModeNames _custom_device_mode_names;
+ ChannelNameSets _channel_name_sets;
+ NoteNameLists _note_name_lists;
+ PatchNameLists _patch_name_lists;
+ ControlNameLists _control_name_lists;
+ ValueNameLists _value_name_lists;
};
-class MIDINameDocument : public PBD::Stateful
+class LIBMIDIPP_API MIDINameDocument
{
public:
- MIDINameDocument() {};
+ // Maps Model names to MasterDeviceNames
+ typedef std::map<std::string, boost::shared_ptr<MasterDeviceNames> > MasterDeviceNamesList;
+
+ MIDINameDocument() {}
+ MIDINameDocument(const std::string& filename);
virtual ~MIDINameDocument() {};
+ const std::string& author() const { return _author; }
+ void set_author(const std::string& author) { _author = author; }
+
+ boost::shared_ptr<MasterDeviceNames> master_device_names(const std::string& model);
+
+ 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);
+ int set_state (const XMLTree&, const XMLNode&);
private:
- string _author;
-
+ std::string _author;
+ MasterDeviceNamesList _master_device_names_list;
+ XMLTree _document;
+ MasterDeviceNames::Models _all_models;
};
+LIBMIDIPP_API extern const char* general_midi_program_names[128]; /* 0 .. 127 */
+
}
}