2008-12-08 04:50:19 -05:00
|
|
|
/*
|
2012-10-08 00:32:12 -04:00
|
|
|
Copyright (C) 2012 Paul Davis
|
|
|
|
Author: Hans Baier
|
2008-12-08 04:50:19 -05:00
|
|
|
|
|
|
|
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$
|
|
|
|
*/
|
|
|
|
|
2008-06-02 17:41:35 -04:00
|
|
|
#ifndef MIDNAM_PATCH_H_
|
|
|
|
#define MIDNAM_PATCH_H_
|
|
|
|
|
2012-06-12 00:05:10 -04:00
|
|
|
#include <algorithm>
|
2012-06-02 10:50:09 -04:00
|
|
|
#include <iostream>
|
2008-06-02 17:41:35 -04:00
|
|
|
#include <string>
|
2008-12-05 23:43:11 -05:00
|
|
|
#include <list>
|
2008-06-02 17:41:35 -04:00
|
|
|
#include <set>
|
2008-12-09 02:42:19 -05:00
|
|
|
#include <map>
|
2008-06-02 17:41:35 -04:00
|
|
|
|
2012-06-12 00:05:10 -04:00
|
|
|
#include <stdint.h>
|
|
|
|
|
2008-12-08 04:50:19 -05:00
|
|
|
#include "midi++/event.h"
|
|
|
|
#include "pbd/xml++.h"
|
|
|
|
|
2008-06-02 17:41:35 -04:00
|
|
|
namespace MIDI
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace Name
|
|
|
|
{
|
|
|
|
|
2008-12-10 05:54:45 -05:00
|
|
|
struct PatchPrimaryKey
|
|
|
|
{
|
|
|
|
public:
|
2012-10-08 23:09:54 -04:00
|
|
|
int bank_number;
|
2008-12-10 05:54:45 -05:00
|
|
|
int program_number;
|
2012-10-08 23:09:54 -04:00
|
|
|
|
|
|
|
PatchPrimaryKey (uint8_t a_program_number = 0, uint16_t a_bank_number = 0) {
|
2012-06-12 00:05:10 -04:00
|
|
|
bank_number = std::min (a_bank_number, (uint16_t) 16384);
|
|
|
|
program_number = std::min (a_program_number, (uint8_t) 127);
|
2008-12-10 05:54:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
bool is_sane() {
|
2012-06-10 12:42:17 -04:00
|
|
|
return ((bank_number >= 0) && (bank_number <= 16384) &&
|
2008-12-13 09:02:28 -05:00
|
|
|
(program_number >=0 ) && (program_number <= 127));
|
2008-12-10 05:54:45 -05:00
|
|
|
}
|
|
|
|
|
2008-12-12 00:17:53 -05:00
|
|
|
inline PatchPrimaryKey& operator=(const PatchPrimaryKey& id) {
|
2012-06-10 12:42:17 -04:00
|
|
|
bank_number = id.bank_number;
|
2008-12-12 00:17:53 -05:00
|
|
|
program_number = id.program_number;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2008-12-10 05:54:45 -05:00
|
|
|
inline bool operator==(const PatchPrimaryKey& id) const {
|
2012-06-10 12:42:17 -04:00
|
|
|
return (bank_number == id.bank_number && program_number == id.program_number);
|
2008-12-10 05:54:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* obey strict weak ordering or crash in STL containers
|
|
|
|
*/
|
|
|
|
inline bool operator<(const PatchPrimaryKey& id) const {
|
2012-06-10 12:42:17 -04:00
|
|
|
if (bank_number < id.bank_number) {
|
2008-12-10 05:54:45 -05:00
|
|
|
return true;
|
2012-06-10 12:42:17 -04:00
|
|
|
} else if (bank_number == id.bank_number && program_number < id.program_number) {
|
2008-12-10 05:54:45 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-01-14 22:13:24 -05:00
|
|
|
class PatchBank;
|
|
|
|
|
2012-03-20 14:01:59 -04:00
|
|
|
class Patch
|
2008-06-02 17:41:35 -04:00
|
|
|
{
|
|
|
|
public:
|
2008-08-04 18:37:24 -04:00
|
|
|
|
2012-10-08 23:09:54 -04:00
|
|
|
Patch (std::string a_name = std::string(), uint8_t a_number = 0, uint16_t bank_number = 0);
|
2009-01-14 22:13:24 -05:00
|
|
|
virtual ~Patch() {};
|
2008-08-04 18:37:24 -04:00
|
|
|
|
2009-05-12 13:03:42 -04:00
|
|
|
const std::string& name() const { return _name; }
|
|
|
|
void set_name(const std::string a_name) { _name = a_name; }
|
2008-08-04 18:37:24 -04:00
|
|
|
|
2012-06-12 00:05:10 -04:00
|
|
|
uint8_t program_number() const { return _id.program_number; }
|
|
|
|
void set_program_number(uint8_t n) { _id.program_number = n; }
|
|
|
|
|
|
|
|
uint16_t bank_number() const { return _id.bank_number; }
|
2012-10-08 23:09:54 -04:00
|
|
|
void set_bank_number (uint16_t n) { _id.bank_number = n; }
|
2012-06-12 00:05:10 -04:00
|
|
|
|
2008-12-10 05:54:45 -05:00
|
|
|
const PatchPrimaryKey& patch_primary_key() const { return _id; }
|
2008-08-04 18:37:24 -04:00
|
|
|
|
2012-10-08 23:09:54 -04:00
|
|
|
XMLNode& get_state (void);
|
2012-03-20 14:01:59 -04:00
|
|
|
int set_state (const XMLTree&, const XMLNode&);
|
|
|
|
|
2008-06-02 17:41:35 -04:00
|
|
|
private:
|
2012-06-12 00:05:10 -04:00
|
|
|
std::string _name;
|
|
|
|
PatchPrimaryKey _id;
|
2008-06-02 17:41:35 -04:00
|
|
|
};
|
|
|
|
|
2012-03-20 14:01:59 -04:00
|
|
|
class PatchBank
|
2008-06-02 17:41:35 -04:00
|
|
|
{
|
|
|
|
public:
|
2008-12-12 00:17:53 -05:00
|
|
|
typedef std::list<boost::shared_ptr<Patch> > PatchNameList;
|
2008-08-04 18:37:24 -04:00
|
|
|
|
2012-10-08 23:09:54 -04:00
|
|
|
PatchBank (uint16_t n = 0, std::string a_name = std::string()) : _name(a_name), _number (n) {};
|
|
|
|
virtual ~PatchBank() { }
|
2008-08-04 18:37:24 -04:00
|
|
|
|
2009-05-12 13:03:42 -04:00
|
|
|
const std::string& name() const { return _name; }
|
|
|
|
void set_name(const std::string a_name) { _name = a_name; }
|
2008-08-04 18:37:24 -04:00
|
|
|
|
2012-10-08 23:09:54 -04:00
|
|
|
int number() const { return _number; }
|
2012-06-12 00:05:10 -04:00
|
|
|
|
2008-06-02 17:41:35 -04:00
|
|
|
const PatchNameList& patch_name_list() const { return _patch_name_list; }
|
2012-03-20 14:01:59 -04:00
|
|
|
const std::string& patch_list_name() const { return _patch_list_name; }
|
|
|
|
|
|
|
|
int set_patch_name_list (const PatchNameList&);
|
|
|
|
|
2012-10-08 23:09:54 -04:00
|
|
|
XMLNode& get_state (void);
|
2012-03-20 14:01:59 -04:00
|
|
|
int set_state (const XMLTree&, const XMLNode&);
|
2008-08-04 18:37:24 -04:00
|
|
|
|
2008-06-02 17:41:35 -04:00
|
|
|
private:
|
2009-05-12 13:03:42 -04:00
|
|
|
std::string _name;
|
2012-10-08 23:09:54 -04:00
|
|
|
uint16_t _number;
|
2009-01-14 22:13:24 -05:00
|
|
|
PatchNameList _patch_name_list;
|
2012-03-20 14:01:59 -04:00
|
|
|
std::string _patch_list_name;
|
2008-06-02 17:41:35 -04:00
|
|
|
};
|
|
|
|
|
2012-03-20 14:01:59 -04:00
|
|
|
class ChannelNameSet
|
2008-06-02 17:41:35 -04:00
|
|
|
{
|
|
|
|
public:
|
2008-12-12 00:17:53 -05:00
|
|
|
typedef std::set<uint8_t> AvailableForChannels;
|
|
|
|
typedef std::list<boost::shared_ptr<PatchBank> > PatchBanks;
|
|
|
|
typedef std::map<PatchPrimaryKey, boost::shared_ptr<Patch> > PatchMap;
|
2008-12-15 06:05:41 -05:00
|
|
|
typedef std::list<PatchPrimaryKey> PatchList;
|
2008-08-04 18:37:24 -04:00
|
|
|
|
2008-06-02 17:41:35 -04:00
|
|
|
ChannelNameSet() {};
|
|
|
|
virtual ~ChannelNameSet() {};
|
2009-05-12 13:03:42 -04:00
|
|
|
ChannelNameSet(std::string a_name) : _name(a_name) {};
|
2008-08-04 18:37:24 -04:00
|
|
|
|
2009-05-12 13:03:42 -04:00
|
|
|
const std::string& name() const { return _name; }
|
|
|
|
void set_name(const std::string a_name) { _name = a_name; }
|
2008-12-23 01:03:45 -05:00
|
|
|
|
|
|
|
const PatchBanks& patch_banks() const { return _patch_banks; }
|
2008-08-04 18:37:24 -04:00
|
|
|
|
2008-12-10 05:54:45 -05:00
|
|
|
bool available_for_channel(uint8_t channel) const {
|
|
|
|
return _available_for_channels.find(channel) != _available_for_channels.end();
|
|
|
|
}
|
|
|
|
|
2008-12-14 17:56:44 -05:00
|
|
|
boost::shared_ptr<Patch> find_patch(PatchPrimaryKey& key) {
|
2008-12-11 03:06:27 -05:00
|
|
|
assert(key.is_sane());
|
2008-12-10 05:54:45 -05:00
|
|
|
return _patch_map[key];
|
|
|
|
}
|
2008-12-14 17:56:44 -05:00
|
|
|
|
|
|
|
boost::shared_ptr<Patch> previous_patch(PatchPrimaryKey& key) {
|
|
|
|
assert(key.is_sane());
|
2008-12-15 06:05:41 -05:00
|
|
|
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>();
|
2008-12-14 17:56:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
boost::shared_ptr<Patch> next_patch(PatchPrimaryKey& key) {
|
|
|
|
assert(key.is_sane());
|
2008-12-15 06:05:41 -05:00
|
|
|
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>();
|
2008-12-14 17:56:44 -05:00
|
|
|
}
|
2008-08-04 18:37:24 -04:00
|
|
|
|
2008-06-02 17:41:35 -04:00
|
|
|
XMLNode& get_state (void);
|
2012-03-20 14:01:59 -04:00
|
|
|
int set_state (const XMLTree&, const XMLNode&);
|
2008-08-04 18:37:24 -04:00
|
|
|
|
2012-10-08 23:09:54 -04:00
|
|
|
void set_patch_banks (const PatchBanks&);
|
|
|
|
void use_patch_name_list (const PatchBank::PatchNameList&);
|
2012-06-11 18:59:35 -04:00
|
|
|
|
2008-06-02 17:41:35 -04:00
|
|
|
private:
|
2012-10-08 23:09:54 -04:00
|
|
|
friend std::ostream& operator<< (std::ostream&, const ChannelNameSet&);
|
2009-05-12 13:03:42 -04:00
|
|
|
std::string _name;
|
2008-06-02 17:41:35 -04:00
|
|
|
AvailableForChannels _available_for_channels;
|
|
|
|
PatchBanks _patch_banks;
|
2008-12-10 05:54:45 -05:00
|
|
|
PatchMap _patch_map;
|
2008-12-15 06:05:41 -05:00
|
|
|
PatchList _patch_list;
|
2012-03-20 14:01:59 -04:00
|
|
|
std::string _patch_list_name;
|
2008-06-02 17:41:35 -04:00
|
|
|
};
|
|
|
|
|
2012-06-12 12:32:06 -04:00
|
|
|
std::ostream& operator<< (std::ostream&, const ChannelNameSet&);
|
|
|
|
|
2012-03-20 14:01:59 -04:00
|
|
|
class Note
|
2008-12-05 19:07:07 -05:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
Note() {};
|
2009-05-12 13:03:42 -04:00
|
|
|
Note(std::string a_number, std::string a_name) : _number(a_number), _name(a_name) {};
|
2008-12-05 19:07:07 -05:00
|
|
|
~Note() {};
|
|
|
|
|
2009-05-12 13:03:42 -04:00
|
|
|
const std::string& name() const { return _name; }
|
|
|
|
void set_name(const std::string a_name) { _name = a_name; }
|
2008-12-05 19:07:07 -05:00
|
|
|
|
2009-05-12 13:03:42 -04:00
|
|
|
const std::string& number() const { return _number; }
|
|
|
|
void set_number(const std::string a_number) { _number = a_number; }
|
2008-12-05 19:07:07 -05:00
|
|
|
|
|
|
|
XMLNode& get_state (void);
|
2012-03-20 14:01:59 -04:00
|
|
|
int set_state (const XMLTree&, const XMLNode&);
|
2008-12-05 19:07:07 -05:00
|
|
|
|
|
|
|
private:
|
2009-05-12 13:03:42 -04:00
|
|
|
std::string _number;
|
|
|
|
std::string _name;
|
2008-12-05 19:07:07 -05:00
|
|
|
};
|
|
|
|
|
2012-03-20 14:01:59 -04:00
|
|
|
class NoteNameList
|
2008-12-05 23:38:44 -05:00
|
|
|
{
|
|
|
|
public:
|
2008-12-12 00:17:53 -05:00
|
|
|
typedef std::list<boost::shared_ptr<Note> > Notes;
|
2008-12-05 23:38:44 -05:00
|
|
|
NoteNameList() {};
|
2009-05-12 13:03:42 -04:00
|
|
|
NoteNameList (std::string a_name) : _name(a_name) {};
|
2008-12-05 23:38:44 -05:00
|
|
|
~NoteNameList() {};
|
|
|
|
|
2009-05-12 13:03:42 -04:00
|
|
|
const std::string& name() const { return _name; }
|
|
|
|
void set_name(const std::string a_name) { _name = a_name; }
|
2008-12-05 23:38:44 -05:00
|
|
|
|
|
|
|
const Notes& notes() const { return _notes; }
|
|
|
|
|
|
|
|
XMLNode& get_state (void);
|
2012-03-20 14:01:59 -04:00
|
|
|
int set_state (const XMLTree&, const XMLNode&);
|
2008-12-05 23:38:44 -05:00
|
|
|
|
|
|
|
private:
|
2009-05-12 13:03:42 -04:00
|
|
|
std::string _name;
|
2008-12-05 23:38:44 -05:00
|
|
|
Notes _notes;
|
|
|
|
};
|
|
|
|
|
2012-03-20 14:01:59 -04:00
|
|
|
class CustomDeviceMode
|
2008-11-23 14:42:09 -05:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
CustomDeviceMode() {};
|
|
|
|
virtual ~CustomDeviceMode() {};
|
|
|
|
|
2009-05-12 13:03:42 -04:00
|
|
|
const std::string& name() const { return _name; }
|
|
|
|
void set_name(const std::string a_name) { _name = a_name; }
|
2008-11-23 14:42:09 -05:00
|
|
|
|
|
|
|
|
|
|
|
XMLNode& get_state (void);
|
2012-03-20 14:01:59 -04:00
|
|
|
int set_state (const XMLTree&, const XMLNode&);
|
2008-11-23 14:42:09 -05:00
|
|
|
|
2012-10-08 00:32:12 -04:00
|
|
|
/// Note: channel here is 0-based while in the MIDNAM-file it's 1-based
|
2009-05-12 13:03:42 -04:00
|
|
|
std::string channel_name_set_name_by_channel(uint8_t channel) {
|
2008-12-10 05:54:45 -05:00
|
|
|
assert(channel <= 15);
|
|
|
|
return _channel_name_set_assignments[channel];
|
|
|
|
}
|
|
|
|
|
2008-11-23 14:42:09 -05:00
|
|
|
private:
|
|
|
|
/// array index = channel number
|
|
|
|
/// string contents = name of channel name set
|
2009-05-12 13:03:42 -04:00
|
|
|
std::string _name;
|
|
|
|
std::string _channel_name_set_assignments[16];
|
2008-11-23 14:42:09 -05:00
|
|
|
};
|
|
|
|
|
2012-03-20 14:01:59 -04:00
|
|
|
class MasterDeviceNames
|
2008-11-23 14:42:09 -05:00
|
|
|
{
|
|
|
|
public:
|
2008-12-10 05:54:45 -05:00
|
|
|
typedef std::list<std::string> Models;
|
|
|
|
/// maps name to CustomDeviceMode
|
2008-12-12 00:17:53 -05:00
|
|
|
typedef std::map<std::string, boost::shared_ptr<CustomDeviceMode> > CustomDeviceModes;
|
2008-12-10 05:54:45 -05:00
|
|
|
typedef std::list<std::string> CustomDeviceModeNames;
|
|
|
|
/// maps name to ChannelNameSet
|
2008-12-12 00:17:53 -05:00
|
|
|
typedef std::map<std::string, boost::shared_ptr<ChannelNameSet> > ChannelNameSets;
|
|
|
|
typedef std::list<boost::shared_ptr<NoteNameList> > NoteNameLists;
|
2012-03-20 14:01:59 -04:00
|
|
|
typedef std::map<std::string, PatchBank::PatchNameList> PatchNameLists;
|
2008-11-23 14:42:09 -05:00
|
|
|
|
|
|
|
MasterDeviceNames() {};
|
|
|
|
virtual ~MasterDeviceNames() {};
|
|
|
|
|
2009-05-12 13:03:42 -04:00
|
|
|
const std::string& manufacturer() const { return _manufacturer; }
|
|
|
|
void set_manufacturer(const std::string a_manufacturer) { _manufacturer = a_manufacturer; }
|
2008-11-23 14:42:09 -05:00
|
|
|
|
|
|
|
const Models& models() const { return _models; }
|
|
|
|
void set_models(const Models some_models) { _models = some_models; }
|
|
|
|
|
2008-12-10 05:54:45 -05:00
|
|
|
const CustomDeviceModeNames& custom_device_mode_names() const { return _custom_device_mode_names; }
|
|
|
|
|
2012-10-08 23:09:54 -04:00
|
|
|
boost::shared_ptr<CustomDeviceMode> custom_device_mode_by_name(std::string mode_name);
|
|
|
|
boost::shared_ptr<ChannelNameSet> channel_name_set_by_device_mode_and_channel(std::string mode, uint8_t channel);
|
|
|
|
boost::shared_ptr<Patch> find_patch(std::string mode, uint8_t channel, PatchPrimaryKey& key);
|
2008-12-10 05:54:45 -05:00
|
|
|
|
2008-11-23 14:42:09 -05:00
|
|
|
XMLNode& get_state (void);
|
2012-03-20 14:01:59 -04:00
|
|
|
int set_state (const XMLTree&, const XMLNode&);
|
2008-11-23 14:42:09 -05:00
|
|
|
|
|
|
|
private:
|
2009-05-12 13:03:42 -04:00
|
|
|
std::string _manufacturer;
|
2008-12-10 05:54:45 -05:00
|
|
|
Models _models;
|
|
|
|
CustomDeviceModes _custom_device_modes;
|
|
|
|
CustomDeviceModeNames _custom_device_mode_names;
|
|
|
|
ChannelNameSets _channel_name_sets;
|
|
|
|
NoteNameLists _note_name_lists;
|
2012-03-20 14:01:59 -04:00
|
|
|
PatchNameLists _patch_name_lists;
|
2008-11-23 14:42:09 -05:00
|
|
|
};
|
|
|
|
|
2012-03-20 14:01:59 -04:00
|
|
|
class MIDINameDocument
|
2008-08-04 18:37:24 -04:00
|
|
|
{
|
|
|
|
public:
|
2008-12-09 02:42:19 -05:00
|
|
|
// Maps Model names to MasterDeviceNames
|
|
|
|
typedef std::map<std::string, boost::shared_ptr<MasterDeviceNames> > MasterDeviceNamesList;
|
2008-12-05 23:43:11 -05:00
|
|
|
|
2009-10-15 14:56:11 -04:00
|
|
|
MIDINameDocument() {}
|
2012-10-08 23:09:54 -04:00
|
|
|
MIDINameDocument(const std::string &filename);
|
2008-08-04 18:37:24 -04:00
|
|
|
virtual ~MIDINameDocument() {};
|
2008-06-02 17:41:35 -04:00
|
|
|
|
2009-05-12 13:03:42 -04:00
|
|
|
const std::string& author() const { return _author; }
|
|
|
|
void set_author(const std::string an_author) { _author = an_author; }
|
2008-12-06 00:00:20 -05:00
|
|
|
|
2008-12-09 02:42:19 -05:00
|
|
|
const MasterDeviceNamesList& master_device_names_by_model() const { return _master_device_names_list; }
|
|
|
|
|
|
|
|
const MasterDeviceNames::Models& all_models() const { return _all_models; }
|
2008-12-10 05:54:45 -05:00
|
|
|
|
2008-08-04 18:37:24 -04:00
|
|
|
XMLNode& get_state (void);
|
2012-03-20 14:01:59 -04:00
|
|
|
int set_state (const XMLTree&, const XMLNode&);
|
2008-08-04 18:37:24 -04:00
|
|
|
|
|
|
|
private:
|
2009-05-12 13:03:42 -04:00
|
|
|
std::string _author;
|
2008-12-09 02:42:19 -05:00
|
|
|
MasterDeviceNamesList _master_device_names_list;
|
|
|
|
XMLTree _document;
|
|
|
|
MasterDeviceNames::Models _all_models;
|
2008-08-04 18:37:24 -04:00
|
|
|
};
|
2008-06-02 17:41:35 -04:00
|
|
|
|
2012-06-11 18:59:35 -04:00
|
|
|
extern const char* general_midi_program_names[128]; /* 0 .. 127 */
|
|
|
|
|
2008-06-02 17:41:35 -04:00
|
|
|
}
|
|
|
|
|
2008-08-04 18:37:24 -04:00
|
|
|
}
|
2008-06-02 17:41:35 -04:00
|
|
|
#endif /*MIDNAM_PATCH_H_*/
|