@@ -471,7 +471,7 @@ class AbstractExternalPlugin : public Plugin {
471
471
};
472
472
473
473
template <typename ExternalPluginType>
474
- class ExternalPlugin : public AbstractExternalPlugin {
474
+ class ExternalPlugin : public AbstractExternalPlugin , juce::AudioPlayHead {
475
475
public:
476
476
ExternalPlugin (
477
477
std::string &_pathToPluginFile,
@@ -599,6 +599,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
599
599
~ExternalPlugin () {
600
600
{
601
601
std::lock_guard<std::mutex> lock (EXTERNAL_PLUGIN_MUTEX);
602
+ if (pluginInstance) {
603
+ pluginInstance->setPlayHead (nullptr );
604
+ }
605
+
602
606
pluginInstance.reset ();
603
607
NUM_ACTIVE_EXTERNAL_PLUGINS--;
604
608
@@ -664,6 +668,9 @@ class ExternalPlugin : public AbstractExternalPlugin {
664
668
{
665
669
std::lock_guard<std::mutex> lock (EXTERNAL_PLUGIN_MUTEX);
666
670
// Delete the plugin instance itself:
671
+ if (pluginInstance) {
672
+ pluginInstance->setPlayHead (nullptr );
673
+ }
667
674
pluginInstance.reset ();
668
675
NUM_ACTIVE_EXTERNAL_PLUGINS--;
669
676
}
@@ -683,6 +690,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
683
690
loadError.toStdString ());
684
691
}
685
692
693
+ pluginInstance->setPlayHead (this );
686
694
pluginInstance->enableAllBuses ();
687
695
688
696
auto mainInputBus = pluginInstance->getBus (true , 0 );
@@ -692,6 +700,9 @@ class ExternalPlugin : public AbstractExternalPlugin {
692
700
auto exception = std::invalid_argument (
693
701
" Plugin '" + pluginInstance->getName ().toStdString () +
694
702
" ' does not produce audio output." );
703
+ if (pluginInstance) {
704
+ pluginInstance->setPlayHead (nullptr );
705
+ }
695
706
pluginInstance.reset ();
696
707
throw exception;
697
708
}
@@ -710,6 +721,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
710
721
pathToPluginFile.toStdString () + " : " +
711
722
loadError.toStdString ());
712
723
}
724
+ pluginInstance->setPlayHead (this );
713
725
}
714
726
}
715
727
@@ -881,7 +893,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
881
893
juce::AudioBuffer<float > audioBuffer (numOutputChannels, bufferSize);
882
894
audioBuffer.clear ();
883
895
896
+ currentPositionInfo.isPlaying = true ;
884
897
pluginInstance->processBlock (audioBuffer, emptyNoteBuffer);
898
+ currentPositionInfo.isPlaying = false ;
899
+ currentPositionInfo.timeInSamples += bufferSize;
885
900
auto noiseFloor = audioBuffer.getMagnitude (0 , bufferSize);
886
901
887
902
audioBuffer.clear ();
@@ -891,7 +906,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
891
906
// the messages in a MidiBuffer get erased every time we call processBlock!
892
907
{
893
908
juce::MidiBuffer noteOnBuffer (noteOn);
909
+ currentPositionInfo.isPlaying = true ;
894
910
pluginInstance->processBlock (audioBuffer, noteOnBuffer);
911
+ currentPositionInfo.isPlaying = false ;
912
+ currentPositionInfo.timeInSamples += bufferSize;
895
913
}
896
914
897
915
// Then keep pumping the message thread until we get some louder output:
@@ -914,8 +932,11 @@ class ExternalPlugin : public AbstractExternalPlugin {
914
932
915
933
audioBuffer.clear ();
916
934
{
935
+ currentPositionInfo.isPlaying = true ;
917
936
juce::MidiBuffer noteOnBuffer (noteOn);
918
937
pluginInstance->processBlock (audioBuffer, noteOnBuffer);
938
+ currentPositionInfo.isPlaying = false ;
939
+ currentPositionInfo.timeInSamples += bufferSize;
919
940
}
920
941
921
942
if (juce::Time::currentTimeMillis () >= endTime)
@@ -927,8 +948,12 @@ class ExternalPlugin : public AbstractExternalPlugin {
927
948
audioBuffer.clear ();
928
949
{
929
950
juce::MidiBuffer allNotesOffBuffer (allNotesOff);
951
+ currentPositionInfo.isPlaying = true ;
930
952
pluginInstance->processBlock (audioBuffer, allNotesOffBuffer);
953
+ currentPositionInfo.isPlaying = false ;
954
+ currentPositionInfo.timeInSamples += bufferSize;
931
955
}
956
+ currentPositionInfo.timeInSamples = 0 ;
932
957
pluginInstance->reset ();
933
958
pluginInstance->releaseResources ();
934
959
@@ -1046,6 +1071,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
1046
1071
// Force prepare() to be called again later by invalidating lastSpec:
1047
1072
lastSpec.maximumBlockSize = 0 ;
1048
1073
samplesProvided = 0 ;
1074
+ currentPositionInfo.timeInSamples = 0 ;
1049
1075
}
1050
1076
}
1051
1077
@@ -1071,6 +1097,8 @@ class ExternalPlugin : public AbstractExternalPlugin {
1071
1097
1072
1098
pluginInstance->setNonRealtime (true );
1073
1099
pluginInstance->prepareToPlay (spec.sampleRate , spec.maximumBlockSize );
1100
+ currentPositionInfo.timeInSamples = 0 ;
1101
+ currentPositionInfo.isPlaying = false ;
1074
1102
1075
1103
lastSpec = spec;
1076
1104
}
@@ -1142,8 +1170,11 @@ class ExternalPlugin : public AbstractExternalPlugin {
1142
1170
channelPointers.size (),
1143
1171
outputBlock.getNumSamples ());
1144
1172
1173
+ currentPositionInfo.isPlaying = true ;
1145
1174
pluginInstance->processBlock (audioBuffer, emptyMidiBuffer);
1175
+ currentPositionInfo.isPlaying = false ;
1146
1176
samplesProvided += outputBlock.getNumSamples ();
1177
+ currentPositionInfo.timeInSamples += outputBlock.getNumSamples ();
1147
1178
1148
1179
// To compensate for any latency added by the plugin,
1149
1180
// only tell Pedalboard to use the last _n_ samples.
@@ -1238,7 +1269,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
1238
1269
juce::MidiBuffer midiChunk;
1239
1270
midiChunk.addEvents (midiInputBuffer, i, chunkSampleCount, -i);
1240
1271
1272
+ currentPositionInfo.isPlaying = true ;
1241
1273
pluginInstance->processBlock (audioChunk, midiChunk);
1274
+ currentPositionInfo.isPlaying = false ;
1275
+ currentPositionInfo.timeInSamples += chunkSampleCount;
1242
1276
}
1243
1277
}
1244
1278
@@ -1302,13 +1336,19 @@ class ExternalPlugin : public AbstractExternalPlugin {
1302
1336
1303
1337
ExternalPluginReloadType reloadType = ExternalPluginReloadType::Unknown;
1304
1338
1339
+ bool getCurrentPosition (CurrentPositionInfo &result) override {
1340
+ result = currentPositionInfo;
1341
+ return true ;
1342
+ }
1343
+
1305
1344
private:
1306
1345
constexpr static int ExternalLoadSampleRate = 44100 ,
1307
1346
ExternalLoadMaximumBlockSize = 8192 ;
1308
1347
juce::String pathToPluginFile;
1309
1348
juce::PluginDescription foundPluginDescription;
1310
1349
juce::AudioPluginFormatManager pluginFormatManager;
1311
1350
std::unique_ptr<juce::AudioPluginInstance> pluginInstance;
1351
+ juce::AudioPlayHead::CurrentPositionInfo currentPositionInfo;
1312
1352
1313
1353
long samplesProvided = 0 ;
1314
1354
float initializationTimeout = DEFAULT_INITIALIZATION_TIMEOUT_SECONDS;
0 commit comments