-
Notifications
You must be signed in to change notification settings - Fork 1
/
PyTschirpPatch.cpp
179 lines (155 loc) · 5.06 KB
/
PyTschirpPatch.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
Copyright (c) 2020 Christof Ruch. All rights reserved.
Dual licensed: Distributed under Affero GPL license by default, an MIT license is available for purchase
*/
#include "PyTschirpPatch.h"
#include "Capability.h"
#include "LayeredPatchCapability.h"
#include "DetailedParametersCapability.h"
#include "StoredPatchNameCapability.h"
#include <algorithm>
namespace py = pybind11;
PyTschirp::PyTschirp(std::shared_ptr<midikraft::Patch> p, std::weak_ptr<midikraft::Synth> synth, int layerNo) : PyTschirp(p, synth)
{
layerNo_ = layerNo;
auto layeredPatch = midikraft::Capability::hasCapability<midikraft::LayeredPatchCapability>(patch_);
if (layeredPatch) {
if (!(layerNo >= 0 && layerNo < layeredPatch->numberOfLayers())) {
throw std::runtime_error("PyTschirp: Invalid layer number given to layerName()");
}
}
}
PyTschirp::PyTschirp(std::shared_ptr<midikraft::DataFile> p, std::weak_ptr<midikraft::Synth> synth)
{
// Downcast possible?
auto correctPatch = std::dynamic_pointer_cast<midikraft::Patch>(p);
if (!correctPatch) {
throw std::runtime_error("PyTschirp: Program error: Can't downcast, wrong patch type!");
}
patch_ = correctPatch;
synth_ = synth;
}
PyTschirp::PyTschirp(std::shared_ptr<midikraft::Patch> patch)
{
patch_ = patch;
}
PyTschirpAttribute PyTschirp::get_attr(std::string const &attrName)
{
if (layerNo_ == -1) {
return PyTschirpAttribute(patch_, attrName);
}
else {
return PyTschirpAttribute(patch_, attrName, layerNo_);
}
}
void PyTschirp::set_attr(std::string const &name, std::vector<int> const &value)
{
auto attr = PyTschirpAttribute(patch_, name);
attr.set(value);
if (isChannelValid()) {
auto liveEditing = midikraft::Capability::hasCapability<midikraft::SynthParameterLiveEditCapability>(attr.def());
if (liveEditing) {
// The synth is hot... we don't know if this patch is currently selected, but let's send the nrpn or other value changing message anyway!
auto messages = liveEditing->setValueMessages(patch_, synth_.lock().get());
synth_.lock()->sendBlockOfMessagesToSynth(midiOutput(), messages);
}
}
}
void PyTschirp::set_attr(std::string const &name, int value)
{
auto attr = PyTschirpAttribute(patch_, name);
attr.set(value);
if (isChannelValid()) {
auto liveEditing = midikraft::Capability::hasCapability<midikraft::SynthParameterLiveEditCapability>(attr.def());
if (liveEditing) {
// The synth is hot... we don't know if this patch is currently selected, but let's send the nrpn or other value changing message anyway!
auto messages = liveEditing->setValueMessages(patch_, synth_.lock().get());
synth_.lock()->sendBlockOfMessagesToSynth(midiOutput(), messages);
}
}
}
std::string PyTschirp::getName()
{
if (layerNo_ == -1) {
if (!synth_.expired())
return synth_.lock()->nameForPatch(patch_);
else
return "synth expired";
}
else {
auto layeredPatch = midikraft::Capability::hasCapability<midikraft::LayeredPatchCapability>(patch_);
if (layeredPatch) {
return layeredPatch->layerName(layerNo_);
}
else {
throw std::runtime_error("PyTschirp: Program error: This is not a layered patch, but should be.");
}
}
}
void PyTschirp::setName(std::string const &newName)
{
auto storedName = midikraft::Capability::hasCapability<midikraft::StoredPatchNameCapability>(patch_);
if (patch_) {
storedName->changeNameStoredInPatch(newName);
}
}
PyTschirp PyTschirp::layer(int layerNo)
{
auto layeredPatch = midikraft::Capability::hasCapability<midikraft::LayeredPatchCapability>(patch_);
if (!layeredPatch) {
throw std::runtime_error("PyTschirp: This is not a layered patch, can't retrieve layer");
}
// Create a new Tschirp that is the same as this one, but stores a layer number and thus will reroute all calls to the layer selected
return PyTschirp(patch_, synth_, layerNo);
}
std::vector<std::string> PyTschirp::parameterNames()
{
std::vector<std::string> result;
auto params = midikraft::Capability::hasCapability<midikraft::DetailedParametersCapability>(patch_);
if (params) {
for (auto p : params->allParameterDefinitions()) {
result.push_back(p->name());
}
}
return result;
}
std::shared_ptr<midikraft::Patch> PyTschirp::patchPtr()
{
return patch_;
}
std::string PyTschirp::underscoreToSpace(std::string const &input)
{
auto copy = input;
std::replace(copy.begin(), copy.end(), '_', ' ');
return copy;
}
juce::MidiDeviceInfo PyTschirp::midiInput()
{
if (!synth_.expired()) {
auto location = midikraft::Capability::hasCapability<midikraft::MidiLocationCapability>(synth_.lock());
if (location) {
return location->midiInput();
}
}
return juce::MidiDeviceInfo();
}
juce::MidiDeviceInfo PyTschirp::midiOutput()
{
if (!synth_.expired()) {
auto location = midikraft::Capability::hasCapability<midikraft::MidiLocationCapability>(synth_.lock());
if (location) {
return location->midiOutput();
}
}
return juce::MidiDeviceInfo();
}
bool PyTschirp::isChannelValid() const
{
if (!synth_.expired()) {
auto location = midikraft::Capability::hasCapability<midikraft::MidiLocationCapability>(synth_.lock());
if (location) {
return location->channel().isValid();
}
}
return false;
}