@dawcore/components 0.0.19 → 0.0.21
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/README.md +1 -1
- package/dist/index.d.mts +157 -137
- package/dist/index.d.ts +157 -137
- package/dist/index.js +895 -613
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +765 -480
- package/dist/index.mjs.map +1 -1
- package/package.json +25 -16
package/dist/index.js
CHANGED
|
@@ -230,7 +230,7 @@ var DawTrackElement = class extends import_lit2.LitElement {
|
|
|
230
230
|
this.pan = 0;
|
|
231
231
|
this.muted = false;
|
|
232
232
|
this.soloed = false;
|
|
233
|
-
this.
|
|
233
|
+
this._renderMode = "waveform";
|
|
234
234
|
this.spectrogramConfig = null;
|
|
235
235
|
this.trackId = crypto.randomUUID();
|
|
236
236
|
// Track removal is detected by the editor's MutationObserver,
|
|
@@ -238,6 +238,21 @@ var DawTrackElement = class extends import_lit2.LitElement {
|
|
|
238
238
|
// cannot bubble events to ancestors).
|
|
239
239
|
this._hasRendered = false;
|
|
240
240
|
}
|
|
241
|
+
get renderMode() {
|
|
242
|
+
return this._renderMode;
|
|
243
|
+
}
|
|
244
|
+
set renderMode(value) {
|
|
245
|
+
const old = this._renderMode;
|
|
246
|
+
let next = value;
|
|
247
|
+
if (next === "both") {
|
|
248
|
+
console.warn(
|
|
249
|
+
`[dawcore] <daw-track render-mode="both"> is not yet supported; falling back to 'spectrogram'`
|
|
250
|
+
);
|
|
251
|
+
next = "spectrogram";
|
|
252
|
+
}
|
|
253
|
+
this._renderMode = next;
|
|
254
|
+
this.requestUpdate("renderMode", old);
|
|
255
|
+
}
|
|
241
256
|
// Light DOM so <daw-clip> children are queryable.
|
|
242
257
|
createRenderRoot() {
|
|
243
258
|
return this;
|
|
@@ -300,8 +315,8 @@ __decorateClass([
|
|
|
300
315
|
(0, import_decorators2.property)({ type: Boolean })
|
|
301
316
|
], DawTrackElement.prototype, "soloed", 2);
|
|
302
317
|
__decorateClass([
|
|
303
|
-
(0, import_decorators2.property)({ attribute: "render-mode" })
|
|
304
|
-
], DawTrackElement.prototype, "renderMode",
|
|
318
|
+
(0, import_decorators2.property)({ attribute: "render-mode", noAccessor: true })
|
|
319
|
+
], DawTrackElement.prototype, "renderMode", 1);
|
|
305
320
|
__decorateClass([
|
|
306
321
|
(0, import_decorators2.property)({ attribute: false })
|
|
307
322
|
], DawTrackElement.prototype, "spectrogramConfig", 2);
|
|
@@ -1237,8 +1252,8 @@ DawStopButtonElement = __decorateClass([
|
|
|
1237
1252
|
], DawStopButtonElement);
|
|
1238
1253
|
|
|
1239
1254
|
// src/elements/daw-editor.ts
|
|
1240
|
-
var
|
|
1241
|
-
var
|
|
1255
|
+
var import_lit15 = require("lit");
|
|
1256
|
+
var import_decorators13 = require("lit/decorators.js");
|
|
1242
1257
|
|
|
1243
1258
|
// src/types.ts
|
|
1244
1259
|
function isDomClip(desc) {
|
|
@@ -1246,7 +1261,7 @@ function isDomClip(desc) {
|
|
|
1246
1261
|
}
|
|
1247
1262
|
|
|
1248
1263
|
// src/elements/daw-editor.ts
|
|
1249
|
-
var
|
|
1264
|
+
var import_core9 = require("@waveform-playlist/core");
|
|
1250
1265
|
|
|
1251
1266
|
// src/workers/peaksWorker.ts
|
|
1252
1267
|
var import_waveform_data = __toESM(require("waveform-data"));
|
|
@@ -1717,129 +1732,399 @@ var PeakPipeline = class {
|
|
|
1717
1732
|
}
|
|
1718
1733
|
};
|
|
1719
1734
|
|
|
1720
|
-
// src/elements/daw-
|
|
1735
|
+
// src/elements/daw-ruler.ts
|
|
1721
1736
|
var import_lit11 = require("lit");
|
|
1722
1737
|
var import_decorators10 = require("lit/decorators.js");
|
|
1723
|
-
|
|
1738
|
+
|
|
1739
|
+
// src/utils/time-format.ts
|
|
1740
|
+
function formatTime(milliseconds) {
|
|
1741
|
+
const seconds = Math.floor(milliseconds / 1e3);
|
|
1742
|
+
const s = seconds % 60;
|
|
1743
|
+
const m = (seconds - s) / 60;
|
|
1744
|
+
return `${m}:${String(s).padStart(2, "0")}`;
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
// src/utils/smart-scale.ts
|
|
1748
|
+
var timeinfo = /* @__PURE__ */ new Map([
|
|
1749
|
+
[700, { marker: 1e3, bigStep: 500, smallStep: 100 }],
|
|
1750
|
+
[1500, { marker: 2e3, bigStep: 1e3, smallStep: 200 }],
|
|
1751
|
+
[2500, { marker: 2e3, bigStep: 1e3, smallStep: 500 }],
|
|
1752
|
+
[5e3, { marker: 5e3, bigStep: 1e3, smallStep: 500 }],
|
|
1753
|
+
[1e4, { marker: 1e4, bigStep: 5e3, smallStep: 1e3 }],
|
|
1754
|
+
[12e3, { marker: 15e3, bigStep: 5e3, smallStep: 1e3 }],
|
|
1755
|
+
[Infinity, { marker: 3e4, bigStep: 1e4, smallStep: 5e3 }]
|
|
1756
|
+
]);
|
|
1757
|
+
function getScaleInfo(samplesPerPixel) {
|
|
1758
|
+
for (const [resolution, config] of timeinfo) {
|
|
1759
|
+
if (samplesPerPixel < resolution) {
|
|
1760
|
+
return config;
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
return { marker: 3e4, bigStep: 1e4, smallStep: 5e3 };
|
|
1764
|
+
}
|
|
1765
|
+
function computeTemporalTicks(samplesPerPixel, sampleRate, duration, rulerHeight) {
|
|
1766
|
+
const widthX = Math.ceil(duration * sampleRate / samplesPerPixel);
|
|
1767
|
+
const config = getScaleInfo(samplesPerPixel);
|
|
1768
|
+
const { marker, bigStep, smallStep } = config;
|
|
1769
|
+
const canvasInfo = /* @__PURE__ */ new Map();
|
|
1770
|
+
const labels = [];
|
|
1771
|
+
const pixPerSec = sampleRate / samplesPerPixel;
|
|
1772
|
+
for (let counter = 0; ; counter += smallStep) {
|
|
1773
|
+
const pix = Math.floor(counter / 1e3 * pixPerSec);
|
|
1774
|
+
if (pix >= widthX) break;
|
|
1775
|
+
if (counter % marker === 0) {
|
|
1776
|
+
canvasInfo.set(pix, rulerHeight);
|
|
1777
|
+
labels.push({ pix, text: formatTime(counter) });
|
|
1778
|
+
} else if (counter % bigStep === 0) {
|
|
1779
|
+
canvasInfo.set(pix, Math.floor(rulerHeight / 2));
|
|
1780
|
+
} else if (counter % smallStep === 0) {
|
|
1781
|
+
canvasInfo.set(pix, Math.floor(rulerHeight / 5));
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
return { widthX, canvasInfo, labels };
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
// src/utils/musical-tick-cache.ts
|
|
1788
|
+
var import_core = require("@waveform-playlist/core");
|
|
1789
|
+
var cachedParams = null;
|
|
1790
|
+
var cachedResult = null;
|
|
1791
|
+
function meterEntriesMatch(a, b) {
|
|
1792
|
+
if (a.length !== b.length) return false;
|
|
1793
|
+
for (let i = 0; i < a.length; i++) {
|
|
1794
|
+
if (a[i].tick !== b[i].tick || a[i].numerator !== b[i].numerator || a[i].denominator !== b[i].denominator)
|
|
1795
|
+
return false;
|
|
1796
|
+
}
|
|
1797
|
+
return true;
|
|
1798
|
+
}
|
|
1799
|
+
function paramsMatch(a, b) {
|
|
1800
|
+
return a.ticksPerPixel === b.ticksPerPixel && a.startPixel === b.startPixel && a.endPixel === b.endPixel && meterEntriesMatch(a.meterEntries, b.meterEntries) && (a.ppqn ?? 960) === (b.ppqn ?? 960);
|
|
1801
|
+
}
|
|
1802
|
+
function getCachedMusicalTicks(params) {
|
|
1803
|
+
if (cachedParams && cachedResult && paramsMatch(cachedParams, params)) {
|
|
1804
|
+
return cachedResult;
|
|
1805
|
+
}
|
|
1806
|
+
cachedResult = (0, import_core.computeMusicalTicks)(params);
|
|
1807
|
+
cachedParams = {
|
|
1808
|
+
...params,
|
|
1809
|
+
meterEntries: params.meterEntries.map((e) => ({ ...e }))
|
|
1810
|
+
};
|
|
1811
|
+
return cachedResult;
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
// src/elements/daw-ruler.ts
|
|
1815
|
+
var MAX_CANVAS_WIDTH3 = 1e3;
|
|
1816
|
+
var DawRulerElement = class extends import_lit11.LitElement {
|
|
1724
1817
|
constructor() {
|
|
1725
1818
|
super(...arguments);
|
|
1726
|
-
this.
|
|
1727
|
-
this.
|
|
1728
|
-
this.
|
|
1729
|
-
this.
|
|
1730
|
-
this.
|
|
1731
|
-
this.
|
|
1732
|
-
this.
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
this.
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
};
|
|
1740
|
-
this._onMuteClick = () => {
|
|
1741
|
-
this._dispatchControl("muted", !this.muted);
|
|
1742
|
-
};
|
|
1743
|
-
this._onSoloClick = () => {
|
|
1744
|
-
this._dispatchControl("soloed", !this.soloed);
|
|
1745
|
-
};
|
|
1746
|
-
this._onRemoveClick = () => {
|
|
1747
|
-
if (!this.trackId) return;
|
|
1748
|
-
this.dispatchEvent(
|
|
1749
|
-
new CustomEvent("daw-track-remove", {
|
|
1750
|
-
bubbles: true,
|
|
1751
|
-
composed: true,
|
|
1752
|
-
detail: { trackId: this.trackId }
|
|
1753
|
-
})
|
|
1754
|
-
);
|
|
1755
|
-
};
|
|
1819
|
+
this.samplesPerPixel = 1024;
|
|
1820
|
+
this.sampleRate = 48e3;
|
|
1821
|
+
this.duration = 0;
|
|
1822
|
+
this.rulerHeight = 30;
|
|
1823
|
+
this.scaleMode = "temporal";
|
|
1824
|
+
this.ticksPerPixel = 4;
|
|
1825
|
+
this.meterEntries = [
|
|
1826
|
+
{ tick: 0, numerator: 4, denominator: 4 }
|
|
1827
|
+
];
|
|
1828
|
+
this.ppqn = 960;
|
|
1829
|
+
this.totalWidth = 0;
|
|
1830
|
+
this._tickData = null;
|
|
1831
|
+
this._musicalTickData = null;
|
|
1756
1832
|
}
|
|
1757
|
-
|
|
1758
|
-
if (
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1833
|
+
willUpdate() {
|
|
1834
|
+
if (this.scaleMode === "beats" && this.totalWidth > 0) {
|
|
1835
|
+
this._musicalTickData = getCachedMusicalTicks({
|
|
1836
|
+
meterEntries: this.meterEntries,
|
|
1837
|
+
ticksPerPixel: this.ticksPerPixel,
|
|
1838
|
+
startPixel: 0,
|
|
1839
|
+
endPixel: this.totalWidth,
|
|
1840
|
+
ppqn: this.ppqn
|
|
1841
|
+
});
|
|
1842
|
+
this._tickData = null;
|
|
1843
|
+
} else if (this.duration > 0 || this.totalWidth > 0) {
|
|
1844
|
+
const widthDerivedDuration = this.totalWidth * this.samplesPerPixel / this.sampleRate;
|
|
1845
|
+
const effectiveDuration = Math.max(this.duration, widthDerivedDuration);
|
|
1846
|
+
this._musicalTickData = null;
|
|
1847
|
+
this._tickData = computeTemporalTicks(
|
|
1848
|
+
this.samplesPerPixel,
|
|
1849
|
+
this.sampleRate,
|
|
1850
|
+
effectiveDuration,
|
|
1851
|
+
this.rulerHeight
|
|
1852
|
+
);
|
|
1853
|
+
} else {
|
|
1854
|
+
this._musicalTickData = null;
|
|
1855
|
+
this._tickData = null;
|
|
1856
|
+
}
|
|
1766
1857
|
}
|
|
1767
1858
|
render() {
|
|
1768
|
-
const
|
|
1769
|
-
|
|
1770
|
-
const
|
|
1859
|
+
const widthX = this.scaleMode === "beats" ? this.totalWidth : this._tickData?.widthX ?? 0;
|
|
1860
|
+
if (widthX <= 0) return import_lit11.html``;
|
|
1861
|
+
const totalChunks = Math.ceil(widthX / MAX_CANVAS_WIDTH3);
|
|
1862
|
+
const indices = Array.from({ length: totalChunks }, (_, i) => i);
|
|
1863
|
+
const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
|
|
1864
|
+
const beatsLabels = this.scaleMode === "beats" ? this._musicalTickData?.ticks.filter((t) => t.label) ?? [] : [];
|
|
1865
|
+
const temporalLabels = this.scaleMode !== "beats" ? this._tickData?.labels ?? [] : [];
|
|
1771
1866
|
return import_lit11.html`
|
|
1772
|
-
<div class="
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
<span class="slider-label-value">${volPercent}%</span>
|
|
1794
|
-
</span>
|
|
1795
|
-
<input
|
|
1796
|
-
type="range"
|
|
1797
|
-
min="0"
|
|
1798
|
-
max="1"
|
|
1799
|
-
step="0.01"
|
|
1800
|
-
.value=${String(this.volume)}
|
|
1801
|
-
@input=${this._onVolumeInput}
|
|
1802
|
-
/>
|
|
1803
|
-
</div>
|
|
1804
|
-
<div class="slider-row">
|
|
1805
|
-
<span class="slider-label">
|
|
1806
|
-
<span class="slider-label-name">Pan</span>
|
|
1807
|
-
<span class="slider-label-value">${panDisplay}</span>
|
|
1808
|
-
</span>
|
|
1809
|
-
<input
|
|
1810
|
-
type="range"
|
|
1811
|
-
min="-1"
|
|
1812
|
-
max="1"
|
|
1813
|
-
step="0.01"
|
|
1814
|
-
.value=${String(this.pan)}
|
|
1815
|
-
@input=${this._onPanInput}
|
|
1816
|
-
/>
|
|
1867
|
+
<div class="container" style="width: ${widthX}px; height: ${this.rulerHeight}px;">
|
|
1868
|
+
${indices.map((i) => {
|
|
1869
|
+
const width = Math.min(MAX_CANVAS_WIDTH3, widthX - i * MAX_CANVAS_WIDTH3);
|
|
1870
|
+
return import_lit11.html`
|
|
1871
|
+
<canvas
|
|
1872
|
+
data-index=${i}
|
|
1873
|
+
width=${width * dpr}
|
|
1874
|
+
height=${this.rulerHeight * dpr}
|
|
1875
|
+
style="left: ${i * MAX_CANVAS_WIDTH3}px; width: ${width}px; height: ${this.rulerHeight}px;"
|
|
1876
|
+
></canvas>
|
|
1877
|
+
`;
|
|
1878
|
+
})}
|
|
1879
|
+
${this.scaleMode === "beats" ? beatsLabels.map(
|
|
1880
|
+
(t) => import_lit11.html`<span
|
|
1881
|
+
class="label ${t.pixel > 0 ? "centered" : ""}"
|
|
1882
|
+
style="left: ${t.pixel > 0 ? t.pixel : t.pixel + 4}px;"
|
|
1883
|
+
>${t.label}</span
|
|
1884
|
+
>`
|
|
1885
|
+
) : temporalLabels.map(
|
|
1886
|
+
({ pix, text }) => import_lit11.html`<span class="label" style="left: ${pix + 4}px;">${text}</span>`
|
|
1887
|
+
)}
|
|
1817
1888
|
</div>
|
|
1818
1889
|
`;
|
|
1819
1890
|
}
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1891
|
+
updated() {
|
|
1892
|
+
this._drawTicks();
|
|
1893
|
+
}
|
|
1894
|
+
_drawTicks() {
|
|
1895
|
+
const canvases = this.shadowRoot?.querySelectorAll("canvas");
|
|
1896
|
+
if (!canvases) return;
|
|
1897
|
+
const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
|
|
1898
|
+
const rulerColor = getComputedStyle(this).getPropertyValue("--daw-ruler-color").trim() || "#c49a6c";
|
|
1899
|
+
const widthX = this.scaleMode === "beats" ? this.totalWidth : this._tickData?.widthX ?? 0;
|
|
1900
|
+
for (const canvas of canvases) {
|
|
1901
|
+
const idx = Number(canvas.dataset.index);
|
|
1902
|
+
const ctx = canvas.getContext("2d");
|
|
1903
|
+
if (!ctx) continue;
|
|
1904
|
+
const canvasWidth = Math.min(MAX_CANVAS_WIDTH3, widthX - idx * MAX_CANVAS_WIDTH3);
|
|
1905
|
+
const globalOffset = idx * MAX_CANVAS_WIDTH3;
|
|
1906
|
+
ctx.resetTransform();
|
|
1907
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1908
|
+
ctx.scale(dpr, dpr);
|
|
1909
|
+
ctx.strokeStyle = rulerColor;
|
|
1910
|
+
ctx.lineWidth = 1;
|
|
1911
|
+
if (this.scaleMode === "beats" && this._musicalTickData) {
|
|
1912
|
+
const h = this.rulerHeight;
|
|
1913
|
+
for (const tick of this._musicalTickData.ticks) {
|
|
1914
|
+
const localX = tick.pixel - globalOffset;
|
|
1915
|
+
if (localX < 0 || localX >= canvasWidth) continue;
|
|
1916
|
+
const tickH = tick.type === "major" ? h * 0.6 : tick.type === "minor" ? h * 0.35 : h * 0.15;
|
|
1917
|
+
ctx.globalAlpha = tick.type === "major" ? 1 : 0.5;
|
|
1918
|
+
ctx.beginPath();
|
|
1919
|
+
ctx.moveTo(localX + 0.5, h);
|
|
1920
|
+
ctx.lineTo(localX + 0.5, h - tickH);
|
|
1921
|
+
ctx.stroke();
|
|
1922
|
+
}
|
|
1923
|
+
ctx.globalAlpha = 1;
|
|
1924
|
+
} else if (this._tickData) {
|
|
1925
|
+
for (const [pix, height] of this._tickData.canvasInfo) {
|
|
1926
|
+
const localX = pix - globalOffset;
|
|
1927
|
+
if (localX < 0 || localX >= canvasWidth) continue;
|
|
1928
|
+
ctx.beginPath();
|
|
1929
|
+
ctx.moveTo(localX + 0.5, this.rulerHeight);
|
|
1930
|
+
ctx.lineTo(localX + 0.5, this.rulerHeight - height);
|
|
1931
|
+
ctx.stroke();
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
};
|
|
1937
|
+
DawRulerElement.styles = import_lit11.css`
|
|
1938
|
+
:host {
|
|
1939
|
+
display: block;
|
|
1940
|
+
position: relative;
|
|
1941
|
+
background: var(--daw-ruler-background, #0f0f1a);
|
|
1942
|
+
}
|
|
1943
|
+
.container {
|
|
1944
|
+
position: relative;
|
|
1945
|
+
}
|
|
1946
|
+
canvas {
|
|
1947
|
+
position: absolute;
|
|
1948
|
+
top: 0;
|
|
1949
|
+
}
|
|
1950
|
+
.label {
|
|
1951
|
+
position: absolute;
|
|
1952
|
+
font-size: 0.7rem;
|
|
1953
|
+
line-height: 1;
|
|
1954
|
+
white-space: nowrap;
|
|
1955
|
+
color: var(--daw-ruler-color, #c49a6c);
|
|
1956
|
+
top: 1px;
|
|
1957
|
+
}
|
|
1958
|
+
.label.centered {
|
|
1959
|
+
transform: translateX(-50%);
|
|
1960
|
+
}
|
|
1961
|
+
`;
|
|
1962
|
+
__decorateClass([
|
|
1963
|
+
(0, import_decorators10.property)({ type: Number, attribute: false })
|
|
1964
|
+
], DawRulerElement.prototype, "samplesPerPixel", 2);
|
|
1965
|
+
__decorateClass([
|
|
1966
|
+
(0, import_decorators10.property)({ type: Number, attribute: false })
|
|
1967
|
+
], DawRulerElement.prototype, "sampleRate", 2);
|
|
1968
|
+
__decorateClass([
|
|
1969
|
+
(0, import_decorators10.property)({ type: Number, attribute: false })
|
|
1970
|
+
], DawRulerElement.prototype, "duration", 2);
|
|
1971
|
+
__decorateClass([
|
|
1972
|
+
(0, import_decorators10.property)({ type: Number, attribute: false })
|
|
1973
|
+
], DawRulerElement.prototype, "rulerHeight", 2);
|
|
1974
|
+
__decorateClass([
|
|
1975
|
+
(0, import_decorators10.property)({ type: String, attribute: false })
|
|
1976
|
+
], DawRulerElement.prototype, "scaleMode", 2);
|
|
1977
|
+
__decorateClass([
|
|
1978
|
+
(0, import_decorators10.property)({ type: Number, attribute: false })
|
|
1979
|
+
], DawRulerElement.prototype, "ticksPerPixel", 2);
|
|
1980
|
+
__decorateClass([
|
|
1981
|
+
(0, import_decorators10.property)({ attribute: false })
|
|
1982
|
+
], DawRulerElement.prototype, "meterEntries", 2);
|
|
1983
|
+
__decorateClass([
|
|
1984
|
+
(0, import_decorators10.property)({ type: Number, attribute: false })
|
|
1985
|
+
], DawRulerElement.prototype, "ppqn", 2);
|
|
1986
|
+
__decorateClass([
|
|
1987
|
+
(0, import_decorators10.property)({ type: Number, attribute: false })
|
|
1988
|
+
], DawRulerElement.prototype, "totalWidth", 2);
|
|
1989
|
+
DawRulerElement = __decorateClass([
|
|
1990
|
+
(0, import_decorators10.customElement)("daw-ruler")
|
|
1991
|
+
], DawRulerElement);
|
|
1992
|
+
|
|
1993
|
+
// src/elements/daw-track-controls.ts
|
|
1994
|
+
var import_lit12 = require("lit");
|
|
1995
|
+
var import_decorators11 = require("lit/decorators.js");
|
|
1996
|
+
var DawTrackControlsElement = class extends import_lit12.LitElement {
|
|
1997
|
+
constructor() {
|
|
1998
|
+
super(...arguments);
|
|
1999
|
+
this.trackId = null;
|
|
2000
|
+
this.trackName = "";
|
|
2001
|
+
this.volume = 1;
|
|
2002
|
+
this.pan = 0;
|
|
2003
|
+
this.muted = false;
|
|
2004
|
+
this.soloed = false;
|
|
2005
|
+
this._onVolumeInput = (e) => {
|
|
2006
|
+
const value = Number(e.target.value);
|
|
2007
|
+
if (Number.isFinite(value)) this._dispatchControl("volume", value);
|
|
2008
|
+
};
|
|
2009
|
+
this._onPanInput = (e) => {
|
|
2010
|
+
const value = Number(e.target.value);
|
|
2011
|
+
if (Number.isFinite(value)) this._dispatchControl("pan", value);
|
|
2012
|
+
};
|
|
2013
|
+
this._onMuteClick = () => {
|
|
2014
|
+
this._dispatchControl("muted", !this.muted);
|
|
2015
|
+
};
|
|
2016
|
+
this._onSoloClick = () => {
|
|
2017
|
+
this._dispatchControl("soloed", !this.soloed);
|
|
2018
|
+
};
|
|
2019
|
+
this._onRemoveClick = () => {
|
|
2020
|
+
if (!this.trackId) return;
|
|
2021
|
+
this.dispatchEvent(
|
|
2022
|
+
new CustomEvent("daw-track-remove", {
|
|
2023
|
+
bubbles: true,
|
|
2024
|
+
composed: true,
|
|
2025
|
+
detail: { trackId: this.trackId }
|
|
2026
|
+
})
|
|
2027
|
+
);
|
|
2028
|
+
};
|
|
2029
|
+
}
|
|
2030
|
+
firstUpdated() {
|
|
2031
|
+
requestAnimationFrame(() => {
|
|
2032
|
+
if (!this.isConnected) return;
|
|
2033
|
+
const rect = this.getBoundingClientRect();
|
|
2034
|
+
if (rect.width > 0 && rect.height === 0) {
|
|
2035
|
+
console.warn(
|
|
2036
|
+
"[dawcore] <daw-track-controls> has zero height: container-type: size requires an explicit height on the element (the editor sets one automatically; standalone usage must too). The controls are currently invisible."
|
|
2037
|
+
);
|
|
2038
|
+
}
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
_dispatchControl(prop, value) {
|
|
2042
|
+
if (!this.trackId) return;
|
|
2043
|
+
this.dispatchEvent(
|
|
2044
|
+
new CustomEvent("daw-track-control", {
|
|
2045
|
+
bubbles: true,
|
|
2046
|
+
composed: true,
|
|
2047
|
+
detail: { trackId: this.trackId, prop, value }
|
|
2048
|
+
})
|
|
2049
|
+
);
|
|
2050
|
+
}
|
|
2051
|
+
render() {
|
|
2052
|
+
const volPercent = Math.round(this.volume * 100);
|
|
2053
|
+
const panPercent = Math.round(Math.abs(this.pan) * 100);
|
|
2054
|
+
const panDisplay = this.pan === 0 ? "C" : (this.pan > 0 ? "R" : "L") + panPercent;
|
|
2055
|
+
return import_lit12.html`
|
|
2056
|
+
<div class="header">
|
|
2057
|
+
<span class="name" title=${this.trackName}>${this.trackName || "Untitled"}</span>
|
|
2058
|
+
<button class="remove-btn" @click=${this._onRemoveClick} title="Remove track">
|
|
2059
|
+
×
|
|
2060
|
+
</button>
|
|
2061
|
+
</div>
|
|
2062
|
+
<div class="buttons">
|
|
2063
|
+
<button
|
|
2064
|
+
class="btn ${this.muted ? "muted-active" : ""}"
|
|
2065
|
+
@click=${this._onMuteClick}
|
|
2066
|
+
title="Mute"
|
|
2067
|
+
>
|
|
2068
|
+
M
|
|
2069
|
+
</button>
|
|
2070
|
+
<button class="btn ${this.soloed ? "active" : ""}" @click=${this._onSoloClick} title="Solo">
|
|
2071
|
+
S
|
|
2072
|
+
</button>
|
|
2073
|
+
</div>
|
|
2074
|
+
<div class="slider-row vol-row">
|
|
2075
|
+
<span class="slider-label">
|
|
2076
|
+
<span class="slider-label-name">Vol</span>
|
|
2077
|
+
<span class="slider-label-value">${volPercent}%</span>
|
|
2078
|
+
</span>
|
|
2079
|
+
<input
|
|
2080
|
+
type="range"
|
|
2081
|
+
min="0"
|
|
2082
|
+
max="1"
|
|
2083
|
+
step="0.01"
|
|
2084
|
+
.value=${String(this.volume)}
|
|
2085
|
+
@input=${this._onVolumeInput}
|
|
2086
|
+
/>
|
|
2087
|
+
</div>
|
|
2088
|
+
<div class="slider-row pan-row">
|
|
2089
|
+
<span class="slider-label">
|
|
2090
|
+
<span class="slider-label-name">Pan</span>
|
|
2091
|
+
<span class="slider-label-value">${panDisplay}</span>
|
|
2092
|
+
</span>
|
|
2093
|
+
<input
|
|
2094
|
+
type="range"
|
|
2095
|
+
min="-1"
|
|
2096
|
+
max="1"
|
|
2097
|
+
step="0.01"
|
|
2098
|
+
.value=${String(this.pan)}
|
|
2099
|
+
@input=${this._onPanInput}
|
|
2100
|
+
/>
|
|
2101
|
+
</div>
|
|
2102
|
+
`;
|
|
2103
|
+
}
|
|
2104
|
+
};
|
|
2105
|
+
DawTrackControlsElement.styles = import_lit12.css`
|
|
2106
|
+
:host {
|
|
2107
|
+
display: flex;
|
|
2108
|
+
flex-direction: column;
|
|
2109
|
+
justify-content: flex-start;
|
|
2110
|
+
box-sizing: border-box;
|
|
2111
|
+
padding: 6px 8px;
|
|
2112
|
+
background: var(--daw-controls-background, #0f0f1a);
|
|
2113
|
+
color: var(--daw-controls-text, #c49a6c);
|
|
2114
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
|
2115
|
+
font-family: system-ui, sans-serif;
|
|
2116
|
+
font-size: 11px;
|
|
2117
|
+
overflow: hidden;
|
|
2118
|
+
container-type: size;
|
|
2119
|
+
}
|
|
2120
|
+
.header {
|
|
2121
|
+
display: flex;
|
|
2122
|
+
align-items: center;
|
|
2123
|
+
justify-content: space-between;
|
|
2124
|
+
gap: 4px;
|
|
2125
|
+
margin-bottom: 3px;
|
|
2126
|
+
}
|
|
2127
|
+
.name {
|
|
1843
2128
|
flex: 1;
|
|
1844
2129
|
overflow: hidden;
|
|
1845
2130
|
text-overflow: ellipsis;
|
|
@@ -1950,64 +2235,52 @@ DawTrackControlsElement.styles = import_lit11.css`
|
|
|
1950
2235
|
border: none;
|
|
1951
2236
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
|
|
1952
2237
|
}
|
|
2238
|
+
/* Compact modes: drop sliders when the row is too short for the full
|
|
2239
|
+
stack. Thresholds are CONTENT-BOX heights — the host is border-box
|
|
2240
|
+
with 12px vertical padding + 1px border, so an editor-given height H
|
|
2241
|
+
enters compact mode at H <= 89px (Pan hidden) and H <= 73px (Vol also
|
|
2242
|
+
hidden). NOTE: container-type: size requires an explicit height on
|
|
2243
|
+
the host — the editor always provides one; standalone consumers must
|
|
2244
|
+
too (see the firstUpdated guard). */
|
|
2245
|
+
@container (max-height: 76px) {
|
|
2246
|
+
.pan-row {
|
|
2247
|
+
display: none;
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
@container (max-height: 60px) {
|
|
2251
|
+
.vol-row {
|
|
2252
|
+
display: none;
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
1953
2255
|
`;
|
|
1954
2256
|
__decorateClass([
|
|
1955
|
-
(0,
|
|
2257
|
+
(0, import_decorators11.property)({ attribute: false })
|
|
1956
2258
|
], DawTrackControlsElement.prototype, "trackId", 2);
|
|
1957
2259
|
__decorateClass([
|
|
1958
|
-
(0,
|
|
2260
|
+
(0, import_decorators11.property)({ attribute: false })
|
|
1959
2261
|
], DawTrackControlsElement.prototype, "trackName", 2);
|
|
1960
2262
|
__decorateClass([
|
|
1961
|
-
(0,
|
|
2263
|
+
(0, import_decorators11.property)({ type: Number, attribute: false })
|
|
1962
2264
|
], DawTrackControlsElement.prototype, "volume", 2);
|
|
1963
2265
|
__decorateClass([
|
|
1964
|
-
(0,
|
|
2266
|
+
(0, import_decorators11.property)({ type: Number, attribute: false })
|
|
1965
2267
|
], DawTrackControlsElement.prototype, "pan", 2);
|
|
1966
2268
|
__decorateClass([
|
|
1967
|
-
(0,
|
|
2269
|
+
(0, import_decorators11.property)({ type: Boolean, attribute: false })
|
|
1968
2270
|
], DawTrackControlsElement.prototype, "muted", 2);
|
|
1969
2271
|
__decorateClass([
|
|
1970
|
-
(0,
|
|
2272
|
+
(0, import_decorators11.property)({ type: Boolean, attribute: false })
|
|
1971
2273
|
], DawTrackControlsElement.prototype, "soloed", 2);
|
|
1972
2274
|
DawTrackControlsElement = __decorateClass([
|
|
1973
|
-
(0,
|
|
2275
|
+
(0, import_decorators11.customElement)("daw-track-controls")
|
|
1974
2276
|
], DawTrackControlsElement);
|
|
1975
2277
|
|
|
1976
2278
|
// src/elements/daw-grid.ts
|
|
1977
|
-
var
|
|
1978
|
-
var
|
|
2279
|
+
var import_lit13 = require("lit");
|
|
2280
|
+
var import_decorators12 = require("lit/decorators.js");
|
|
1979
2281
|
var import_core2 = require("@waveform-playlist/core");
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
var import_core = require("@waveform-playlist/core");
|
|
1983
|
-
var cachedParams = null;
|
|
1984
|
-
var cachedResult = null;
|
|
1985
|
-
function meterEntriesMatch(a, b) {
|
|
1986
|
-
if (a.length !== b.length) return false;
|
|
1987
|
-
for (let i = 0; i < a.length; i++) {
|
|
1988
|
-
if (a[i].tick !== b[i].tick || a[i].numerator !== b[i].numerator || a[i].denominator !== b[i].denominator)
|
|
1989
|
-
return false;
|
|
1990
|
-
}
|
|
1991
|
-
return true;
|
|
1992
|
-
}
|
|
1993
|
-
function paramsMatch(a, b) {
|
|
1994
|
-
return a.ticksPerPixel === b.ticksPerPixel && a.startPixel === b.startPixel && a.endPixel === b.endPixel && meterEntriesMatch(a.meterEntries, b.meterEntries) && (a.ppqn ?? 960) === (b.ppqn ?? 960);
|
|
1995
|
-
}
|
|
1996
|
-
function getCachedMusicalTicks(params) {
|
|
1997
|
-
if (cachedParams && cachedResult && paramsMatch(cachedParams, params)) {
|
|
1998
|
-
return cachedResult;
|
|
1999
|
-
}
|
|
2000
|
-
cachedResult = (0, import_core.computeMusicalTicks)(params);
|
|
2001
|
-
cachedParams = {
|
|
2002
|
-
...params,
|
|
2003
|
-
meterEntries: params.meterEntries.map((e) => ({ ...e }))
|
|
2004
|
-
};
|
|
2005
|
-
return cachedResult;
|
|
2006
|
-
}
|
|
2007
|
-
|
|
2008
|
-
// src/elements/daw-grid.ts
|
|
2009
|
-
var MAX_CANVAS_WIDTH3 = 1e3;
|
|
2010
|
-
var DawGridElement = class extends import_lit12.LitElement {
|
|
2282
|
+
var MAX_CANVAS_WIDTH4 = 1e3;
|
|
2283
|
+
var DawGridElement = class extends import_lit13.LitElement {
|
|
2011
2284
|
constructor() {
|
|
2012
2285
|
super(...arguments);
|
|
2013
2286
|
this.ticksPerPixel = 24;
|
|
@@ -2035,25 +2308,25 @@ var DawGridElement = class extends import_lit12.LitElement {
|
|
|
2035
2308
|
}
|
|
2036
2309
|
}
|
|
2037
2310
|
render() {
|
|
2038
|
-
if (!this._tickData) return
|
|
2311
|
+
if (!this._tickData) return import_lit13.html``;
|
|
2039
2312
|
const totalWidth = this.length;
|
|
2040
2313
|
const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
|
|
2041
2314
|
const indices = getVisibleChunkIndices(
|
|
2042
2315
|
totalWidth,
|
|
2043
|
-
|
|
2316
|
+
MAX_CANVAS_WIDTH4,
|
|
2044
2317
|
this.visibleStart,
|
|
2045
2318
|
this.visibleEnd
|
|
2046
2319
|
);
|
|
2047
|
-
return
|
|
2320
|
+
return import_lit13.html`
|
|
2048
2321
|
<div class="container" style="width: ${totalWidth}px; height: ${this.height}px;">
|
|
2049
2322
|
${indices.map((i) => {
|
|
2050
|
-
const width = Math.min(
|
|
2051
|
-
return
|
|
2323
|
+
const width = Math.min(MAX_CANVAS_WIDTH4, totalWidth - i * MAX_CANVAS_WIDTH4);
|
|
2324
|
+
return import_lit13.html`
|
|
2052
2325
|
<canvas
|
|
2053
2326
|
data-index=${i}
|
|
2054
2327
|
width=${width * dpr}
|
|
2055
2328
|
height=${this.height * dpr}
|
|
2056
|
-
style="left: ${i *
|
|
2329
|
+
style="left: ${i * MAX_CANVAS_WIDTH4}px; width: ${width}px; height: ${this.height}px;"
|
|
2057
2330
|
></canvas>
|
|
2058
2331
|
`;
|
|
2059
2332
|
})}
|
|
@@ -2077,8 +2350,8 @@ var DawGridElement = class extends import_lit12.LitElement {
|
|
|
2077
2350
|
const idx = Number(canvas.dataset.index);
|
|
2078
2351
|
const ctx = canvas.getContext("2d");
|
|
2079
2352
|
if (!ctx) continue;
|
|
2080
|
-
const chunkLeft = idx *
|
|
2081
|
-
const canvasWidth = Math.min(
|
|
2353
|
+
const chunkLeft = idx * MAX_CANVAS_WIDTH4;
|
|
2354
|
+
const canvasWidth = Math.min(MAX_CANVAS_WIDTH4, this.length - chunkLeft);
|
|
2082
2355
|
ctx.resetTransform();
|
|
2083
2356
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2084
2357
|
ctx.scale(dpr, dpr);
|
|
@@ -2109,7 +2382,7 @@ var DawGridElement = class extends import_lit12.LitElement {
|
|
|
2109
2382
|
}
|
|
2110
2383
|
}
|
|
2111
2384
|
};
|
|
2112
|
-
DawGridElement.styles =
|
|
2385
|
+
DawGridElement.styles = import_lit13.css`
|
|
2113
2386
|
:host {
|
|
2114
2387
|
display: block;
|
|
2115
2388
|
position: absolute;
|
|
@@ -2127,33 +2400,33 @@ DawGridElement.styles = import_lit12.css`
|
|
|
2127
2400
|
}
|
|
2128
2401
|
`;
|
|
2129
2402
|
__decorateClass([
|
|
2130
|
-
(0,
|
|
2403
|
+
(0, import_decorators12.property)({ type: Number, attribute: false })
|
|
2131
2404
|
], DawGridElement.prototype, "ticksPerPixel", 2);
|
|
2132
2405
|
__decorateClass([
|
|
2133
|
-
(0,
|
|
2406
|
+
(0, import_decorators12.property)({ attribute: false })
|
|
2134
2407
|
], DawGridElement.prototype, "meterEntries", 2);
|
|
2135
2408
|
__decorateClass([
|
|
2136
|
-
(0,
|
|
2409
|
+
(0, import_decorators12.property)({ type: Number, attribute: false })
|
|
2137
2410
|
], DawGridElement.prototype, "ppqn", 2);
|
|
2138
2411
|
__decorateClass([
|
|
2139
|
-
(0,
|
|
2412
|
+
(0, import_decorators12.property)({ type: Number, attribute: false })
|
|
2140
2413
|
], DawGridElement.prototype, "visibleStart", 2);
|
|
2141
2414
|
__decorateClass([
|
|
2142
|
-
(0,
|
|
2415
|
+
(0, import_decorators12.property)({ type: Number, attribute: false })
|
|
2143
2416
|
], DawGridElement.prototype, "visibleEnd", 2);
|
|
2144
2417
|
__decorateClass([
|
|
2145
|
-
(0,
|
|
2418
|
+
(0, import_decorators12.property)({ type: Number, attribute: false })
|
|
2146
2419
|
], DawGridElement.prototype, "length", 2);
|
|
2147
2420
|
__decorateClass([
|
|
2148
|
-
(0,
|
|
2421
|
+
(0, import_decorators12.property)({ type: Number, attribute: false })
|
|
2149
2422
|
], DawGridElement.prototype, "height", 2);
|
|
2150
2423
|
DawGridElement = __decorateClass([
|
|
2151
|
-
(0,
|
|
2424
|
+
(0, import_decorators12.customElement)("daw-grid")
|
|
2152
2425
|
], DawGridElement);
|
|
2153
2426
|
|
|
2154
2427
|
// src/styles/theme.ts
|
|
2155
|
-
var
|
|
2156
|
-
var hostStyles =
|
|
2428
|
+
var import_lit14 = require("lit");
|
|
2429
|
+
var hostStyles = import_lit14.css`
|
|
2157
2430
|
:host {
|
|
2158
2431
|
--daw-wave-color: #c49a6c;
|
|
2159
2432
|
--daw-progress-color: #63c75f;
|
|
@@ -2169,7 +2442,7 @@ var hostStyles = import_lit13.css`
|
|
|
2169
2442
|
--daw-clip-header-text: #e0d4c8;
|
|
2170
2443
|
}
|
|
2171
2444
|
`;
|
|
2172
|
-
var clipStyles =
|
|
2445
|
+
var clipStyles = import_lit14.css`
|
|
2173
2446
|
.clip-container {
|
|
2174
2447
|
position: absolute;
|
|
2175
2448
|
overflow: hidden;
|
|
@@ -2774,15 +3047,7 @@ var RecordingController = class {
|
|
|
2774
3047
|
|
|
2775
3048
|
// src/controllers/spectrogram-controller.ts
|
|
2776
3049
|
var import_spectrogram = require("@dawcore/spectrogram");
|
|
2777
|
-
var
|
|
2778
|
-
fftSize: 2048,
|
|
2779
|
-
windowFunction: "hann",
|
|
2780
|
-
frequencyScale: "mel",
|
|
2781
|
-
minFrequency: 0,
|
|
2782
|
-
gainDb: 20,
|
|
2783
|
-
rangeDb: 80
|
|
2784
|
-
};
|
|
2785
|
-
var LIBRARY_DEFAULT_COLOR_MAP = "viridis";
|
|
3050
|
+
var import_core4 = require("@waveform-playlist/core");
|
|
2786
3051
|
var SpectrogramController = class {
|
|
2787
3052
|
constructor(host, workerFactory) {
|
|
2788
3053
|
this.orchestrator = null;
|
|
@@ -2856,7 +3121,21 @@ var SpectrogramController = class {
|
|
|
2856
3121
|
const detail = e.detail;
|
|
2857
3122
|
this.host.dispatchEvent(
|
|
2858
3123
|
new CustomEvent("daw-spectrogram-ready", {
|
|
2859
|
-
detail,
|
|
3124
|
+
detail: { trackId: detail.trackId, generation: detail.generation },
|
|
3125
|
+
bubbles: true,
|
|
3126
|
+
composed: true
|
|
3127
|
+
})
|
|
3128
|
+
);
|
|
3129
|
+
});
|
|
3130
|
+
this.orchestrator.addEventListener("viewport-error", (e) => {
|
|
3131
|
+
const detail = e.detail;
|
|
3132
|
+
this.host.dispatchEvent(
|
|
3133
|
+
new CustomEvent("daw-spectrogram-error", {
|
|
3134
|
+
detail: {
|
|
3135
|
+
trackId: detail.trackId,
|
|
3136
|
+
generation: detail.generation,
|
|
3137
|
+
error: detail.error
|
|
3138
|
+
},
|
|
2860
3139
|
bubbles: true,
|
|
2861
3140
|
composed: true
|
|
2862
3141
|
})
|
|
@@ -2877,18 +3156,18 @@ var SpectrogramController = class {
|
|
|
2877
3156
|
track = c;
|
|
2878
3157
|
break;
|
|
2879
3158
|
}
|
|
2880
|
-
return { ...
|
|
3159
|
+
return { ...import_core4.SPECTROGRAM_DEFAULTS, ...this.editorConfig ?? {}, ...track ?? {} };
|
|
2881
3160
|
}
|
|
2882
3161
|
mergedColorMap() {
|
|
2883
3162
|
for (const c of this.trackColorMaps.values()) {
|
|
2884
|
-
return c ??
|
|
3163
|
+
return c ?? import_core4.DEFAULT_SPECTROGRAM_COLOR_MAP;
|
|
2885
3164
|
}
|
|
2886
|
-
return this.editorColorMap ??
|
|
3165
|
+
return this.editorColorMap ?? import_core4.DEFAULT_SPECTROGRAM_COLOR_MAP;
|
|
2887
3166
|
}
|
|
2888
3167
|
};
|
|
2889
3168
|
|
|
2890
3169
|
// src/interactions/pointer-handler.ts
|
|
2891
|
-
var
|
|
3170
|
+
var import_core5 = require("@waveform-playlist/core");
|
|
2892
3171
|
|
|
2893
3172
|
// src/interactions/constants.ts
|
|
2894
3173
|
var DRAG_THRESHOLD = 3;
|
|
@@ -2910,7 +3189,11 @@ var PointerHandler = class {
|
|
|
2910
3189
|
e.preventDefault();
|
|
2911
3190
|
this._timeline = this._host.shadowRoot?.querySelector(".timeline");
|
|
2912
3191
|
if (this._timeline) {
|
|
2913
|
-
|
|
3192
|
+
try {
|
|
3193
|
+
this._timeline.setPointerCapture(e.pointerId);
|
|
3194
|
+
} catch (err) {
|
|
3195
|
+
console.warn("[dawcore] setPointerCapture failed: " + String(err));
|
|
3196
|
+
}
|
|
2914
3197
|
const onMove = (me) => clipHandler.onPointerMove(me);
|
|
2915
3198
|
const onUp = (ue) => {
|
|
2916
3199
|
clipHandler.onPointerUp(ue);
|
|
@@ -2932,11 +3215,20 @@ var PointerHandler = class {
|
|
|
2932
3215
|
}
|
|
2933
3216
|
}
|
|
2934
3217
|
this._timeline = this._host.shadowRoot?.querySelector(".timeline");
|
|
2935
|
-
if (!this._timeline)
|
|
3218
|
+
if (!this._timeline) {
|
|
3219
|
+
console.warn(
|
|
3220
|
+
"[dawcore] PointerHandler: .timeline not found in shadow root \u2014 seek/selection ignored"
|
|
3221
|
+
);
|
|
3222
|
+
return;
|
|
3223
|
+
}
|
|
2936
3224
|
this._timelineRect = this._timeline.getBoundingClientRect();
|
|
2937
3225
|
this._dragStartPx = this._pxFromPointer(e);
|
|
2938
3226
|
this._isDragging = false;
|
|
2939
|
-
|
|
3227
|
+
try {
|
|
3228
|
+
this._timeline.setPointerCapture(e.pointerId);
|
|
3229
|
+
} catch (err) {
|
|
3230
|
+
console.warn("[dawcore] setPointerCapture failed: " + String(err));
|
|
3231
|
+
}
|
|
2940
3232
|
this._timeline.addEventListener("pointermove", this._onPointerMove);
|
|
2941
3233
|
this._timeline.addEventListener("pointerup", this._onPointerUp);
|
|
2942
3234
|
};
|
|
@@ -2998,10 +3290,10 @@ var PointerHandler = class {
|
|
|
2998
3290
|
const h = this._host;
|
|
2999
3291
|
if (h.scaleMode === "beats") {
|
|
3000
3292
|
let tick = px * h.ticksPerPixel;
|
|
3001
|
-
tick = (0,
|
|
3293
|
+
tick = (0, import_core5.snapTickToGrid)(tick, h.snapTo, h._meterEntries, h.ppqn);
|
|
3002
3294
|
return h._ticksToSeconds(tick);
|
|
3003
3295
|
}
|
|
3004
|
-
return (0,
|
|
3296
|
+
return (0, import_core5.pixelsToSeconds)(px, h.samplesPerPixel, h.effectiveSampleRate);
|
|
3005
3297
|
}
|
|
3006
3298
|
_timeToPx(time) {
|
|
3007
3299
|
const h = this._host;
|
|
@@ -3093,7 +3385,7 @@ var PointerHandler = class {
|
|
|
3093
3385
|
};
|
|
3094
3386
|
|
|
3095
3387
|
// src/interactions/clip-pointer-handler.ts
|
|
3096
|
-
var
|
|
3388
|
+
var import_core6 = require("@waveform-playlist/core");
|
|
3097
3389
|
var ClipPointerHandler = class {
|
|
3098
3390
|
constructor(host) {
|
|
3099
3391
|
this._mode = null;
|
|
@@ -3127,7 +3419,7 @@ var ClipPointerHandler = class {
|
|
|
3127
3419
|
const anchorTick = h._secondsToTicks(anchorSeconds);
|
|
3128
3420
|
const deltaTicks = totalDeltaPx * h.ticksPerPixel;
|
|
3129
3421
|
const targetTick = anchorTick + deltaTicks;
|
|
3130
|
-
const snappedTick = h.snapTo !== "off" ? (0,
|
|
3422
|
+
const snappedTick = h.snapTo !== "off" ? (0, import_core6.snapTickToGrid)(targetTick, h.snapTo, h._meterEntries, h.ppqn) : targetTick;
|
|
3131
3423
|
const snappedSeconds = h._ticksToSeconds(snappedTick);
|
|
3132
3424
|
const snappedSample = Math.round(snappedSeconds * h.effectiveSampleRate);
|
|
3133
3425
|
return snappedSample - anchorSample;
|
|
@@ -3390,7 +3682,7 @@ var ClipPointerHandler = class {
|
|
|
3390
3682
|
};
|
|
3391
3683
|
|
|
3392
3684
|
// src/interactions/file-loader.ts
|
|
3393
|
-
var
|
|
3685
|
+
var import_core7 = require("@waveform-playlist/core");
|
|
3394
3686
|
async function loadFiles(host, files) {
|
|
3395
3687
|
if (!files) {
|
|
3396
3688
|
console.warn("[dawcore] loadFiles called with null/undefined");
|
|
@@ -3412,7 +3704,7 @@ async function loadFiles(host, files) {
|
|
|
3412
3704
|
host._audioCache.delete(blobUrl);
|
|
3413
3705
|
host._resolvedSampleRate = audioBuffer.sampleRate;
|
|
3414
3706
|
const name = file.name.replace(/\.\w+$/, "");
|
|
3415
|
-
const clip = (0,
|
|
3707
|
+
const clip = (0, import_core7.createClip)({
|
|
3416
3708
|
audioBuffer,
|
|
3417
3709
|
startSample: 0,
|
|
3418
3710
|
durationSamples: audioBuffer.length,
|
|
@@ -3436,7 +3728,7 @@ async function loadFiles(host, files) {
|
|
|
3436
3728
|
);
|
|
3437
3729
|
host._peaksData = new Map(host._peaksData).set(clip.id, peakData);
|
|
3438
3730
|
const trackId = crypto.randomUUID();
|
|
3439
|
-
const track = (0,
|
|
3731
|
+
const track = (0, import_core7.createTrack)({ name, clips: [clip] });
|
|
3440
3732
|
track.id = trackId;
|
|
3441
3733
|
host._tracks = new Map(host._tracks).set(trackId, {
|
|
3442
3734
|
name,
|
|
@@ -3598,7 +3890,7 @@ function stringifyReason(reason) {
|
|
|
3598
3890
|
}
|
|
3599
3891
|
|
|
3600
3892
|
// src/interactions/recording-clip.ts
|
|
3601
|
-
var
|
|
3893
|
+
var import_core8 = require("@waveform-playlist/core");
|
|
3602
3894
|
function addRecordedClip(host, trackId, buf, startSample, durSamples, offsetSamples = 0) {
|
|
3603
3895
|
let trimmedBuf = buf;
|
|
3604
3896
|
if (offsetSamples > 0 && offsetSamples < buf.length) {
|
|
@@ -3613,7 +3905,7 @@ function addRecordedClip(host, trackId, buf, startSample, durSamples, offsetSamp
|
|
|
3613
3905
|
}
|
|
3614
3906
|
trimmedBuf = trimmed;
|
|
3615
3907
|
}
|
|
3616
|
-
const clip = (0,
|
|
3908
|
+
const clip = (0, import_core8.createClip)({
|
|
3617
3909
|
audioBuffer: trimmedBuf,
|
|
3618
3910
|
startSample,
|
|
3619
3911
|
durationSamples: durSamples,
|
|
@@ -3868,10 +4160,144 @@ async function loadWaveformDataFromUrl(src) {
|
|
|
3868
4160
|
}
|
|
3869
4161
|
}
|
|
3870
4162
|
|
|
4163
|
+
// src/controllers/scroll-sync-controller.ts
|
|
4164
|
+
var LINE_HEIGHT_PX = 16;
|
|
4165
|
+
var ScrollSyncController = class {
|
|
4166
|
+
constructor(host) {
|
|
4167
|
+
this._scrollContainer = null;
|
|
4168
|
+
this._wheelTargets = /* @__PURE__ */ new Set();
|
|
4169
|
+
this._warnedX = false;
|
|
4170
|
+
this._warnedY = false;
|
|
4171
|
+
/** Selector (in host shadow DOM) for the scroll container. */
|
|
4172
|
+
this.scrollSelector = "";
|
|
4173
|
+
/** Selector for the element receiving translate3d(-scrollLeft, 0, 0). */
|
|
4174
|
+
this.xTargetSelector = "";
|
|
4175
|
+
/** Selector for the element receiving translate3d(0, -scrollTop, 0). */
|
|
4176
|
+
this.yTargetSelector = "";
|
|
4177
|
+
/**
|
|
4178
|
+
* Selector (or comma-separated selectors) for elements whose wheel events
|
|
4179
|
+
* forward to the scroll container. All matching elements receive listeners.
|
|
4180
|
+
*/
|
|
4181
|
+
this.wheelForwardSelector = "";
|
|
4182
|
+
this._onScroll = () => {
|
|
4183
|
+
this._apply();
|
|
4184
|
+
};
|
|
4185
|
+
this._onWheel = (e) => {
|
|
4186
|
+
const sc = this._scrollContainer;
|
|
4187
|
+
if (!sc) return;
|
|
4188
|
+
const scale = e.deltaMode === WheelEvent.DOM_DELTA_LINE ? LINE_HEIGHT_PX : e.deltaMode === WheelEvent.DOM_DELTA_PAGE ? sc.clientHeight : 1;
|
|
4189
|
+
const scaleX = e.deltaMode === WheelEvent.DOM_DELTA_PAGE ? sc.clientWidth : scale;
|
|
4190
|
+
const beforeLeft = sc.scrollLeft;
|
|
4191
|
+
const beforeTop = sc.scrollTop;
|
|
4192
|
+
sc.scrollLeft += e.deltaX * scaleX;
|
|
4193
|
+
sc.scrollTop += e.deltaY * scale;
|
|
4194
|
+
if (sc.scrollLeft !== beforeLeft || sc.scrollTop !== beforeTop) {
|
|
4195
|
+
e.preventDefault();
|
|
4196
|
+
}
|
|
4197
|
+
};
|
|
4198
|
+
this._host = host;
|
|
4199
|
+
host.addController(this);
|
|
4200
|
+
}
|
|
4201
|
+
hostConnected() {
|
|
4202
|
+
requestAnimationFrame(() => {
|
|
4203
|
+
if (!this._host.isConnected) return;
|
|
4204
|
+
this._attach();
|
|
4205
|
+
if (!this._scrollContainer && this.scrollSelector) {
|
|
4206
|
+
console.warn(
|
|
4207
|
+
'[dawcore] ScrollSyncController: scroll container not found for "' + this.scrollSelector + '"'
|
|
4208
|
+
);
|
|
4209
|
+
}
|
|
4210
|
+
});
|
|
4211
|
+
}
|
|
4212
|
+
hostDisconnected() {
|
|
4213
|
+
this._scrollContainer?.removeEventListener("scroll", this._onScroll);
|
|
4214
|
+
this._scrollContainer = null;
|
|
4215
|
+
for (const target of this._wheelTargets) {
|
|
4216
|
+
target.removeEventListener("wheel", this._onWheel);
|
|
4217
|
+
}
|
|
4218
|
+
this._wheelTargets.clear();
|
|
4219
|
+
}
|
|
4220
|
+
/**
|
|
4221
|
+
* Re-attach and re-apply transforms from the current scroll position.
|
|
4222
|
+
* Called from the host's updated() so elements created by a re-render
|
|
4223
|
+
* (e.g. the ruler appearing when the first track loads) pick up the
|
|
4224
|
+
* current offset and listeners.
|
|
4225
|
+
*/
|
|
4226
|
+
sync() {
|
|
4227
|
+
this._attach();
|
|
4228
|
+
}
|
|
4229
|
+
_query(selector) {
|
|
4230
|
+
return selector ? this._host.shadowRoot?.querySelector(selector) : null;
|
|
4231
|
+
}
|
|
4232
|
+
_queryAll(selector) {
|
|
4233
|
+
if (!selector) return [];
|
|
4234
|
+
return Array.from(this._host.shadowRoot?.querySelectorAll(selector) ?? []);
|
|
4235
|
+
}
|
|
4236
|
+
_attach() {
|
|
4237
|
+
const container = this._query(this.scrollSelector);
|
|
4238
|
+
if (!container) {
|
|
4239
|
+
if (this._scrollContainer && !this._scrollContainer.isConnected) {
|
|
4240
|
+
console.warn(
|
|
4241
|
+
'[dawcore] ScrollSyncController: scroll container "' + this.scrollSelector + '" was removed from the DOM \u2014 detaching listeners until it reappears.'
|
|
4242
|
+
);
|
|
4243
|
+
this._scrollContainer.removeEventListener("scroll", this._onScroll);
|
|
4244
|
+
this._scrollContainer = null;
|
|
4245
|
+
for (const t of this._wheelTargets) t.removeEventListener("wheel", this._onWheel);
|
|
4246
|
+
this._wheelTargets.clear();
|
|
4247
|
+
}
|
|
4248
|
+
return;
|
|
4249
|
+
}
|
|
4250
|
+
if (container !== this._scrollContainer) {
|
|
4251
|
+
this._scrollContainer?.removeEventListener("scroll", this._onScroll);
|
|
4252
|
+
this._scrollContainer = container;
|
|
4253
|
+
container.addEventListener("scroll", this._onScroll, { passive: true });
|
|
4254
|
+
}
|
|
4255
|
+
const nextTargets = new Set(this._queryAll(this.wheelForwardSelector));
|
|
4256
|
+
for (const old of this._wheelTargets) {
|
|
4257
|
+
if (!nextTargets.has(old)) {
|
|
4258
|
+
old.removeEventListener("wheel", this._onWheel);
|
|
4259
|
+
this._wheelTargets.delete(old);
|
|
4260
|
+
}
|
|
4261
|
+
}
|
|
4262
|
+
for (const next of nextTargets) {
|
|
4263
|
+
if (!this._wheelTargets.has(next)) {
|
|
4264
|
+
next.addEventListener("wheel", this._onWheel, { passive: false });
|
|
4265
|
+
this._wheelTargets.add(next);
|
|
4266
|
+
}
|
|
4267
|
+
}
|
|
4268
|
+
this._apply();
|
|
4269
|
+
}
|
|
4270
|
+
_apply() {
|
|
4271
|
+
const sc = this._scrollContainer;
|
|
4272
|
+
if (!sc) return;
|
|
4273
|
+
const xTarget = this._query(this.xTargetSelector);
|
|
4274
|
+
if (xTarget) {
|
|
4275
|
+
xTarget.style.transform = `translate3d(${-sc.scrollLeft}px, 0, 0)`;
|
|
4276
|
+
this._warnedX = false;
|
|
4277
|
+
} else if (this.xTargetSelector && sc.scrollLeft !== 0 && !this._warnedX) {
|
|
4278
|
+
this._warnedX = true;
|
|
4279
|
+
console.warn(
|
|
4280
|
+
'[dawcore] ScrollSyncController: x target "' + this.xTargetSelector + '" not found while scrolled \u2014 the synced pane will appear frozen. Check the selector, or clear it if the target is intentionally not rendered.'
|
|
4281
|
+
);
|
|
4282
|
+
}
|
|
4283
|
+
const yTarget = this._query(this.yTargetSelector);
|
|
4284
|
+
if (yTarget) {
|
|
4285
|
+
yTarget.style.transform = `translate3d(0, ${-sc.scrollTop}px, 0)`;
|
|
4286
|
+
this._warnedY = false;
|
|
4287
|
+
} else if (this.yTargetSelector && sc.scrollTop !== 0 && !this._warnedY) {
|
|
4288
|
+
this._warnedY = true;
|
|
4289
|
+
console.warn(
|
|
4290
|
+
'[dawcore] ScrollSyncController: y target "' + this.yTargetSelector + '" not found while scrolled \u2014 the synced pane will appear frozen. Check the selector, or clear it if the target is intentionally not rendered.'
|
|
4291
|
+
);
|
|
4292
|
+
}
|
|
4293
|
+
}
|
|
4294
|
+
};
|
|
4295
|
+
|
|
3871
4296
|
// src/elements/daw-editor.ts
|
|
3872
4297
|
var import_meta = {};
|
|
4298
|
+
var RULER_HEIGHT = 30;
|
|
3873
4299
|
var NO_ADAPTER_ERROR = "No PlayoutAdapter set on <daw-editor>. Set editor.adapter before use.\n\n // Option 1: Native Web Audio (no Tone.js)\n npm install @dawcore/transport\n import { NativePlayoutAdapter } from '@dawcore/transport';\n editor.adapter = new NativePlayoutAdapter(new AudioContext());\n\n // Option 2: Tone.js (effects, MIDI synths)\n npm install @waveform-playlist/playout\n import { createToneAdapter } from '@waveform-playlist/playout';\n editor.adapter = createToneAdapter();";
|
|
3874
|
-
var DawEditorElement = class extends
|
|
4300
|
+
var DawEditorElement = class extends import_lit15.LitElement {
|
|
3875
4301
|
constructor() {
|
|
3876
4302
|
super(...arguments);
|
|
3877
4303
|
this._samplesPerPixel = 1024;
|
|
@@ -3930,13 +4356,21 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
3930
4356
|
v.scrollSelector = ".scroll-area";
|
|
3931
4357
|
return v;
|
|
3932
4358
|
})();
|
|
4359
|
+
this._scrollSync = (() => {
|
|
4360
|
+
const s = new ScrollSyncController(this);
|
|
4361
|
+
s.scrollSelector = ".scroll-area";
|
|
4362
|
+
return s;
|
|
4363
|
+
})();
|
|
3933
4364
|
/**
|
|
3934
4365
|
* Cache of the last ViewportState forwarded to the spectrogram controller.
|
|
3935
4366
|
* Lit's `updated()` fires on every reactive state change (`_isPlaying`,
|
|
3936
4367
|
* `_selectedTrackId`, etc.) — most of which don't affect the spectrogram
|
|
3937
4368
|
* viewport. Skip the cross-controller call when nothing changed.
|
|
3938
4369
|
*
|
|
3939
|
-
* The orchestrator dedupes too,
|
|
4370
|
+
* The orchestrator dedupes identical viewports too, so removing this cache
|
|
4371
|
+
* wouldn't change observable behavior — but it would push a fresh
|
|
4372
|
+
* `setViewport` call (with object allocation) into every Lit reactive
|
|
4373
|
+
* update for properties unrelated to the viewport.
|
|
3940
4374
|
*/
|
|
3941
4375
|
this._lastSpectrogramViewport = null;
|
|
3942
4376
|
// --- Track Events ---
|
|
@@ -4179,9 +4613,10 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
4179
4613
|
this._spectrogramController?.unregisterCanvas(canvasId);
|
|
4180
4614
|
}
|
|
4181
4615
|
/**
|
|
4182
|
-
*
|
|
4183
|
-
*
|
|
4184
|
-
*
|
|
4616
|
+
* Forward a clip's AudioBuffer to the spectrogram controller if the parent
|
|
4617
|
+
* track is in spectrogram render-mode. Eagerly creates the controller via
|
|
4618
|
+
* `_ensureSpectrogramController` so the audio data is queued for the first
|
|
4619
|
+
* render — even if no canvases have been registered yet.
|
|
4185
4620
|
*/
|
|
4186
4621
|
_maybeRegisterSpectrogramClipAudio(trackId, clip) {
|
|
4187
4622
|
const descriptor = this._tracks.get(trackId);
|
|
@@ -4472,6 +4907,13 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
4472
4907
|
}
|
|
4473
4908
|
}
|
|
4474
4909
|
updated(_changed) {
|
|
4910
|
+
this._scrollSync.xTargetSelector = this._showRuler ? ".ruler-content" : "";
|
|
4911
|
+
this._scrollSync.yTargetSelector = this._showControls ? ".controls-column" : "";
|
|
4912
|
+
this._scrollSync.wheelForwardSelector = [
|
|
4913
|
+
this._showControls ? ".controls-viewport" : "",
|
|
4914
|
+
this._showRuler ? ".ruler-viewport" : ""
|
|
4915
|
+
].filter(Boolean).join(", ");
|
|
4916
|
+
this._scrollSync.sync();
|
|
4475
4917
|
if (this._spectrogramController) {
|
|
4476
4918
|
const vs = this._viewport.visibleStart;
|
|
4477
4919
|
const ve = this._viewport.visibleEnd;
|
|
@@ -4632,7 +5074,7 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
4632
5074
|
let clip;
|
|
4633
5075
|
if (waveformData) {
|
|
4634
5076
|
const wdRate = waveformData.sample_rate;
|
|
4635
|
-
clip = (0,
|
|
5077
|
+
clip = (0, import_core9.createClip)({
|
|
4636
5078
|
audioBuffer,
|
|
4637
5079
|
waveformData,
|
|
4638
5080
|
startSample: Math.round(clipDesc.start * wdRate),
|
|
@@ -4645,7 +5087,7 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
4645
5087
|
});
|
|
4646
5088
|
this._peakPipeline.cacheWaveformData(audioBuffer, waveformData);
|
|
4647
5089
|
} else {
|
|
4648
|
-
clip = (0,
|
|
5090
|
+
clip = (0, import_core9.createClipFromSeconds)({
|
|
4649
5091
|
audioBuffer,
|
|
4650
5092
|
startTime: clipDesc.start,
|
|
4651
5093
|
duration: clipDesc.duration || audioBuffer.duration,
|
|
@@ -4725,7 +5167,7 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
4725
5167
|
const noteSpanSeconds = notes.length ? notes.reduce((max, n) => Math.max(max, n.time + n.duration), 0) : 0;
|
|
4726
5168
|
const sourceDurationSamples = Math.ceil(Math.max(noteSpanSeconds, clipDesc.duration, 1) * sr);
|
|
4727
5169
|
const requestedDurationSamples = clipDesc.duration > 0 ? Math.round(clipDesc.duration * sr) : sourceDurationSamples;
|
|
4728
|
-
const clip = (0,
|
|
5170
|
+
const clip = (0, import_core9.createClip)({
|
|
4729
5171
|
startSample: Math.round(clipDesc.start * sr),
|
|
4730
5172
|
durationSamples: requestedDurationSamples,
|
|
4731
5173
|
offsetSamples: Math.round(clipDesc.offset * sr),
|
|
@@ -4934,7 +5376,7 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
4934
5376
|
const waveformData = await waveformDataPromise;
|
|
4935
5377
|
if (waveformData) {
|
|
4936
5378
|
const wdRate = waveformData.sample_rate;
|
|
4937
|
-
const clip2 = (0,
|
|
5379
|
+
const clip2 = (0, import_core9.createClip)({
|
|
4938
5380
|
waveformData,
|
|
4939
5381
|
startSample: Math.round(clipDesc.start * wdRate),
|
|
4940
5382
|
durationSamples: Math.round((clipDesc.duration || waveformData.duration) * wdRate),
|
|
@@ -4959,7 +5401,7 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
4959
5401
|
});
|
|
4960
5402
|
this._peaksData = new Map(this._peaksData).set(clip2.id, peakData);
|
|
4961
5403
|
this._minSamplesPerPixel = Math.max(this._minSamplesPerPixel, waveformData.scale);
|
|
4962
|
-
const previewTrack = (0,
|
|
5404
|
+
const previewTrack = (0, import_core9.createTrack)({
|
|
4963
5405
|
name: descriptor.name,
|
|
4964
5406
|
clips: [clip2],
|
|
4965
5407
|
volume: descriptor.volume,
|
|
@@ -5015,7 +5457,7 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
5015
5457
|
}
|
|
5016
5458
|
}
|
|
5017
5459
|
}
|
|
5018
|
-
const track = (0,
|
|
5460
|
+
const track = (0, import_core9.createTrack)({
|
|
5019
5461
|
name: descriptor.name,
|
|
5020
5462
|
clips,
|
|
5021
5463
|
volume: descriptor.volume,
|
|
@@ -5298,6 +5740,13 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
5298
5740
|
}
|
|
5299
5741
|
const oldDesc = this._tracks.get(trackId);
|
|
5300
5742
|
if (!oldDesc) return;
|
|
5743
|
+
let normalizedRenderMode = partial.renderMode;
|
|
5744
|
+
if (normalizedRenderMode === "both") {
|
|
5745
|
+
console.warn(
|
|
5746
|
+
`[dawcore] render-mode="both" is not yet supported; falling back to 'spectrogram'`
|
|
5747
|
+
);
|
|
5748
|
+
normalizedRenderMode = "spectrogram";
|
|
5749
|
+
}
|
|
5301
5750
|
const newDesc = {
|
|
5302
5751
|
...oldDesc,
|
|
5303
5752
|
...partial.name !== void 0 && { name: partial.name },
|
|
@@ -5305,7 +5754,7 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
5305
5754
|
...partial.pan !== void 0 && { pan: partial.pan },
|
|
5306
5755
|
...partial.muted !== void 0 && { muted: partial.muted },
|
|
5307
5756
|
...partial.soloed !== void 0 && { soloed: partial.soloed },
|
|
5308
|
-
...
|
|
5757
|
+
...normalizedRenderMode !== void 0 && { renderMode: normalizedRenderMode }
|
|
5309
5758
|
};
|
|
5310
5759
|
this._tracks = new Map(this._tracks).set(trackId, newDesc);
|
|
5311
5760
|
if (this._engine) {
|
|
@@ -5626,7 +6075,7 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
5626
6075
|
const w = Math.floor(audibleSamples / renderSpp);
|
|
5627
6076
|
return rs.peaks.map((chPeaks, ch) => {
|
|
5628
6077
|
const slicedPeaks = latencyPixels > 0 ? chPeaks.slice(latencyPixels * 2) : chPeaks;
|
|
5629
|
-
return
|
|
6078
|
+
return import_lit15.html`
|
|
5630
6079
|
<daw-waveform
|
|
5631
6080
|
data-recording-track=${trackId}
|
|
5632
6081
|
data-recording-channel=${ch}
|
|
@@ -5682,6 +6131,14 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
5682
6131
|
_getPlayhead() {
|
|
5683
6132
|
return this.shadowRoot?.querySelector("daw-playhead");
|
|
5684
6133
|
}
|
|
6134
|
+
/** True when the controls column should be rendered (and its selector is valid). */
|
|
6135
|
+
get _showControls() {
|
|
6136
|
+
return this._getOrderedTracks().length > 0 || this.indefinitePlayback;
|
|
6137
|
+
}
|
|
6138
|
+
/** True when the ruler header band should be rendered (and its selector is valid). */
|
|
6139
|
+
get _showRuler() {
|
|
6140
|
+
return (this._getOrderedTracks().length > 0 || this.scaleMode === "beats" || this.indefinitePlayback) && this.timescale;
|
|
6141
|
+
}
|
|
5685
6142
|
_getOrderedTracks() {
|
|
5686
6143
|
const domOrder = [...this.querySelectorAll("daw-track")].map(
|
|
5687
6144
|
(el) => el.trackId
|
|
@@ -5723,64 +6180,79 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
5723
6180
|
trackHeight: this.waveHeight * numChannels + (this.clipHeaders ? this.clipHeaderHeight : 0)
|
|
5724
6181
|
};
|
|
5725
6182
|
});
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
style="height: ${t.trackHeight}px;"
|
|
5733
|
-
.trackId=${t.trackId}
|
|
5734
|
-
.trackName=${t.descriptor?.name ?? "Untitled"}
|
|
5735
|
-
.volume=${t.descriptor?.volume ?? 1}
|
|
5736
|
-
.pan=${t.descriptor?.pan ?? 0}
|
|
5737
|
-
.muted=${t.descriptor?.muted ?? false}
|
|
5738
|
-
.soloed=${t.descriptor?.soloed ?? false}
|
|
5739
|
-
></daw-track-controls>
|
|
5740
|
-
`
|
|
5741
|
-
)}
|
|
5742
|
-
</div>` : ""}
|
|
5743
|
-
<div class="scroll-area">
|
|
5744
|
-
<div
|
|
5745
|
-
class="timeline ${this._dragOver ? "drag-over" : ""}"
|
|
5746
|
-
style="width: ${this._totalWidth > 0 ? this._totalWidth + "px" : "100%"};"
|
|
5747
|
-
data-playing=${this._isPlaying}
|
|
5748
|
-
@pointerdown=${this._pointer.onPointerDown}
|
|
5749
|
-
@dragover=${this._onDragOver}
|
|
5750
|
-
@dragleave=${this._onDragLeave}
|
|
5751
|
-
@drop=${this._onDrop}
|
|
5752
|
-
>
|
|
5753
|
-
${(orderedTracks.length > 0 || this.scaleMode === "beats" || this.indefinitePlayback) && this.timescale ? import_lit14.html`<daw-ruler
|
|
5754
|
-
.samplesPerPixel=${spp}
|
|
5755
|
-
.sampleRate=${this.effectiveSampleRate}
|
|
5756
|
-
.duration=${this._duration}
|
|
5757
|
-
.scaleMode=${this.scaleMode}
|
|
5758
|
-
.ticksPerPixel=${this.ticksPerPixel}
|
|
5759
|
-
.meterEntries=${this._meterEntries}
|
|
5760
|
-
.ppqn=${this.ppqn}
|
|
5761
|
-
.totalWidth=${this._totalWidth}
|
|
5762
|
-
></daw-ruler>` : ""}
|
|
5763
|
-
${this.scaleMode === "beats" ? import_lit14.html`<daw-grid
|
|
5764
|
-
style="top: ${this.timescale ? 30 : 0}px;"
|
|
5765
|
-
.ticksPerPixel=${this.ticksPerPixel}
|
|
5766
|
-
.meterEntries=${this._meterEntries}
|
|
5767
|
-
.ppqn=${this.ppqn}
|
|
5768
|
-
.visibleStart=${this._viewport.visibleStart}
|
|
5769
|
-
.visibleEnd=${this._viewport.visibleEnd}
|
|
5770
|
-
.length=${this._totalWidth}
|
|
5771
|
-
.height=${orderedTracks.length > 0 ? orderedTracks.reduce((sum, t) => sum + t.trackHeight + 1, 0) : this._emptyGridHeight}
|
|
5772
|
-
></daw-grid>` : ""}
|
|
5773
|
-
${orderedTracks.length > 0 || this.scaleMode === "beats" || this.indefinitePlayback ? import_lit14.html`<daw-selection .startPx=${selStartPx} .endPx=${selEndPx}></daw-selection>
|
|
5774
|
-
<daw-playhead></daw-playhead>` : ""}
|
|
5775
|
-
${orderedTracks.map((t) => {
|
|
5776
|
-
const channelHeight = this.waveHeight;
|
|
5777
|
-
return import_lit14.html`
|
|
6183
|
+
const showControls = this._showControls;
|
|
6184
|
+
const showRuler = this._showRuler;
|
|
6185
|
+
return import_lit15.html`
|
|
6186
|
+
${showRuler ? import_lit15.html`<div class="header-row" style="height: ${RULER_HEIGHT}px;">
|
|
6187
|
+
${showControls ? import_lit15.html`<div class="ruler-gap"></div>` : ""}
|
|
6188
|
+
<div class="ruler-viewport" @pointerdown=${this._pointer.onPointerDown}>
|
|
5778
6189
|
<div
|
|
5779
|
-
class="
|
|
5780
|
-
style="
|
|
5781
|
-
data-track-id=${t.trackId}
|
|
6190
|
+
class="ruler-content"
|
|
6191
|
+
style="width: ${this._totalWidth > 0 ? this._totalWidth + "px" : "100%"};"
|
|
5782
6192
|
>
|
|
5783
|
-
|
|
6193
|
+
<daw-ruler
|
|
6194
|
+
.samplesPerPixel=${spp}
|
|
6195
|
+
.sampleRate=${this.effectiveSampleRate}
|
|
6196
|
+
.duration=${this._duration}
|
|
6197
|
+
.scaleMode=${this.scaleMode}
|
|
6198
|
+
.ticksPerPixel=${this.ticksPerPixel}
|
|
6199
|
+
.meterEntries=${this._meterEntries}
|
|
6200
|
+
.ppqn=${this.ppqn}
|
|
6201
|
+
.totalWidth=${this._totalWidth}
|
|
6202
|
+
.rulerHeight=${RULER_HEIGHT}
|
|
6203
|
+
></daw-ruler>
|
|
6204
|
+
</div>
|
|
6205
|
+
</div>
|
|
6206
|
+
</div>` : ""}
|
|
6207
|
+
<div class="body">
|
|
6208
|
+
${showControls ? import_lit15.html`<div class="controls-viewport">
|
|
6209
|
+
<div class="controls-column">
|
|
6210
|
+
${orderedTracks.map(
|
|
6211
|
+
(t) => import_lit15.html`
|
|
6212
|
+
<daw-track-controls
|
|
6213
|
+
style="height: ${t.trackHeight}px;"
|
|
6214
|
+
.trackId=${t.trackId}
|
|
6215
|
+
.trackName=${t.descriptor?.name ?? "Untitled"}
|
|
6216
|
+
.volume=${t.descriptor?.volume ?? 1}
|
|
6217
|
+
.pan=${t.descriptor?.pan ?? 0}
|
|
6218
|
+
.muted=${t.descriptor?.muted ?? false}
|
|
6219
|
+
.soloed=${t.descriptor?.soloed ?? false}
|
|
6220
|
+
></daw-track-controls>
|
|
6221
|
+
`
|
|
6222
|
+
)}
|
|
6223
|
+
</div>
|
|
6224
|
+
</div>` : ""}
|
|
6225
|
+
<div class="scroll-area">
|
|
6226
|
+
<div
|
|
6227
|
+
class="timeline ${this._dragOver ? "drag-over" : ""}"
|
|
6228
|
+
style="width: ${this._totalWidth > 0 ? this._totalWidth + "px" : "100%"};"
|
|
6229
|
+
data-playing=${this._isPlaying}
|
|
6230
|
+
@pointerdown=${this._pointer.onPointerDown}
|
|
6231
|
+
@dragover=${this._onDragOver}
|
|
6232
|
+
@dragleave=${this._onDragLeave}
|
|
6233
|
+
@drop=${this._onDrop}
|
|
6234
|
+
>
|
|
6235
|
+
${this.scaleMode === "beats" ? import_lit15.html`<daw-grid
|
|
6236
|
+
style="top: 0px;"
|
|
6237
|
+
.ticksPerPixel=${this.ticksPerPixel}
|
|
6238
|
+
.meterEntries=${this._meterEntries}
|
|
6239
|
+
.ppqn=${this.ppqn}
|
|
6240
|
+
.visibleStart=${this._viewport.visibleStart}
|
|
6241
|
+
.visibleEnd=${this._viewport.visibleEnd}
|
|
6242
|
+
.length=${this._totalWidth}
|
|
6243
|
+
.height=${orderedTracks.length > 0 ? orderedTracks.reduce((sum, t) => sum + t.trackHeight, 0) : this._emptyGridHeight}
|
|
6244
|
+
></daw-grid>` : ""}
|
|
6245
|
+
${orderedTracks.length > 0 || this.scaleMode === "beats" || this.indefinitePlayback ? import_lit15.html`<daw-selection .startPx=${selStartPx} .endPx=${selEndPx}></daw-selection>
|
|
6246
|
+
<daw-playhead></daw-playhead>` : ""}
|
|
6247
|
+
${orderedTracks.map((t) => {
|
|
6248
|
+
const channelHeight = this.waveHeight;
|
|
6249
|
+
return import_lit15.html`
|
|
6250
|
+
<div
|
|
6251
|
+
class="track-row ${t.trackId === this._selectedTrackId ? "selected" : ""}"
|
|
6252
|
+
style="height: ${t.trackHeight}px;"
|
|
6253
|
+
data-track-id=${t.trackId}
|
|
6254
|
+
>
|
|
6255
|
+
${t.track.clips.map((clip) => {
|
|
5784
6256
|
const peakData = this._peaksData.get(clip.id);
|
|
5785
6257
|
let clipLeft;
|
|
5786
6258
|
let width;
|
|
@@ -5793,7 +6265,7 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
5793
6265
|
width = Math.round(endTick / this.ticksPerPixel) - clipLeft;
|
|
5794
6266
|
} else {
|
|
5795
6267
|
clipLeft = Math.floor(clip.startSample / spp);
|
|
5796
|
-
width = (0,
|
|
6268
|
+
width = (0, import_core9.clipPixelWidth)(clip.startSample, clip.durationSamples, spp);
|
|
5797
6269
|
}
|
|
5798
6270
|
let clipSegments;
|
|
5799
6271
|
let segmentChannels;
|
|
@@ -5823,7 +6295,10 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
5823
6295
|
const segEndSample = Math.round(segEndAudioSec * sr);
|
|
5824
6296
|
const totalPeaks = clip.durationSamples / baseScale;
|
|
5825
6297
|
clipSegments.push({
|
|
5826
|
-
peakStart: Math.max(
|
|
6298
|
+
peakStart: Math.max(
|
|
6299
|
+
0,
|
|
6300
|
+
(segStartSample - clip.offsetSamples) / baseScale
|
|
6301
|
+
),
|
|
5827
6302
|
peakEnd: Math.min(
|
|
5828
6303
|
totalPeaks,
|
|
5829
6304
|
(segEndSample - clip.offsetSamples) / baseScale
|
|
@@ -5837,78 +6312,79 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
5837
6312
|
const channels = segmentChannels ?? peakData?.data ?? [new Int16Array(0)];
|
|
5838
6313
|
const hdrH = this.clipHeaders ? this.clipHeaderHeight : 0;
|
|
5839
6314
|
const chH = this.waveHeight;
|
|
5840
|
-
return
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
data-clip-id=${clip.id}
|
|
5848
|
-
data-track-id=${t.trackId}
|
|
5849
|
-
?data-interactive=${this.interactiveClips}
|
|
5850
|
-
>
|
|
5851
|
-
<span>${clip.name || t.descriptor?.name || ""}</span>
|
|
5852
|
-
</div>` : ""}
|
|
5853
|
-
${t.descriptor?.renderMode === "piano-roll" ? import_lit14.html`<daw-piano-roll
|
|
5854
|
-
style="position:absolute;left:0;top:${hdrH}px;"
|
|
5855
|
-
.midiNotes=${clip.midiNotes ?? []}
|
|
5856
|
-
.length=${peakData?.length ?? width}
|
|
5857
|
-
.waveHeight=${chH * channels.length}
|
|
5858
|
-
.samplesPerPixel=${this._renderSpp}
|
|
5859
|
-
.sampleRate=${this.effectiveSampleRate}
|
|
5860
|
-
.clipOffsetSeconds=${(clip.offsetSamples ?? 0) / this.effectiveSampleRate}
|
|
5861
|
-
.visibleStart=${this._viewport.visibleStart}
|
|
5862
|
-
.visibleEnd=${this._viewport.visibleEnd}
|
|
5863
|
-
.originX=${clipLeft}
|
|
5864
|
-
?selected=${t.trackId === this._selectedTrackId}
|
|
5865
|
-
></daw-piano-roll>` : t.descriptor?.renderMode === "spectrogram" ? channels.map(
|
|
5866
|
-
(_chPeaks, chIdx) => import_lit14.html`<daw-spectrogram
|
|
5867
|
-
style="position:absolute;left:0;top:${hdrH + chIdx * chH}px;height:${chH}px;width:${peakData?.length ?? width}px;"
|
|
5868
|
-
.clipId=${clip.id}
|
|
5869
|
-
.trackId=${t.trackId}
|
|
5870
|
-
.channelIndex=${chIdx}
|
|
5871
|
-
.length=${peakData?.length ?? width}
|
|
5872
|
-
.waveHeight=${chH}
|
|
5873
|
-
.samplesPerPixel=${this._renderSpp}
|
|
5874
|
-
.sampleRate=${this.effectiveSampleRate}
|
|
5875
|
-
.clipOffsetSeconds=${(clip.offsetSamples ?? 0) / this.effectiveSampleRate}
|
|
5876
|
-
.visibleStart=${this._viewport.visibleStart}
|
|
5877
|
-
.visibleEnd=${this._viewport.visibleEnd}
|
|
5878
|
-
.originX=${clipLeft}
|
|
5879
|
-
></daw-spectrogram>`
|
|
5880
|
-
) : channels.map(
|
|
5881
|
-
(chPeaks, chIdx) => import_lit14.html` <daw-waveform
|
|
5882
|
-
style="position:absolute;left:0;top:${hdrH + chIdx * chH}px;"
|
|
5883
|
-
.peaks=${chPeaks}
|
|
5884
|
-
.length=${peakData?.length ?? width}
|
|
5885
|
-
.waveHeight=${chH}
|
|
5886
|
-
.barWidth=${this.barWidth}
|
|
5887
|
-
.barGap=${this.barGap}
|
|
5888
|
-
.visibleStart=${this._viewport.visibleStart}
|
|
5889
|
-
.visibleEnd=${this._viewport.visibleEnd}
|
|
5890
|
-
.originX=${clipLeft}
|
|
5891
|
-
.segments=${clipSegments}
|
|
5892
|
-
></daw-waveform>`
|
|
5893
|
-
)}
|
|
5894
|
-
${this.interactiveClips ? import_lit14.html` <div
|
|
5895
|
-
class="clip-boundary"
|
|
5896
|
-
data-boundary-edge="left"
|
|
6315
|
+
return import_lit15.html` <div
|
|
6316
|
+
class="clip-container"
|
|
6317
|
+
style="left:${clipLeft}px;top:0;width:${width}px;height:${t.trackHeight}px;"
|
|
6318
|
+
data-clip-id=${clip.id}
|
|
6319
|
+
>
|
|
6320
|
+
${hdrH > 0 ? import_lit15.html`<div
|
|
6321
|
+
class="clip-header"
|
|
5897
6322
|
data-clip-id=${clip.id}
|
|
5898
6323
|
data-track-id=${t.trackId}
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
6324
|
+
?data-interactive=${this.interactiveClips}
|
|
6325
|
+
>
|
|
6326
|
+
<span>${clip.name || t.descriptor?.name || ""}</span>
|
|
6327
|
+
</div>` : ""}
|
|
6328
|
+
${t.descriptor?.renderMode === "piano-roll" ? import_lit15.html`<daw-piano-roll
|
|
6329
|
+
style="position:absolute;left:0;top:${hdrH}px;"
|
|
6330
|
+
.midiNotes=${clip.midiNotes ?? []}
|
|
6331
|
+
.length=${peakData?.length ?? width}
|
|
6332
|
+
.waveHeight=${chH * channels.length}
|
|
6333
|
+
.samplesPerPixel=${this._renderSpp}
|
|
6334
|
+
.sampleRate=${this.effectiveSampleRate}
|
|
6335
|
+
.clipOffsetSeconds=${(clip.offsetSamples ?? 0) / this.effectiveSampleRate}
|
|
6336
|
+
.visibleStart=${this._viewport.visibleStart}
|
|
6337
|
+
.visibleEnd=${this._viewport.visibleEnd}
|
|
6338
|
+
.originX=${clipLeft}
|
|
6339
|
+
?selected=${t.trackId === this._selectedTrackId}
|
|
6340
|
+
></daw-piano-roll>` : t.descriptor?.renderMode === "spectrogram" ? channels.map(
|
|
6341
|
+
(_chPeaks, chIdx) => import_lit15.html`<daw-spectrogram
|
|
6342
|
+
style="position:absolute;left:0;top:${hdrH + chIdx * chH}px;height:${chH}px;width:${peakData?.length ?? width}px;"
|
|
6343
|
+
.clipId=${clip.id}
|
|
6344
|
+
.trackId=${t.trackId}
|
|
6345
|
+
.channelIndex=${chIdx}
|
|
6346
|
+
.length=${peakData?.length ?? width}
|
|
6347
|
+
.waveHeight=${chH}
|
|
6348
|
+
.samplesPerPixel=${this._renderSpp}
|
|
6349
|
+
.sampleRate=${this.effectiveSampleRate}
|
|
6350
|
+
.clipOffsetSeconds=${(clip.offsetSamples ?? 0) / this.effectiveSampleRate}
|
|
6351
|
+
.visibleStart=${this._viewport.visibleStart}
|
|
6352
|
+
.visibleEnd=${this._viewport.visibleEnd}
|
|
6353
|
+
.originX=${clipLeft}
|
|
6354
|
+
></daw-spectrogram>`
|
|
6355
|
+
) : channels.map(
|
|
6356
|
+
(chPeaks, chIdx) => import_lit15.html` <daw-waveform
|
|
6357
|
+
style="position:absolute;left:0;top:${hdrH + chIdx * chH}px;"
|
|
6358
|
+
.peaks=${chPeaks}
|
|
6359
|
+
.length=${peakData?.length ?? width}
|
|
6360
|
+
.waveHeight=${chH}
|
|
6361
|
+
.barWidth=${this.barWidth}
|
|
6362
|
+
.barGap=${this.barGap}
|
|
6363
|
+
.visibleStart=${this._viewport.visibleStart}
|
|
6364
|
+
.visibleEnd=${this._viewport.visibleEnd}
|
|
6365
|
+
.originX=${clipLeft}
|
|
6366
|
+
.segments=${clipSegments}
|
|
6367
|
+
></daw-waveform>`
|
|
6368
|
+
)}
|
|
6369
|
+
${this.interactiveClips ? import_lit15.html` <div
|
|
6370
|
+
class="clip-boundary"
|
|
6371
|
+
data-boundary-edge="left"
|
|
6372
|
+
data-clip-id=${clip.id}
|
|
6373
|
+
data-track-id=${t.trackId}
|
|
6374
|
+
></div>
|
|
6375
|
+
<div
|
|
6376
|
+
class="clip-boundary"
|
|
6377
|
+
data-boundary-edge="right"
|
|
6378
|
+
data-clip-id=${clip.id}
|
|
6379
|
+
data-track-id=${t.trackId}
|
|
6380
|
+
></div>` : ""}
|
|
6381
|
+
</div>`;
|
|
5907
6382
|
})}
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
6383
|
+
${this._renderRecordingPreview(t.trackId, channelHeight)}
|
|
6384
|
+
</div>
|
|
6385
|
+
`;
|
|
5911
6386
|
})}
|
|
6387
|
+
</div>
|
|
5912
6388
|
</div>
|
|
5913
6389
|
</div>
|
|
5914
6390
|
<slot></slot>
|
|
@@ -5917,21 +6393,48 @@ var DawEditorElement = class extends import_lit14.LitElement {
|
|
|
5917
6393
|
};
|
|
5918
6394
|
DawEditorElement.styles = [
|
|
5919
6395
|
hostStyles,
|
|
5920
|
-
|
|
6396
|
+
import_lit15.css`
|
|
5921
6397
|
:host {
|
|
5922
6398
|
display: flex;
|
|
6399
|
+
flex-direction: column;
|
|
5923
6400
|
position: relative;
|
|
5924
6401
|
background: var(--daw-background, #1a1a2e);
|
|
5925
6402
|
overflow: hidden;
|
|
5926
6403
|
}
|
|
5927
|
-
.
|
|
6404
|
+
.header-row {
|
|
6405
|
+
display: flex;
|
|
6406
|
+
flex-shrink: 0;
|
|
6407
|
+
}
|
|
6408
|
+
.ruler-gap {
|
|
6409
|
+
flex-shrink: 0;
|
|
6410
|
+
width: var(--daw-controls-width, 180px);
|
|
6411
|
+
}
|
|
6412
|
+
.ruler-viewport {
|
|
6413
|
+
flex: 1;
|
|
6414
|
+
position: relative;
|
|
6415
|
+
overflow: hidden;
|
|
6416
|
+
cursor: text;
|
|
6417
|
+
}
|
|
6418
|
+
.ruler-content {
|
|
6419
|
+
will-change: transform;
|
|
6420
|
+
}
|
|
6421
|
+
.body {
|
|
6422
|
+
flex: 1;
|
|
6423
|
+
min-height: 0;
|
|
6424
|
+
display: flex;
|
|
6425
|
+
}
|
|
6426
|
+
.controls-viewport {
|
|
5928
6427
|
flex-shrink: 0;
|
|
5929
6428
|
width: var(--daw-controls-width, 180px);
|
|
6429
|
+
overflow: hidden;
|
|
6430
|
+
}
|
|
6431
|
+
.controls-column {
|
|
6432
|
+
will-change: transform;
|
|
5930
6433
|
}
|
|
5931
6434
|
.scroll-area {
|
|
5932
6435
|
flex: 1;
|
|
5933
|
-
overflow
|
|
5934
|
-
overflow-
|
|
6436
|
+
overflow: auto;
|
|
6437
|
+
overflow-anchor: none;
|
|
5935
6438
|
min-height: var(--daw-min-height, 200px);
|
|
5936
6439
|
}
|
|
5937
6440
|
.timeline {
|
|
@@ -5941,6 +6444,7 @@ DawEditorElement.styles = [
|
|
|
5941
6444
|
}
|
|
5942
6445
|
.track-row {
|
|
5943
6446
|
position: relative;
|
|
6447
|
+
box-sizing: border-box;
|
|
5944
6448
|
background: var(--daw-track-background, #16213e);
|
|
5945
6449
|
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
|
5946
6450
|
}
|
|
@@ -5965,333 +6469,102 @@ DawEditorElement.styles = [
|
|
|
5965
6469
|
];
|
|
5966
6470
|
DawEditorElement._CONTROL_PROPS = /* @__PURE__ */ new Set(["volume", "pan", "muted", "soloed"]);
|
|
5967
6471
|
__decorateClass([
|
|
5968
|
-
(0,
|
|
6472
|
+
(0, import_decorators13.property)({ type: Number, attribute: "samples-per-pixel", noAccessor: true })
|
|
5969
6473
|
], DawEditorElement.prototype, "samplesPerPixel", 1);
|
|
5970
6474
|
__decorateClass([
|
|
5971
|
-
(0,
|
|
6475
|
+
(0, import_decorators13.property)({ type: Number, attribute: "wave-height" })
|
|
5972
6476
|
], DawEditorElement.prototype, "waveHeight", 2);
|
|
5973
6477
|
__decorateClass([
|
|
5974
|
-
(0,
|
|
6478
|
+
(0, import_decorators13.property)({ type: Boolean })
|
|
5975
6479
|
], DawEditorElement.prototype, "timescale", 2);
|
|
5976
6480
|
__decorateClass([
|
|
5977
|
-
(0,
|
|
6481
|
+
(0, import_decorators13.property)({ type: Boolean })
|
|
5978
6482
|
], DawEditorElement.prototype, "mono", 2);
|
|
5979
6483
|
__decorateClass([
|
|
5980
|
-
(0,
|
|
6484
|
+
(0, import_decorators13.property)({ type: Number, attribute: "bar-width" })
|
|
5981
6485
|
], DawEditorElement.prototype, "barWidth", 2);
|
|
5982
6486
|
__decorateClass([
|
|
5983
|
-
(0,
|
|
6487
|
+
(0, import_decorators13.property)({ type: Number, attribute: "bar-gap" })
|
|
5984
6488
|
], DawEditorElement.prototype, "barGap", 2);
|
|
5985
6489
|
__decorateClass([
|
|
5986
|
-
(0,
|
|
6490
|
+
(0, import_decorators13.property)({ type: Boolean, attribute: "file-drop" })
|
|
5987
6491
|
], DawEditorElement.prototype, "fileDrop", 2);
|
|
5988
6492
|
__decorateClass([
|
|
5989
|
-
(0,
|
|
6493
|
+
(0, import_decorators13.property)({ type: Boolean, attribute: "clip-headers" })
|
|
5990
6494
|
], DawEditorElement.prototype, "clipHeaders", 2);
|
|
5991
6495
|
__decorateClass([
|
|
5992
|
-
(0,
|
|
6496
|
+
(0, import_decorators13.property)({ type: Number, attribute: "clip-header-height" })
|
|
5993
6497
|
], DawEditorElement.prototype, "clipHeaderHeight", 2);
|
|
5994
6498
|
__decorateClass([
|
|
5995
|
-
(0,
|
|
6499
|
+
(0, import_decorators13.property)({ type: Boolean, attribute: "interactive-clips" })
|
|
5996
6500
|
], DawEditorElement.prototype, "interactiveClips", 2);
|
|
5997
6501
|
__decorateClass([
|
|
5998
|
-
(0,
|
|
6502
|
+
(0, import_decorators13.property)({ type: Boolean, attribute: "indefinite-playback" })
|
|
5999
6503
|
], DawEditorElement.prototype, "indefinitePlayback", 2);
|
|
6000
6504
|
__decorateClass([
|
|
6001
|
-
(0,
|
|
6505
|
+
(0, import_decorators13.property)({ attribute: false, noAccessor: true })
|
|
6002
6506
|
], DawEditorElement.prototype, "spectrogramConfig", 1);
|
|
6003
6507
|
__decorateClass([
|
|
6004
|
-
(0,
|
|
6508
|
+
(0, import_decorators13.property)({ attribute: false, noAccessor: true })
|
|
6005
6509
|
], DawEditorElement.prototype, "spectrogramColorMap", 1);
|
|
6006
6510
|
__decorateClass([
|
|
6007
|
-
(0,
|
|
6511
|
+
(0, import_decorators13.property)({ type: String, attribute: "scale-mode" })
|
|
6008
6512
|
], DawEditorElement.prototype, "scaleMode", 2);
|
|
6009
6513
|
__decorateClass([
|
|
6010
|
-
(0,
|
|
6514
|
+
(0, import_decorators13.property)({ type: Number, attribute: "ticks-per-pixel", noAccessor: true })
|
|
6011
6515
|
], DawEditorElement.prototype, "ticksPerPixel", 1);
|
|
6012
6516
|
__decorateClass([
|
|
6013
|
-
(0,
|
|
6517
|
+
(0, import_decorators13.property)({ type: Number, noAccessor: true })
|
|
6014
6518
|
], DawEditorElement.prototype, "bpm", 1);
|
|
6015
6519
|
__decorateClass([
|
|
6016
|
-
(0,
|
|
6520
|
+
(0, import_decorators13.property)({ attribute: false })
|
|
6017
6521
|
], DawEditorElement.prototype, "timeSignature", 2);
|
|
6018
6522
|
__decorateClass([
|
|
6019
|
-
(0,
|
|
6523
|
+
(0, import_decorators13.property)({ attribute: false })
|
|
6020
6524
|
], DawEditorElement.prototype, "meterEntries", 2);
|
|
6021
6525
|
__decorateClass([
|
|
6022
|
-
(0,
|
|
6526
|
+
(0, import_decorators13.property)({ type: Number, noAccessor: true })
|
|
6023
6527
|
], DawEditorElement.prototype, "ppqn", 1);
|
|
6024
6528
|
__decorateClass([
|
|
6025
|
-
(0,
|
|
6529
|
+
(0, import_decorators13.property)({ type: String, attribute: "snap-to" })
|
|
6026
6530
|
], DawEditorElement.prototype, "snapTo", 2);
|
|
6027
6531
|
__decorateClass([
|
|
6028
|
-
(0,
|
|
6532
|
+
(0, import_decorators13.property)({ attribute: false })
|
|
6029
6533
|
], DawEditorElement.prototype, "secondsToTicks", 2);
|
|
6030
6534
|
__decorateClass([
|
|
6031
|
-
(0,
|
|
6535
|
+
(0, import_decorators13.property)({ attribute: false })
|
|
6032
6536
|
], DawEditorElement.prototype, "ticksToSeconds", 2);
|
|
6033
6537
|
__decorateClass([
|
|
6034
|
-
(0,
|
|
6538
|
+
(0, import_decorators13.state)()
|
|
6035
6539
|
], DawEditorElement.prototype, "_tracks", 2);
|
|
6036
6540
|
__decorateClass([
|
|
6037
|
-
(0,
|
|
6541
|
+
(0, import_decorators13.state)()
|
|
6038
6542
|
], DawEditorElement.prototype, "_engineTracks", 2);
|
|
6039
6543
|
__decorateClass([
|
|
6040
|
-
(0,
|
|
6544
|
+
(0, import_decorators13.state)()
|
|
6041
6545
|
], DawEditorElement.prototype, "_peaksData", 2);
|
|
6042
6546
|
__decorateClass([
|
|
6043
|
-
(0,
|
|
6547
|
+
(0, import_decorators13.state)()
|
|
6044
6548
|
], DawEditorElement.prototype, "_isPlaying", 2);
|
|
6045
6549
|
__decorateClass([
|
|
6046
|
-
(0,
|
|
6550
|
+
(0, import_decorators13.state)()
|
|
6047
6551
|
], DawEditorElement.prototype, "_duration", 2);
|
|
6048
6552
|
__decorateClass([
|
|
6049
|
-
(0,
|
|
6553
|
+
(0, import_decorators13.state)()
|
|
6050
6554
|
], DawEditorElement.prototype, "_selectedTrackId", 2);
|
|
6051
6555
|
__decorateClass([
|
|
6052
|
-
(0,
|
|
6556
|
+
(0, import_decorators13.state)()
|
|
6053
6557
|
], DawEditorElement.prototype, "_dragOver", 2);
|
|
6054
6558
|
__decorateClass([
|
|
6055
|
-
(0,
|
|
6559
|
+
(0, import_decorators13.property)({ attribute: false })
|
|
6056
6560
|
], DawEditorElement.prototype, "adapter", 1);
|
|
6057
6561
|
__decorateClass([
|
|
6058
|
-
(0,
|
|
6562
|
+
(0, import_decorators13.property)({ attribute: "eager-resume" })
|
|
6059
6563
|
], DawEditorElement.prototype, "eagerResume", 2);
|
|
6060
6564
|
DawEditorElement = __decorateClass([
|
|
6061
|
-
(0,
|
|
6565
|
+
(0, import_decorators13.customElement)("daw-editor")
|
|
6062
6566
|
], DawEditorElement);
|
|
6063
6567
|
|
|
6064
|
-
// src/elements/daw-ruler.ts
|
|
6065
|
-
var import_lit15 = require("lit");
|
|
6066
|
-
var import_decorators13 = require("lit/decorators.js");
|
|
6067
|
-
|
|
6068
|
-
// src/utils/time-format.ts
|
|
6069
|
-
function formatTime(milliseconds) {
|
|
6070
|
-
const seconds = Math.floor(milliseconds / 1e3);
|
|
6071
|
-
const s = seconds % 60;
|
|
6072
|
-
const m = (seconds - s) / 60;
|
|
6073
|
-
return `${m}:${String(s).padStart(2, "0")}`;
|
|
6074
|
-
}
|
|
6075
|
-
|
|
6076
|
-
// src/utils/smart-scale.ts
|
|
6077
|
-
var timeinfo = /* @__PURE__ */ new Map([
|
|
6078
|
-
[700, { marker: 1e3, bigStep: 500, smallStep: 100 }],
|
|
6079
|
-
[1500, { marker: 2e3, bigStep: 1e3, smallStep: 200 }],
|
|
6080
|
-
[2500, { marker: 2e3, bigStep: 1e3, smallStep: 500 }],
|
|
6081
|
-
[5e3, { marker: 5e3, bigStep: 1e3, smallStep: 500 }],
|
|
6082
|
-
[1e4, { marker: 1e4, bigStep: 5e3, smallStep: 1e3 }],
|
|
6083
|
-
[12e3, { marker: 15e3, bigStep: 5e3, smallStep: 1e3 }],
|
|
6084
|
-
[Infinity, { marker: 3e4, bigStep: 1e4, smallStep: 5e3 }]
|
|
6085
|
-
]);
|
|
6086
|
-
function getScaleInfo(samplesPerPixel) {
|
|
6087
|
-
for (const [resolution, config] of timeinfo) {
|
|
6088
|
-
if (samplesPerPixel < resolution) {
|
|
6089
|
-
return config;
|
|
6090
|
-
}
|
|
6091
|
-
}
|
|
6092
|
-
return { marker: 3e4, bigStep: 1e4, smallStep: 5e3 };
|
|
6093
|
-
}
|
|
6094
|
-
function computeTemporalTicks(samplesPerPixel, sampleRate, duration, rulerHeight) {
|
|
6095
|
-
const widthX = Math.ceil(duration * sampleRate / samplesPerPixel);
|
|
6096
|
-
const config = getScaleInfo(samplesPerPixel);
|
|
6097
|
-
const { marker, bigStep, smallStep } = config;
|
|
6098
|
-
const canvasInfo = /* @__PURE__ */ new Map();
|
|
6099
|
-
const labels = [];
|
|
6100
|
-
const pixPerSec = sampleRate / samplesPerPixel;
|
|
6101
|
-
for (let counter = 0; ; counter += smallStep) {
|
|
6102
|
-
const pix = Math.floor(counter / 1e3 * pixPerSec);
|
|
6103
|
-
if (pix >= widthX) break;
|
|
6104
|
-
if (counter % marker === 0) {
|
|
6105
|
-
canvasInfo.set(pix, rulerHeight);
|
|
6106
|
-
labels.push({ pix, text: formatTime(counter) });
|
|
6107
|
-
} else if (counter % bigStep === 0) {
|
|
6108
|
-
canvasInfo.set(pix, Math.floor(rulerHeight / 2));
|
|
6109
|
-
} else if (counter % smallStep === 0) {
|
|
6110
|
-
canvasInfo.set(pix, Math.floor(rulerHeight / 5));
|
|
6111
|
-
}
|
|
6112
|
-
}
|
|
6113
|
-
return { widthX, canvasInfo, labels };
|
|
6114
|
-
}
|
|
6115
|
-
|
|
6116
|
-
// src/elements/daw-ruler.ts
|
|
6117
|
-
var MAX_CANVAS_WIDTH4 = 1e3;
|
|
6118
|
-
var DawRulerElement = class extends import_lit15.LitElement {
|
|
6119
|
-
constructor() {
|
|
6120
|
-
super(...arguments);
|
|
6121
|
-
this.samplesPerPixel = 1024;
|
|
6122
|
-
this.sampleRate = 48e3;
|
|
6123
|
-
this.duration = 0;
|
|
6124
|
-
this.rulerHeight = 30;
|
|
6125
|
-
this.scaleMode = "temporal";
|
|
6126
|
-
this.ticksPerPixel = 4;
|
|
6127
|
-
this.meterEntries = [
|
|
6128
|
-
{ tick: 0, numerator: 4, denominator: 4 }
|
|
6129
|
-
];
|
|
6130
|
-
this.ppqn = 960;
|
|
6131
|
-
this.totalWidth = 0;
|
|
6132
|
-
this._tickData = null;
|
|
6133
|
-
this._musicalTickData = null;
|
|
6134
|
-
}
|
|
6135
|
-
willUpdate() {
|
|
6136
|
-
if (this.scaleMode === "beats" && this.totalWidth > 0) {
|
|
6137
|
-
this._musicalTickData = getCachedMusicalTicks({
|
|
6138
|
-
meterEntries: this.meterEntries,
|
|
6139
|
-
ticksPerPixel: this.ticksPerPixel,
|
|
6140
|
-
startPixel: 0,
|
|
6141
|
-
endPixel: this.totalWidth,
|
|
6142
|
-
ppqn: this.ppqn
|
|
6143
|
-
});
|
|
6144
|
-
this._tickData = null;
|
|
6145
|
-
} else if (this.duration > 0 || this.totalWidth > 0) {
|
|
6146
|
-
const widthDerivedDuration = this.totalWidth * this.samplesPerPixel / this.sampleRate;
|
|
6147
|
-
const effectiveDuration = Math.max(this.duration, widthDerivedDuration);
|
|
6148
|
-
this._musicalTickData = null;
|
|
6149
|
-
this._tickData = computeTemporalTicks(
|
|
6150
|
-
this.samplesPerPixel,
|
|
6151
|
-
this.sampleRate,
|
|
6152
|
-
effectiveDuration,
|
|
6153
|
-
this.rulerHeight
|
|
6154
|
-
);
|
|
6155
|
-
} else {
|
|
6156
|
-
this._musicalTickData = null;
|
|
6157
|
-
this._tickData = null;
|
|
6158
|
-
}
|
|
6159
|
-
}
|
|
6160
|
-
render() {
|
|
6161
|
-
const widthX = this.scaleMode === "beats" ? this.totalWidth : this._tickData?.widthX ?? 0;
|
|
6162
|
-
if (widthX <= 0) return import_lit15.html``;
|
|
6163
|
-
const totalChunks = Math.ceil(widthX / MAX_CANVAS_WIDTH4);
|
|
6164
|
-
const indices = Array.from({ length: totalChunks }, (_, i) => i);
|
|
6165
|
-
const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
|
|
6166
|
-
const beatsLabels = this.scaleMode === "beats" ? this._musicalTickData?.ticks.filter((t) => t.label) ?? [] : [];
|
|
6167
|
-
const temporalLabels = this.scaleMode !== "beats" ? this._tickData?.labels ?? [] : [];
|
|
6168
|
-
return import_lit15.html`
|
|
6169
|
-
<div class="container" style="width: ${widthX}px; height: ${this.rulerHeight}px;">
|
|
6170
|
-
${indices.map((i) => {
|
|
6171
|
-
const width = Math.min(MAX_CANVAS_WIDTH4, widthX - i * MAX_CANVAS_WIDTH4);
|
|
6172
|
-
return import_lit15.html`
|
|
6173
|
-
<canvas
|
|
6174
|
-
data-index=${i}
|
|
6175
|
-
width=${width * dpr}
|
|
6176
|
-
height=${this.rulerHeight * dpr}
|
|
6177
|
-
style="left: ${i * MAX_CANVAS_WIDTH4}px; width: ${width}px; height: ${this.rulerHeight}px;"
|
|
6178
|
-
></canvas>
|
|
6179
|
-
`;
|
|
6180
|
-
})}
|
|
6181
|
-
${this.scaleMode === "beats" ? beatsLabels.map(
|
|
6182
|
-
(t) => import_lit15.html`<span
|
|
6183
|
-
class="label ${t.pixel > 0 ? "centered" : ""}"
|
|
6184
|
-
style="left: ${t.pixel > 0 ? t.pixel : t.pixel + 4}px;"
|
|
6185
|
-
>${t.label}</span
|
|
6186
|
-
>`
|
|
6187
|
-
) : temporalLabels.map(
|
|
6188
|
-
({ pix, text }) => import_lit15.html`<span class="label" style="left: ${pix + 4}px;">${text}</span>`
|
|
6189
|
-
)}
|
|
6190
|
-
</div>
|
|
6191
|
-
`;
|
|
6192
|
-
}
|
|
6193
|
-
updated() {
|
|
6194
|
-
this._drawTicks();
|
|
6195
|
-
}
|
|
6196
|
-
_drawTicks() {
|
|
6197
|
-
const canvases = this.shadowRoot?.querySelectorAll("canvas");
|
|
6198
|
-
if (!canvases) return;
|
|
6199
|
-
const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
|
|
6200
|
-
const rulerColor = getComputedStyle(this).getPropertyValue("--daw-ruler-color").trim() || "#c49a6c";
|
|
6201
|
-
const widthX = this.scaleMode === "beats" ? this.totalWidth : this._tickData?.widthX ?? 0;
|
|
6202
|
-
for (const canvas of canvases) {
|
|
6203
|
-
const idx = Number(canvas.dataset.index);
|
|
6204
|
-
const ctx = canvas.getContext("2d");
|
|
6205
|
-
if (!ctx) continue;
|
|
6206
|
-
const canvasWidth = Math.min(MAX_CANVAS_WIDTH4, widthX - idx * MAX_CANVAS_WIDTH4);
|
|
6207
|
-
const globalOffset = idx * MAX_CANVAS_WIDTH4;
|
|
6208
|
-
ctx.resetTransform();
|
|
6209
|
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
6210
|
-
ctx.scale(dpr, dpr);
|
|
6211
|
-
ctx.strokeStyle = rulerColor;
|
|
6212
|
-
ctx.lineWidth = 1;
|
|
6213
|
-
if (this.scaleMode === "beats" && this._musicalTickData) {
|
|
6214
|
-
const h = this.rulerHeight;
|
|
6215
|
-
for (const tick of this._musicalTickData.ticks) {
|
|
6216
|
-
const localX = tick.pixel - globalOffset;
|
|
6217
|
-
if (localX < 0 || localX >= canvasWidth) continue;
|
|
6218
|
-
const tickH = tick.type === "major" ? h * 0.6 : tick.type === "minor" ? h * 0.35 : h * 0.15;
|
|
6219
|
-
ctx.globalAlpha = tick.type === "major" ? 1 : 0.5;
|
|
6220
|
-
ctx.beginPath();
|
|
6221
|
-
ctx.moveTo(localX + 0.5, h);
|
|
6222
|
-
ctx.lineTo(localX + 0.5, h - tickH);
|
|
6223
|
-
ctx.stroke();
|
|
6224
|
-
}
|
|
6225
|
-
ctx.globalAlpha = 1;
|
|
6226
|
-
} else if (this._tickData) {
|
|
6227
|
-
for (const [pix, height] of this._tickData.canvasInfo) {
|
|
6228
|
-
const localX = pix - globalOffset;
|
|
6229
|
-
if (localX < 0 || localX >= canvasWidth) continue;
|
|
6230
|
-
ctx.beginPath();
|
|
6231
|
-
ctx.moveTo(localX + 0.5, this.rulerHeight);
|
|
6232
|
-
ctx.lineTo(localX + 0.5, this.rulerHeight - height);
|
|
6233
|
-
ctx.stroke();
|
|
6234
|
-
}
|
|
6235
|
-
}
|
|
6236
|
-
}
|
|
6237
|
-
}
|
|
6238
|
-
};
|
|
6239
|
-
DawRulerElement.styles = import_lit15.css`
|
|
6240
|
-
:host {
|
|
6241
|
-
display: block;
|
|
6242
|
-
position: relative;
|
|
6243
|
-
background: var(--daw-ruler-background, #0f0f1a);
|
|
6244
|
-
}
|
|
6245
|
-
.container {
|
|
6246
|
-
position: relative;
|
|
6247
|
-
}
|
|
6248
|
-
canvas {
|
|
6249
|
-
position: absolute;
|
|
6250
|
-
top: 0;
|
|
6251
|
-
}
|
|
6252
|
-
.label {
|
|
6253
|
-
position: absolute;
|
|
6254
|
-
font-size: 0.7rem;
|
|
6255
|
-
line-height: 1;
|
|
6256
|
-
white-space: nowrap;
|
|
6257
|
-
color: var(--daw-ruler-color, #c49a6c);
|
|
6258
|
-
top: 1px;
|
|
6259
|
-
}
|
|
6260
|
-
.label.centered {
|
|
6261
|
-
transform: translateX(-50%);
|
|
6262
|
-
}
|
|
6263
|
-
`;
|
|
6264
|
-
__decorateClass([
|
|
6265
|
-
(0, import_decorators13.property)({ type: Number, attribute: false })
|
|
6266
|
-
], DawRulerElement.prototype, "samplesPerPixel", 2);
|
|
6267
|
-
__decorateClass([
|
|
6268
|
-
(0, import_decorators13.property)({ type: Number, attribute: false })
|
|
6269
|
-
], DawRulerElement.prototype, "sampleRate", 2);
|
|
6270
|
-
__decorateClass([
|
|
6271
|
-
(0, import_decorators13.property)({ type: Number, attribute: false })
|
|
6272
|
-
], DawRulerElement.prototype, "duration", 2);
|
|
6273
|
-
__decorateClass([
|
|
6274
|
-
(0, import_decorators13.property)({ type: Number, attribute: false })
|
|
6275
|
-
], DawRulerElement.prototype, "rulerHeight", 2);
|
|
6276
|
-
__decorateClass([
|
|
6277
|
-
(0, import_decorators13.property)({ type: String, attribute: false })
|
|
6278
|
-
], DawRulerElement.prototype, "scaleMode", 2);
|
|
6279
|
-
__decorateClass([
|
|
6280
|
-
(0, import_decorators13.property)({ type: Number, attribute: false })
|
|
6281
|
-
], DawRulerElement.prototype, "ticksPerPixel", 2);
|
|
6282
|
-
__decorateClass([
|
|
6283
|
-
(0, import_decorators13.property)({ attribute: false })
|
|
6284
|
-
], DawRulerElement.prototype, "meterEntries", 2);
|
|
6285
|
-
__decorateClass([
|
|
6286
|
-
(0, import_decorators13.property)({ type: Number, attribute: false })
|
|
6287
|
-
], DawRulerElement.prototype, "ppqn", 2);
|
|
6288
|
-
__decorateClass([
|
|
6289
|
-
(0, import_decorators13.property)({ type: Number, attribute: false })
|
|
6290
|
-
], DawRulerElement.prototype, "totalWidth", 2);
|
|
6291
|
-
DawRulerElement = __decorateClass([
|
|
6292
|
-
(0, import_decorators13.customElement)("daw-ruler")
|
|
6293
|
-
], DawRulerElement);
|
|
6294
|
-
|
|
6295
6568
|
// src/elements/daw-selection.ts
|
|
6296
6569
|
var import_lit16 = require("lit");
|
|
6297
6570
|
var import_decorators14 = require("lit/decorators.js");
|
|
@@ -6415,7 +6688,7 @@ DawRecordButtonElement = __decorateClass([
|
|
|
6415
6688
|
// src/elements/daw-keyboard-shortcuts.ts
|
|
6416
6689
|
var import_lit18 = require("lit");
|
|
6417
6690
|
var import_decorators16 = require("lit/decorators.js");
|
|
6418
|
-
var
|
|
6691
|
+
var import_core10 = require("@waveform-playlist/core");
|
|
6419
6692
|
var DawKeyboardShortcutsElement = class extends import_lit18.LitElement {
|
|
6420
6693
|
constructor() {
|
|
6421
6694
|
super(...arguments);
|
|
@@ -6435,7 +6708,7 @@ var DawKeyboardShortcutsElement = class extends import_lit18.LitElement {
|
|
|
6435
6708
|
const shortcuts = this.shortcuts;
|
|
6436
6709
|
if (shortcuts.length === 0) return;
|
|
6437
6710
|
try {
|
|
6438
|
-
(0,
|
|
6711
|
+
(0, import_core10.handleKeyboardEvent)(e, shortcuts, true);
|
|
6439
6712
|
} catch (err) {
|
|
6440
6713
|
console.warn("[dawcore] Keyboard shortcut failed (key=" + e.key + "): " + String(err));
|
|
6441
6714
|
const target = this._editor ?? this;
|
|
@@ -6602,6 +6875,7 @@ var DawSpectrogramElement = class extends import_lit19.LitElement {
|
|
|
6602
6875
|
this.originX = 0;
|
|
6603
6876
|
this._canvases = [];
|
|
6604
6877
|
this._registeredCanvasIds = [];
|
|
6878
|
+
this._warnedNoHost = false;
|
|
6605
6879
|
}
|
|
6606
6880
|
get samplesPerPixel() {
|
|
6607
6881
|
return this._samplesPerPixel;
|
|
@@ -6668,7 +6942,15 @@ var DawSpectrogramElement = class extends import_lit19.LitElement {
|
|
|
6668
6942
|
}
|
|
6669
6943
|
_registerCanvases() {
|
|
6670
6944
|
const editor = this._findHostEditor();
|
|
6671
|
-
if (!editor || typeof editor._spectrogramRegisterCanvas !== "function")
|
|
6945
|
+
if (!editor || typeof editor._spectrogramRegisterCanvas !== "function") {
|
|
6946
|
+
if (!this._warnedNoHost) {
|
|
6947
|
+
this._warnedNoHost = true;
|
|
6948
|
+
console.warn(
|
|
6949
|
+
"[dawcore] <daw-spectrogram> (clip " + this.clipId + ") could not find host <daw-editor>. Canvases will not render. Ensure the element is mounted inside a <daw-editor>."
|
|
6950
|
+
);
|
|
6951
|
+
}
|
|
6952
|
+
return;
|
|
6953
|
+
}
|
|
6672
6954
|
for (let i = 0; i < this._canvases.length; i++) {
|
|
6673
6955
|
const canvas = this._canvases[i];
|
|
6674
6956
|
const canvasId = this.clipId + "-ch" + this.channelIndex + "-chunk" + i;
|