@signalsandsorcery/plugin-sdk 2.40.1 → 2.40.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -2961,6 +2961,15 @@ interface SDKTrackRowProps {
2961
2961
  * a title suffix. Undefined (all single-track panels) renders nothing.
2962
2962
  */
2963
2963
  linkedSoundHint?: string;
2964
+ /**
2965
+ * One-shot linked sync (@since SDK 2.48.0): presence renders a "→ All"
2966
+ * button next to Shuffle that pushes THIS row's current sound to every
2967
+ * linked sibling. The affordance for patch changes made inside a custom
2968
+ * plugin's own editor (Kontakt / Diva…), which fire no change event —
2969
+ * and the only sound-propagation control that works on such tracks,
2970
+ * since Shuffle is Surge-only.
2971
+ */
2972
+ onSyncSoundToGroup?: () => void;
2964
2973
  /** Current MIDI notes for the piano-roll editor (the 'edit' tab). */
2965
2974
  editNotes?: readonly PluginMidiNote[];
2966
2975
  /** Persist edited notes; PRESENCE of this callback enables the Edit tab. */
@@ -2980,7 +2989,7 @@ interface SDKTrackRowProps {
2980
2989
  * a thin peak meter welds to the bottom of the row. Omit to hide it. */
2981
2990
  levels?: TrackLevelsHandle;
2982
2991
  }
2983
- declare function TrackRow({ track, prompt, runtimeState, soloedOut, fxDetailState, drawerOpen, drawerTab, onTabChange, isGenerating, isAuthenticated, error, hasMidi, generationProgress, estimatedGenerationMs, onPromptChange, onGenerate, onShuffle, onCopy, onDelete, contentSlot, onMuteToggle, onSoloToggle, onVolumeChange, onPanChange, onFxToggle, onFxPresetChange, onFxDryWetChange, externalFxHost, onToggleFxDrawer, onProgressChange, accentColor, instrumentName, instrumentMissing, onToggleDrawer, availableInstruments, currentInstrumentPluginId, onInstrumentSelect, instrumentsLoading, onRefreshInstruments, editorStage, onShowEditor, onBackToInstruments, soundHistory, soundHistoryCursor, onRestoreSound, onToggleFavorite, onImportSound, importSoundLabel, linkedSoundHint, editNotes, onNotesChange, editBars, editBpm, editSnap, onAuditionNote, drag, levels, }: SDKTrackRowProps): React$1.ReactElement;
2992
+ declare function TrackRow({ track, prompt, runtimeState, soloedOut, fxDetailState, drawerOpen, drawerTab, onTabChange, isGenerating, isAuthenticated, error, hasMidi, generationProgress, estimatedGenerationMs, onPromptChange, onGenerate, onShuffle, onCopy, onDelete, contentSlot, onMuteToggle, onSoloToggle, onVolumeChange, onPanChange, onFxToggle, onFxPresetChange, onFxDryWetChange, externalFxHost, onToggleFxDrawer, onProgressChange, accentColor, instrumentName, instrumentMissing, onToggleDrawer, availableInstruments, currentInstrumentPluginId, onInstrumentSelect, instrumentsLoading, onRefreshInstruments, editorStage, onShowEditor, onBackToInstruments, soundHistory, soundHistoryCursor, onRestoreSound, onToggleFavorite, onImportSound, importSoundLabel, linkedSoundHint, onSyncSoundToGroup, editNotes, onNotesChange, editBars, editBpm, editSnap, onAuditionNote, drag, levels, }: SDKTrackRowProps): React$1.ReactElement;
2984
2993
 
2985
2994
  /**
2986
2995
  * Crossfade-pair metadata — family-agnostic types + parsing shared by every
@@ -5053,6 +5062,12 @@ interface CoreTrackHandlers {
5053
5062
  promptChange(trackId: string, prompt: string): void;
5054
5063
  generate(trackId: string): void;
5055
5064
  shuffle(trackId: string): void;
5065
+ /**
5066
+ * One-shot linked sync (@since SDK 2.48.0): broadcast the track's CURRENT
5067
+ * sound to its linked siblings — the affordance for patch changes made
5068
+ * inside a plugin's own editor (no change event to hook).
5069
+ */
5070
+ syncSoundToGroup(trackId: string): void;
5056
5071
  copy(trackId: string): void;
5057
5072
  delete(trackId: string): void;
5058
5073
  muteToggle(trackId: string): void;
@@ -5383,6 +5398,12 @@ interface GeneratorPanelCore {
5383
5398
  * soundHistory.restoreTo for panels without broadcastTargets.
5384
5399
  */
5385
5400
  handleRestoreSound(trackId: string, index: number): Promise<void>;
5401
+ /**
5402
+ * One-shot linked sync (@since SDK 2.48.0): capture the track's CURRENT
5403
+ * sound and broadcast it to its linked siblings — for edits made inside a
5404
+ * plugin's own editor, which fire no change event.
5405
+ */
5406
+ handleSyncSoundToGroup(trackId: string): Promise<void>;
5386
5407
  handleAddTrack(): Promise<void>;
5387
5408
  handleDeleteTrack(trackId: string): Promise<void>;
5388
5409
  handleExportMidi(): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -2961,6 +2961,15 @@ interface SDKTrackRowProps {
2961
2961
  * a title suffix. Undefined (all single-track panels) renders nothing.
2962
2962
  */
2963
2963
  linkedSoundHint?: string;
2964
+ /**
2965
+ * One-shot linked sync (@since SDK 2.48.0): presence renders a "→ All"
2966
+ * button next to Shuffle that pushes THIS row's current sound to every
2967
+ * linked sibling. The affordance for patch changes made inside a custom
2968
+ * plugin's own editor (Kontakt / Diva…), which fire no change event —
2969
+ * and the only sound-propagation control that works on such tracks,
2970
+ * since Shuffle is Surge-only.
2971
+ */
2972
+ onSyncSoundToGroup?: () => void;
2964
2973
  /** Current MIDI notes for the piano-roll editor (the 'edit' tab). */
2965
2974
  editNotes?: readonly PluginMidiNote[];
2966
2975
  /** Persist edited notes; PRESENCE of this callback enables the Edit tab. */
@@ -2980,7 +2989,7 @@ interface SDKTrackRowProps {
2980
2989
  * a thin peak meter welds to the bottom of the row. Omit to hide it. */
2981
2990
  levels?: TrackLevelsHandle;
2982
2991
  }
2983
- declare function TrackRow({ track, prompt, runtimeState, soloedOut, fxDetailState, drawerOpen, drawerTab, onTabChange, isGenerating, isAuthenticated, error, hasMidi, generationProgress, estimatedGenerationMs, onPromptChange, onGenerate, onShuffle, onCopy, onDelete, contentSlot, onMuteToggle, onSoloToggle, onVolumeChange, onPanChange, onFxToggle, onFxPresetChange, onFxDryWetChange, externalFxHost, onToggleFxDrawer, onProgressChange, accentColor, instrumentName, instrumentMissing, onToggleDrawer, availableInstruments, currentInstrumentPluginId, onInstrumentSelect, instrumentsLoading, onRefreshInstruments, editorStage, onShowEditor, onBackToInstruments, soundHistory, soundHistoryCursor, onRestoreSound, onToggleFavorite, onImportSound, importSoundLabel, linkedSoundHint, editNotes, onNotesChange, editBars, editBpm, editSnap, onAuditionNote, drag, levels, }: SDKTrackRowProps): React$1.ReactElement;
2992
+ declare function TrackRow({ track, prompt, runtimeState, soloedOut, fxDetailState, drawerOpen, drawerTab, onTabChange, isGenerating, isAuthenticated, error, hasMidi, generationProgress, estimatedGenerationMs, onPromptChange, onGenerate, onShuffle, onCopy, onDelete, contentSlot, onMuteToggle, onSoloToggle, onVolumeChange, onPanChange, onFxToggle, onFxPresetChange, onFxDryWetChange, externalFxHost, onToggleFxDrawer, onProgressChange, accentColor, instrumentName, instrumentMissing, onToggleDrawer, availableInstruments, currentInstrumentPluginId, onInstrumentSelect, instrumentsLoading, onRefreshInstruments, editorStage, onShowEditor, onBackToInstruments, soundHistory, soundHistoryCursor, onRestoreSound, onToggleFavorite, onImportSound, importSoundLabel, linkedSoundHint, onSyncSoundToGroup, editNotes, onNotesChange, editBars, editBpm, editSnap, onAuditionNote, drag, levels, }: SDKTrackRowProps): React$1.ReactElement;
2984
2993
 
2985
2994
  /**
2986
2995
  * Crossfade-pair metadata — family-agnostic types + parsing shared by every
@@ -5053,6 +5062,12 @@ interface CoreTrackHandlers {
5053
5062
  promptChange(trackId: string, prompt: string): void;
5054
5063
  generate(trackId: string): void;
5055
5064
  shuffle(trackId: string): void;
5065
+ /**
5066
+ * One-shot linked sync (@since SDK 2.48.0): broadcast the track's CURRENT
5067
+ * sound to its linked siblings — the affordance for patch changes made
5068
+ * inside a plugin's own editor (no change event to hook).
5069
+ */
5070
+ syncSoundToGroup(trackId: string): void;
5056
5071
  copy(trackId: string): void;
5057
5072
  delete(trackId: string): void;
5058
5073
  muteToggle(trackId: string): void;
@@ -5383,6 +5398,12 @@ interface GeneratorPanelCore {
5383
5398
  * soundHistory.restoreTo for panels without broadcastTargets.
5384
5399
  */
5385
5400
  handleRestoreSound(trackId: string, index: number): Promise<void>;
5401
+ /**
5402
+ * One-shot linked sync (@since SDK 2.48.0): capture the track's CURRENT
5403
+ * sound and broadcast it to its linked siblings — for edits made inside a
5404
+ * plugin's own editor, which fire no change event.
5405
+ */
5406
+ handleSyncSoundToGroup(trackId: string): Promise<void>;
5386
5407
  handleAddTrack(): Promise<void>;
5387
5408
  handleDeleteTrack(trackId: string): Promise<void>;
5388
5409
  handleExportMidi(): Promise<void>;
package/dist/index.js CHANGED
@@ -2700,6 +2700,7 @@ function TrackRow({
2700
2700
  onImportSound,
2701
2701
  importSoundLabel,
2702
2702
  linkedSoundHint,
2703
+ onSyncSoundToGroup,
2703
2704
  editNotes,
2704
2705
  onNotesChange,
2705
2706
  editBars,
@@ -2887,6 +2888,17 @@ function TrackRow({
2887
2888
  ]
2888
2889
  }
2889
2890
  ),
2891
+ onSyncSoundToGroup && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2892
+ "button",
2893
+ {
2894
+ "data-testid": "sdk-sync-sound-button",
2895
+ onClick: onSyncSoundToGroup,
2896
+ disabled: isGenerating,
2897
+ className: `px-1.5 py-0.5 rounded-sm text-xs font-medium transition-colors border whitespace-nowrap ${isGenerating ? "bg-sas-panel border-sas-border text-sas-muted/30 cursor-not-allowed" : "bg-sas-panel-alt border-sas-border text-sas-muted hover:border-sas-accent hover:text-sas-accent"}`,
2898
+ title: "Apply THIS part's current sound to all linked parts \u2014 use after picking a patch inside the plugin's own editor",
2899
+ children: "\u2192 All"
2900
+ }
2901
+ ),
2890
2902
  freezeBadge && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2891
2903
  "span",
2892
2904
  {
@@ -7882,6 +7894,26 @@ function useGeneratorPanelCore({
7882
7894
  },
7883
7895
  [adapter, makeServices, host, logTag]
7884
7896
  );
7897
+ const handleSyncSoundToGroup = (0, import_react31.useCallback)(
7898
+ async (trackId) => {
7899
+ const track = tracksRef.current.find((t) => t.handle.id === trackId);
7900
+ if (!track) return;
7901
+ let cap = null;
7902
+ try {
7903
+ cap = await adapter.sound.captureSoundDescriptor(trackId);
7904
+ } catch {
7905
+ cap = null;
7906
+ }
7907
+ if (!cap) {
7908
+ host.showToast("warning", "Nothing to sync", "This track has no sound to copy yet.");
7909
+ return;
7910
+ }
7911
+ const hist = soundHistory.list(trackId);
7912
+ const label = (hist.cursor >= 0 ? hist.entries[hist.cursor]?.label : void 0) ?? track.instrumentName ?? "Current sound";
7913
+ await broadcastSoundFromTrack(trackId, cap.descriptor, label);
7914
+ },
7915
+ [adapter, soundHistory, host, broadcastSoundFromTrack]
7916
+ );
7885
7917
  const handleRestoreSound = (0, import_react31.useCallback)(
7886
7918
  async (trackId, index) => {
7887
7919
  const entry = soundHistory.list(trackId).entries[index];
@@ -8423,6 +8455,9 @@ function useGeneratorPanelCore({
8423
8455
  shuffle: (trackId) => {
8424
8456
  void handleShuffle(trackId);
8425
8457
  },
8458
+ syncSoundToGroup: (trackId) => {
8459
+ void handleSyncSoundToGroup(trackId);
8460
+ },
8426
8461
  copy: (trackId) => {
8427
8462
  void handleCopy(trackId);
8428
8463
  },
@@ -8443,6 +8478,7 @@ function useGeneratorPanelCore({
8443
8478
  handlePromptChange,
8444
8479
  handleGenerate,
8445
8480
  handleShuffle,
8481
+ handleSyncSoundToGroup,
8446
8482
  handleCopy,
8447
8483
  handleDeleteTrack,
8448
8484
  handleMuteToggle,
@@ -8501,6 +8537,7 @@ function useGeneratorPanelCore({
8501
8537
  handleGenerate,
8502
8538
  handleShuffle,
8503
8539
  handleRestoreSound,
8540
+ handleSyncSoundToGroup,
8504
8541
  handleAddTrack,
8505
8542
  handleDeleteTrack,
8506
8543
  handleExportMidi,