@@ -516,7 +516,7 @@ class AbstractExternalPlugin : public Plugin {
516
516
};
517
517
518
518
template <typename ExternalPluginType>
519
- class ExternalPlugin : public AbstractExternalPlugin {
519
+ class ExternalPlugin : public AbstractExternalPlugin , juce::AudioPlayHead {
520
520
public:
521
521
ExternalPlugin (
522
522
std::string &_pathToPluginFile,
@@ -630,6 +630,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
630
630
~ExternalPlugin () {
631
631
{
632
632
std::lock_guard<std::mutex> lock (EXTERNAL_PLUGIN_MUTEX);
633
+ if (pluginInstance) {
634
+ pluginInstance->setPlayHead (nullptr );
635
+ }
636
+
633
637
pluginInstance.reset ();
634
638
NUM_ACTIVE_EXTERNAL_PLUGINS--;
635
639
@@ -695,6 +699,9 @@ class ExternalPlugin : public AbstractExternalPlugin {
695
699
{
696
700
std::lock_guard<std::mutex> lock (EXTERNAL_PLUGIN_MUTEX);
697
701
// Delete the plugin instance itself:
702
+ if (pluginInstance) {
703
+ pluginInstance->setPlayHead (nullptr );
704
+ }
698
705
pluginInstance.reset ();
699
706
NUM_ACTIVE_EXTERNAL_PLUGINS--;
700
707
}
@@ -714,6 +721,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
714
721
loadError.toStdString ());
715
722
}
716
723
724
+ pluginInstance->setPlayHead (this );
717
725
pluginInstance->enableAllBuses ();
718
726
719
727
auto mainInputBus = pluginInstance->getBus (true , 0 );
@@ -723,6 +731,9 @@ class ExternalPlugin : public AbstractExternalPlugin {
723
731
auto exception = std::invalid_argument (
724
732
" Plugin '" + pluginInstance->getName ().toStdString () +
725
733
" ' does not produce audio output." );
734
+ if (pluginInstance) {
735
+ pluginInstance->setPlayHead (nullptr );
736
+ }
726
737
pluginInstance.reset ();
727
738
throw exception;
728
739
}
@@ -741,6 +752,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
741
752
pathToPluginFile.toStdString () + " : " +
742
753
loadError.toStdString ());
743
754
}
755
+ pluginInstance->setPlayHead (this );
744
756
}
745
757
}
746
758
@@ -912,7 +924,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
912
924
juce::AudioBuffer<float > audioBuffer (numOutputChannels, bufferSize);
913
925
audioBuffer.clear ();
914
926
927
+ currentPositionInfo.isPlaying = true ;
915
928
pluginInstance->processBlock (audioBuffer, emptyNoteBuffer);
929
+ currentPositionInfo.isPlaying = false ;
930
+ currentPositionInfo.timeInSamples += bufferSize;
916
931
auto noiseFloor = audioBuffer.getMagnitude (0 , bufferSize);
917
932
918
933
audioBuffer.clear ();
@@ -922,7 +937,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
922
937
// the messages in a MidiBuffer get erased every time we call processBlock!
923
938
{
924
939
juce::MidiBuffer noteOnBuffer (noteOn);
940
+ currentPositionInfo.isPlaying = true ;
925
941
pluginInstance->processBlock (audioBuffer, noteOnBuffer);
942
+ currentPositionInfo.isPlaying = false ;
943
+ currentPositionInfo.timeInSamples += bufferSize;
926
944
}
927
945
928
946
// Then keep pumping the message thread until we get some louder output:
@@ -945,8 +963,11 @@ class ExternalPlugin : public AbstractExternalPlugin {
945
963
946
964
audioBuffer.clear ();
947
965
{
966
+ currentPositionInfo.isPlaying = true ;
948
967
juce::MidiBuffer noteOnBuffer (noteOn);
949
968
pluginInstance->processBlock (audioBuffer, noteOnBuffer);
969
+ currentPositionInfo.isPlaying = false ;
970
+ currentPositionInfo.timeInSamples += bufferSize;
950
971
}
951
972
952
973
if (juce::Time::currentTimeMillis () >= endTime)
@@ -958,8 +979,12 @@ class ExternalPlugin : public AbstractExternalPlugin {
958
979
audioBuffer.clear ();
959
980
{
960
981
juce::MidiBuffer allNotesOffBuffer (allNotesOff);
982
+ currentPositionInfo.isPlaying = true ;
961
983
pluginInstance->processBlock (audioBuffer, allNotesOffBuffer);
984
+ currentPositionInfo.isPlaying = false ;
985
+ currentPositionInfo.timeInSamples += bufferSize;
962
986
}
987
+ currentPositionInfo.timeInSamples = 0 ;
963
988
pluginInstance->reset ();
964
989
pluginInstance->releaseResources ();
965
990
@@ -1077,6 +1102,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
1077
1102
// Force prepare() to be called again later by invalidating lastSpec:
1078
1103
lastSpec.maximumBlockSize = 0 ;
1079
1104
samplesProvided = 0 ;
1105
+ currentPositionInfo.timeInSamples = 0 ;
1080
1106
}
1081
1107
}
1082
1108
@@ -1102,6 +1128,8 @@ class ExternalPlugin : public AbstractExternalPlugin {
1102
1128
1103
1129
pluginInstance->setNonRealtime (true );
1104
1130
pluginInstance->prepareToPlay (spec.sampleRate , spec.maximumBlockSize );
1131
+ currentPositionInfo.timeInSamples = 0 ;
1132
+ currentPositionInfo.isPlaying = false ;
1105
1133
1106
1134
lastSpec = spec;
1107
1135
}
@@ -1173,8 +1201,11 @@ class ExternalPlugin : public AbstractExternalPlugin {
1173
1201
channelPointers.size (),
1174
1202
outputBlock.getNumSamples ());
1175
1203
1204
+ currentPositionInfo.isPlaying = true ;
1176
1205
pluginInstance->processBlock (audioBuffer, emptyMidiBuffer);
1206
+ currentPositionInfo.isPlaying = false ;
1177
1207
samplesProvided += outputBlock.getNumSamples ();
1208
+ currentPositionInfo.timeInSamples += outputBlock.getNumSamples ();
1178
1209
1179
1210
// To compensate for any latency added by the plugin,
1180
1211
// only tell Pedalboard to use the last _n_ samples.
@@ -1269,7 +1300,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
1269
1300
juce::MidiBuffer midiChunk;
1270
1301
midiChunk.addEvents (midiInputBuffer, i, chunkSampleCount, -i);
1271
1302
1303
+ currentPositionInfo.isPlaying = true ;
1272
1304
pluginInstance->processBlock (audioChunk, midiChunk);
1305
+ currentPositionInfo.isPlaying = false ;
1306
+ currentPositionInfo.timeInSamples += chunkSampleCount;
1273
1307
}
1274
1308
}
1275
1309
@@ -1337,6 +1371,11 @@ class ExternalPlugin : public AbstractExternalPlugin {
1337
1371
ExternalPluginReloadType reloadType = ExternalPluginReloadType::Unknown;
1338
1372
juce::PluginDescription foundPluginDescription;
1339
1373
1374
+ bool getCurrentPosition (CurrentPositionInfo &result) override {
1375
+ result = currentPositionInfo;
1376
+ return true ;
1377
+ }
1378
+
1340
1379
private:
1341
1380
std::unique_ptr<juce::AudioPluginInstance>
1342
1381
createPluginInstance (const juce::PluginDescription &foundPluginDescription,
@@ -1371,6 +1410,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
1371
1410
juce::String pathToPluginFile;
1372
1411
juce::AudioPluginFormatManager pluginFormatManager;
1373
1412
std::unique_ptr<juce::AudioPluginInstance> pluginInstance;
1413
+ juce::AudioPlayHead::CurrentPositionInfo currentPositionInfo;
1374
1414
1375
1415
long samplesProvided = 0 ;
1376
1416
float initializationTimeout = DEFAULT_INITIALIZATION_TIMEOUT_SECONDS;
0 commit comments