@dawcore/components 0.0.20 → 0.0.22
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 +30 -24
- package/dist/index.d.ts +30 -24
- package/dist/index.js +713 -480
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +701 -468
- package/dist/index.mjs.map +1 -1
- package/package.json +23 -14
package/dist/index.mjs
CHANGED
|
@@ -1196,8 +1196,8 @@ DawStopButtonElement = __decorateClass([
|
|
|
1196
1196
|
], DawStopButtonElement);
|
|
1197
1197
|
|
|
1198
1198
|
// src/elements/daw-editor.ts
|
|
1199
|
-
import { LitElement as
|
|
1200
|
-
import { customElement as
|
|
1199
|
+
import { LitElement as LitElement11, html as html10, css as css10 } from "lit";
|
|
1200
|
+
import { customElement as customElement13, property as property9, state as state3 } from "lit/decorators.js";
|
|
1201
1201
|
|
|
1202
1202
|
// src/types.ts
|
|
1203
1203
|
function isDomClip(desc) {
|
|
@@ -1681,10 +1681,268 @@ var PeakPipeline = class {
|
|
|
1681
1681
|
}
|
|
1682
1682
|
};
|
|
1683
1683
|
|
|
1684
|
-
// src/elements/daw-
|
|
1684
|
+
// src/elements/daw-ruler.ts
|
|
1685
1685
|
import { LitElement as LitElement8, html as html7, css as css6 } from "lit";
|
|
1686
1686
|
import { customElement as customElement10, property as property6 } from "lit/decorators.js";
|
|
1687
|
-
|
|
1687
|
+
|
|
1688
|
+
// src/utils/time-format.ts
|
|
1689
|
+
function formatTime(milliseconds) {
|
|
1690
|
+
const seconds = Math.floor(milliseconds / 1e3);
|
|
1691
|
+
const s = seconds % 60;
|
|
1692
|
+
const m = (seconds - s) / 60;
|
|
1693
|
+
return `${m}:${String(s).padStart(2, "0")}`;
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
// src/utils/smart-scale.ts
|
|
1697
|
+
var timeinfo = /* @__PURE__ */ new Map([
|
|
1698
|
+
[700, { marker: 1e3, bigStep: 500, smallStep: 100 }],
|
|
1699
|
+
[1500, { marker: 2e3, bigStep: 1e3, smallStep: 200 }],
|
|
1700
|
+
[2500, { marker: 2e3, bigStep: 1e3, smallStep: 500 }],
|
|
1701
|
+
[5e3, { marker: 5e3, bigStep: 1e3, smallStep: 500 }],
|
|
1702
|
+
[1e4, { marker: 1e4, bigStep: 5e3, smallStep: 1e3 }],
|
|
1703
|
+
[12e3, { marker: 15e3, bigStep: 5e3, smallStep: 1e3 }],
|
|
1704
|
+
[Infinity, { marker: 3e4, bigStep: 1e4, smallStep: 5e3 }]
|
|
1705
|
+
]);
|
|
1706
|
+
function getScaleInfo(samplesPerPixel) {
|
|
1707
|
+
for (const [resolution, config] of timeinfo) {
|
|
1708
|
+
if (samplesPerPixel < resolution) {
|
|
1709
|
+
return config;
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
return { marker: 3e4, bigStep: 1e4, smallStep: 5e3 };
|
|
1713
|
+
}
|
|
1714
|
+
function computeTemporalTicks(samplesPerPixel, sampleRate, duration, rulerHeight) {
|
|
1715
|
+
const widthX = Math.ceil(duration * sampleRate / samplesPerPixel);
|
|
1716
|
+
const config = getScaleInfo(samplesPerPixel);
|
|
1717
|
+
const { marker, bigStep, smallStep } = config;
|
|
1718
|
+
const canvasInfo = /* @__PURE__ */ new Map();
|
|
1719
|
+
const labels = [];
|
|
1720
|
+
const pixPerSec = sampleRate / samplesPerPixel;
|
|
1721
|
+
for (let counter = 0; ; counter += smallStep) {
|
|
1722
|
+
const pix = Math.floor(counter / 1e3 * pixPerSec);
|
|
1723
|
+
if (pix >= widthX) break;
|
|
1724
|
+
if (counter % marker === 0) {
|
|
1725
|
+
canvasInfo.set(pix, rulerHeight);
|
|
1726
|
+
labels.push({ pix, text: formatTime(counter) });
|
|
1727
|
+
} else if (counter % bigStep === 0) {
|
|
1728
|
+
canvasInfo.set(pix, Math.floor(rulerHeight / 2));
|
|
1729
|
+
} else if (counter % smallStep === 0) {
|
|
1730
|
+
canvasInfo.set(pix, Math.floor(rulerHeight / 5));
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
return { widthX, canvasInfo, labels };
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
// src/utils/musical-tick-cache.ts
|
|
1737
|
+
import { computeMusicalTicks } from "@waveform-playlist/core";
|
|
1738
|
+
var cachedParams = null;
|
|
1739
|
+
var cachedResult = null;
|
|
1740
|
+
function meterEntriesMatch(a, b) {
|
|
1741
|
+
if (a.length !== b.length) return false;
|
|
1742
|
+
for (let i = 0; i < a.length; i++) {
|
|
1743
|
+
if (a[i].tick !== b[i].tick || a[i].numerator !== b[i].numerator || a[i].denominator !== b[i].denominator)
|
|
1744
|
+
return false;
|
|
1745
|
+
}
|
|
1746
|
+
return true;
|
|
1747
|
+
}
|
|
1748
|
+
function paramsMatch(a, b) {
|
|
1749
|
+
return a.ticksPerPixel === b.ticksPerPixel && a.startPixel === b.startPixel && a.endPixel === b.endPixel && meterEntriesMatch(a.meterEntries, b.meterEntries) && (a.ppqn ?? 960) === (b.ppqn ?? 960);
|
|
1750
|
+
}
|
|
1751
|
+
function getCachedMusicalTicks(params) {
|
|
1752
|
+
if (cachedParams && cachedResult && paramsMatch(cachedParams, params)) {
|
|
1753
|
+
return cachedResult;
|
|
1754
|
+
}
|
|
1755
|
+
cachedResult = computeMusicalTicks(params);
|
|
1756
|
+
cachedParams = {
|
|
1757
|
+
...params,
|
|
1758
|
+
meterEntries: params.meterEntries.map((e) => ({ ...e }))
|
|
1759
|
+
};
|
|
1760
|
+
return cachedResult;
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
// src/elements/daw-ruler.ts
|
|
1764
|
+
var MAX_CANVAS_WIDTH3 = 1e3;
|
|
1765
|
+
var DawRulerElement = class extends LitElement8 {
|
|
1766
|
+
constructor() {
|
|
1767
|
+
super(...arguments);
|
|
1768
|
+
this.samplesPerPixel = 1024;
|
|
1769
|
+
this.sampleRate = 48e3;
|
|
1770
|
+
this.duration = 0;
|
|
1771
|
+
this.rulerHeight = 30;
|
|
1772
|
+
this.scaleMode = "temporal";
|
|
1773
|
+
this.ticksPerPixel = 4;
|
|
1774
|
+
this.meterEntries = [
|
|
1775
|
+
{ tick: 0, numerator: 4, denominator: 4 }
|
|
1776
|
+
];
|
|
1777
|
+
this.ppqn = 960;
|
|
1778
|
+
this.totalWidth = 0;
|
|
1779
|
+
this._tickData = null;
|
|
1780
|
+
this._musicalTickData = null;
|
|
1781
|
+
}
|
|
1782
|
+
willUpdate() {
|
|
1783
|
+
if (this.scaleMode === "beats" && this.totalWidth > 0) {
|
|
1784
|
+
this._musicalTickData = getCachedMusicalTicks({
|
|
1785
|
+
meterEntries: this.meterEntries,
|
|
1786
|
+
ticksPerPixel: this.ticksPerPixel,
|
|
1787
|
+
startPixel: 0,
|
|
1788
|
+
endPixel: this.totalWidth,
|
|
1789
|
+
ppqn: this.ppqn
|
|
1790
|
+
});
|
|
1791
|
+
this._tickData = null;
|
|
1792
|
+
} else if (this.duration > 0 || this.totalWidth > 0) {
|
|
1793
|
+
const widthDerivedDuration = this.totalWidth * this.samplesPerPixel / this.sampleRate;
|
|
1794
|
+
const effectiveDuration = Math.max(this.duration, widthDerivedDuration);
|
|
1795
|
+
this._musicalTickData = null;
|
|
1796
|
+
this._tickData = computeTemporalTicks(
|
|
1797
|
+
this.samplesPerPixel,
|
|
1798
|
+
this.sampleRate,
|
|
1799
|
+
effectiveDuration,
|
|
1800
|
+
this.rulerHeight
|
|
1801
|
+
);
|
|
1802
|
+
} else {
|
|
1803
|
+
this._musicalTickData = null;
|
|
1804
|
+
this._tickData = null;
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
render() {
|
|
1808
|
+
const widthX = this.scaleMode === "beats" ? this.totalWidth : this._tickData?.widthX ?? 0;
|
|
1809
|
+
if (widthX <= 0) return html7``;
|
|
1810
|
+
const totalChunks = Math.ceil(widthX / MAX_CANVAS_WIDTH3);
|
|
1811
|
+
const indices = Array.from({ length: totalChunks }, (_, i) => i);
|
|
1812
|
+
const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
|
|
1813
|
+
const beatsLabels = this.scaleMode === "beats" ? this._musicalTickData?.ticks.filter((t) => t.label) ?? [] : [];
|
|
1814
|
+
const temporalLabels = this.scaleMode !== "beats" ? this._tickData?.labels ?? [] : [];
|
|
1815
|
+
return html7`
|
|
1816
|
+
<div class="container" style="width: ${widthX}px; height: ${this.rulerHeight}px;">
|
|
1817
|
+
${indices.map((i) => {
|
|
1818
|
+
const width = Math.min(MAX_CANVAS_WIDTH3, widthX - i * MAX_CANVAS_WIDTH3);
|
|
1819
|
+
return html7`
|
|
1820
|
+
<canvas
|
|
1821
|
+
data-index=${i}
|
|
1822
|
+
width=${width * dpr}
|
|
1823
|
+
height=${this.rulerHeight * dpr}
|
|
1824
|
+
style="left: ${i * MAX_CANVAS_WIDTH3}px; width: ${width}px; height: ${this.rulerHeight}px;"
|
|
1825
|
+
></canvas>
|
|
1826
|
+
`;
|
|
1827
|
+
})}
|
|
1828
|
+
${this.scaleMode === "beats" ? beatsLabels.map(
|
|
1829
|
+
(t) => html7`<span
|
|
1830
|
+
class="label ${t.pixel > 0 ? "centered" : ""}"
|
|
1831
|
+
style="left: ${t.pixel > 0 ? t.pixel : t.pixel + 4}px;"
|
|
1832
|
+
>${t.label}</span
|
|
1833
|
+
>`
|
|
1834
|
+
) : temporalLabels.map(
|
|
1835
|
+
({ pix, text }) => html7`<span class="label" style="left: ${pix + 4}px;">${text}</span>`
|
|
1836
|
+
)}
|
|
1837
|
+
</div>
|
|
1838
|
+
`;
|
|
1839
|
+
}
|
|
1840
|
+
updated() {
|
|
1841
|
+
this._drawTicks();
|
|
1842
|
+
}
|
|
1843
|
+
_drawTicks() {
|
|
1844
|
+
const canvases = this.shadowRoot?.querySelectorAll("canvas");
|
|
1845
|
+
if (!canvases) return;
|
|
1846
|
+
const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
|
|
1847
|
+
const rulerColor = getComputedStyle(this).getPropertyValue("--daw-ruler-color").trim() || "#c49a6c";
|
|
1848
|
+
const widthX = this.scaleMode === "beats" ? this.totalWidth : this._tickData?.widthX ?? 0;
|
|
1849
|
+
for (const canvas of canvases) {
|
|
1850
|
+
const idx = Number(canvas.dataset.index);
|
|
1851
|
+
const ctx = canvas.getContext("2d");
|
|
1852
|
+
if (!ctx) continue;
|
|
1853
|
+
const canvasWidth = Math.min(MAX_CANVAS_WIDTH3, widthX - idx * MAX_CANVAS_WIDTH3);
|
|
1854
|
+
const globalOffset = idx * MAX_CANVAS_WIDTH3;
|
|
1855
|
+
ctx.resetTransform();
|
|
1856
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1857
|
+
ctx.scale(dpr, dpr);
|
|
1858
|
+
ctx.strokeStyle = rulerColor;
|
|
1859
|
+
ctx.lineWidth = 1;
|
|
1860
|
+
if (this.scaleMode === "beats" && this._musicalTickData) {
|
|
1861
|
+
const h = this.rulerHeight;
|
|
1862
|
+
for (const tick of this._musicalTickData.ticks) {
|
|
1863
|
+
const localX = tick.pixel - globalOffset;
|
|
1864
|
+
if (localX < 0 || localX >= canvasWidth) continue;
|
|
1865
|
+
const tickH = tick.type === "major" ? h * 0.6 : tick.type === "minor" ? h * 0.35 : h * 0.15;
|
|
1866
|
+
ctx.globalAlpha = tick.type === "major" ? 1 : 0.5;
|
|
1867
|
+
ctx.beginPath();
|
|
1868
|
+
ctx.moveTo(localX + 0.5, h);
|
|
1869
|
+
ctx.lineTo(localX + 0.5, h - tickH);
|
|
1870
|
+
ctx.stroke();
|
|
1871
|
+
}
|
|
1872
|
+
ctx.globalAlpha = 1;
|
|
1873
|
+
} else if (this._tickData) {
|
|
1874
|
+
for (const [pix, height] of this._tickData.canvasInfo) {
|
|
1875
|
+
const localX = pix - globalOffset;
|
|
1876
|
+
if (localX < 0 || localX >= canvasWidth) continue;
|
|
1877
|
+
ctx.beginPath();
|
|
1878
|
+
ctx.moveTo(localX + 0.5, this.rulerHeight);
|
|
1879
|
+
ctx.lineTo(localX + 0.5, this.rulerHeight - height);
|
|
1880
|
+
ctx.stroke();
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
};
|
|
1886
|
+
DawRulerElement.styles = css6`
|
|
1887
|
+
:host {
|
|
1888
|
+
display: block;
|
|
1889
|
+
position: relative;
|
|
1890
|
+
background: var(--daw-ruler-background, #0f0f1a);
|
|
1891
|
+
}
|
|
1892
|
+
.container {
|
|
1893
|
+
position: relative;
|
|
1894
|
+
}
|
|
1895
|
+
canvas {
|
|
1896
|
+
position: absolute;
|
|
1897
|
+
top: 0;
|
|
1898
|
+
}
|
|
1899
|
+
.label {
|
|
1900
|
+
position: absolute;
|
|
1901
|
+
font-size: 0.7rem;
|
|
1902
|
+
line-height: 1;
|
|
1903
|
+
white-space: nowrap;
|
|
1904
|
+
color: var(--daw-ruler-color, #c49a6c);
|
|
1905
|
+
top: 1px;
|
|
1906
|
+
}
|
|
1907
|
+
.label.centered {
|
|
1908
|
+
transform: translateX(-50%);
|
|
1909
|
+
}
|
|
1910
|
+
`;
|
|
1911
|
+
__decorateClass([
|
|
1912
|
+
property6({ type: Number, attribute: false })
|
|
1913
|
+
], DawRulerElement.prototype, "samplesPerPixel", 2);
|
|
1914
|
+
__decorateClass([
|
|
1915
|
+
property6({ type: Number, attribute: false })
|
|
1916
|
+
], DawRulerElement.prototype, "sampleRate", 2);
|
|
1917
|
+
__decorateClass([
|
|
1918
|
+
property6({ type: Number, attribute: false })
|
|
1919
|
+
], DawRulerElement.prototype, "duration", 2);
|
|
1920
|
+
__decorateClass([
|
|
1921
|
+
property6({ type: Number, attribute: false })
|
|
1922
|
+
], DawRulerElement.prototype, "rulerHeight", 2);
|
|
1923
|
+
__decorateClass([
|
|
1924
|
+
property6({ type: String, attribute: false })
|
|
1925
|
+
], DawRulerElement.prototype, "scaleMode", 2);
|
|
1926
|
+
__decorateClass([
|
|
1927
|
+
property6({ type: Number, attribute: false })
|
|
1928
|
+
], DawRulerElement.prototype, "ticksPerPixel", 2);
|
|
1929
|
+
__decorateClass([
|
|
1930
|
+
property6({ attribute: false })
|
|
1931
|
+
], DawRulerElement.prototype, "meterEntries", 2);
|
|
1932
|
+
__decorateClass([
|
|
1933
|
+
property6({ type: Number, attribute: false })
|
|
1934
|
+
], DawRulerElement.prototype, "ppqn", 2);
|
|
1935
|
+
__decorateClass([
|
|
1936
|
+
property6({ type: Number, attribute: false })
|
|
1937
|
+
], DawRulerElement.prototype, "totalWidth", 2);
|
|
1938
|
+
DawRulerElement = __decorateClass([
|
|
1939
|
+
customElement10("daw-ruler")
|
|
1940
|
+
], DawRulerElement);
|
|
1941
|
+
|
|
1942
|
+
// src/elements/daw-track-controls.ts
|
|
1943
|
+
import { LitElement as LitElement9, html as html8, css as css7 } from "lit";
|
|
1944
|
+
import { customElement as customElement11, property as property7 } from "lit/decorators.js";
|
|
1945
|
+
var DawTrackControlsElement = class extends LitElement9 {
|
|
1688
1946
|
constructor() {
|
|
1689
1947
|
super(...arguments);
|
|
1690
1948
|
this.trackId = null;
|
|
@@ -1718,6 +1976,17 @@ var DawTrackControlsElement = class extends LitElement8 {
|
|
|
1718
1976
|
);
|
|
1719
1977
|
};
|
|
1720
1978
|
}
|
|
1979
|
+
firstUpdated() {
|
|
1980
|
+
requestAnimationFrame(() => {
|
|
1981
|
+
if (!this.isConnected) return;
|
|
1982
|
+
const rect = this.getBoundingClientRect();
|
|
1983
|
+
if (rect.width > 0 && rect.height === 0) {
|
|
1984
|
+
console.warn(
|
|
1985
|
+
"[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."
|
|
1986
|
+
);
|
|
1987
|
+
}
|
|
1988
|
+
});
|
|
1989
|
+
}
|
|
1721
1990
|
_dispatchControl(prop, value) {
|
|
1722
1991
|
if (!this.trackId) return;
|
|
1723
1992
|
this.dispatchEvent(
|
|
@@ -1732,7 +2001,7 @@ var DawTrackControlsElement = class extends LitElement8 {
|
|
|
1732
2001
|
const volPercent = Math.round(this.volume * 100);
|
|
1733
2002
|
const panPercent = Math.round(Math.abs(this.pan) * 100);
|
|
1734
2003
|
const panDisplay = this.pan === 0 ? "C" : (this.pan > 0 ? "R" : "L") + panPercent;
|
|
1735
|
-
return
|
|
2004
|
+
return html8`
|
|
1736
2005
|
<div class="header">
|
|
1737
2006
|
<span class="name" title=${this.trackName}>${this.trackName || "Untitled"}</span>
|
|
1738
2007
|
<button class="remove-btn" @click=${this._onRemoveClick} title="Remove track">
|
|
@@ -1751,7 +2020,7 @@ var DawTrackControlsElement = class extends LitElement8 {
|
|
|
1751
2020
|
S
|
|
1752
2021
|
</button>
|
|
1753
2022
|
</div>
|
|
1754
|
-
<div class="slider-row">
|
|
2023
|
+
<div class="slider-row vol-row">
|
|
1755
2024
|
<span class="slider-label">
|
|
1756
2025
|
<span class="slider-label-name">Vol</span>
|
|
1757
2026
|
<span class="slider-label-value">${volPercent}%</span>
|
|
@@ -1765,7 +2034,7 @@ var DawTrackControlsElement = class extends LitElement8 {
|
|
|
1765
2034
|
@input=${this._onVolumeInput}
|
|
1766
2035
|
/>
|
|
1767
2036
|
</div>
|
|
1768
|
-
<div class="slider-row">
|
|
2037
|
+
<div class="slider-row pan-row">
|
|
1769
2038
|
<span class="slider-label">
|
|
1770
2039
|
<span class="slider-label-name">Pan</span>
|
|
1771
2040
|
<span class="slider-label-value">${panDisplay}</span>
|
|
@@ -1782,7 +2051,7 @@ var DawTrackControlsElement = class extends LitElement8 {
|
|
|
1782
2051
|
`;
|
|
1783
2052
|
}
|
|
1784
2053
|
};
|
|
1785
|
-
DawTrackControlsElement.styles =
|
|
2054
|
+
DawTrackControlsElement.styles = css7`
|
|
1786
2055
|
:host {
|
|
1787
2056
|
display: flex;
|
|
1788
2057
|
flex-direction: column;
|
|
@@ -1795,6 +2064,7 @@ DawTrackControlsElement.styles = css6`
|
|
|
1795
2064
|
font-family: system-ui, sans-serif;
|
|
1796
2065
|
font-size: 11px;
|
|
1797
2066
|
overflow: hidden;
|
|
2067
|
+
container-type: size;
|
|
1798
2068
|
}
|
|
1799
2069
|
.header {
|
|
1800
2070
|
display: flex;
|
|
@@ -1914,64 +2184,52 @@ DawTrackControlsElement.styles = css6`
|
|
|
1914
2184
|
border: none;
|
|
1915
2185
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
|
|
1916
2186
|
}
|
|
2187
|
+
/* Compact modes: drop sliders when the row is too short for the full
|
|
2188
|
+
stack. Thresholds are CONTENT-BOX heights — the host is border-box
|
|
2189
|
+
with 12px vertical padding + 1px border, so an editor-given height H
|
|
2190
|
+
enters compact mode at H <= 89px (Pan hidden) and H <= 73px (Vol also
|
|
2191
|
+
hidden). NOTE: container-type: size requires an explicit height on
|
|
2192
|
+
the host — the editor always provides one; standalone consumers must
|
|
2193
|
+
too (see the firstUpdated guard). */
|
|
2194
|
+
@container (max-height: 76px) {
|
|
2195
|
+
.pan-row {
|
|
2196
|
+
display: none;
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
@container (max-height: 60px) {
|
|
2200
|
+
.vol-row {
|
|
2201
|
+
display: none;
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
1917
2204
|
`;
|
|
1918
2205
|
__decorateClass([
|
|
1919
|
-
|
|
2206
|
+
property7({ attribute: false })
|
|
1920
2207
|
], DawTrackControlsElement.prototype, "trackId", 2);
|
|
1921
2208
|
__decorateClass([
|
|
1922
|
-
|
|
2209
|
+
property7({ attribute: false })
|
|
1923
2210
|
], DawTrackControlsElement.prototype, "trackName", 2);
|
|
1924
2211
|
__decorateClass([
|
|
1925
|
-
|
|
2212
|
+
property7({ type: Number, attribute: false })
|
|
1926
2213
|
], DawTrackControlsElement.prototype, "volume", 2);
|
|
1927
2214
|
__decorateClass([
|
|
1928
|
-
|
|
2215
|
+
property7({ type: Number, attribute: false })
|
|
1929
2216
|
], DawTrackControlsElement.prototype, "pan", 2);
|
|
1930
2217
|
__decorateClass([
|
|
1931
|
-
|
|
2218
|
+
property7({ type: Boolean, attribute: false })
|
|
1932
2219
|
], DawTrackControlsElement.prototype, "muted", 2);
|
|
1933
2220
|
__decorateClass([
|
|
1934
|
-
|
|
2221
|
+
property7({ type: Boolean, attribute: false })
|
|
1935
2222
|
], DawTrackControlsElement.prototype, "soloed", 2);
|
|
1936
2223
|
DawTrackControlsElement = __decorateClass([
|
|
1937
|
-
|
|
2224
|
+
customElement11("daw-track-controls")
|
|
1938
2225
|
], DawTrackControlsElement);
|
|
1939
2226
|
|
|
1940
2227
|
// src/elements/daw-grid.ts
|
|
1941
|
-
import { LitElement as
|
|
1942
|
-
import { customElement as
|
|
2228
|
+
import { LitElement as LitElement10, html as html9, css as css8 } from "lit";
|
|
2229
|
+
import { customElement as customElement12, property as property8 } from "lit/decorators.js";
|
|
1943
2230
|
import { MIN_PIXELS_PER_UNIT } from "@waveform-playlist/core";
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
import { computeMusicalTicks } from "@waveform-playlist/core";
|
|
1947
|
-
var cachedParams = null;
|
|
1948
|
-
var cachedResult = null;
|
|
1949
|
-
function meterEntriesMatch(a, b) {
|
|
1950
|
-
if (a.length !== b.length) return false;
|
|
1951
|
-
for (let i = 0; i < a.length; i++) {
|
|
1952
|
-
if (a[i].tick !== b[i].tick || a[i].numerator !== b[i].numerator || a[i].denominator !== b[i].denominator)
|
|
1953
|
-
return false;
|
|
1954
|
-
}
|
|
1955
|
-
return true;
|
|
1956
|
-
}
|
|
1957
|
-
function paramsMatch(a, b) {
|
|
1958
|
-
return a.ticksPerPixel === b.ticksPerPixel && a.startPixel === b.startPixel && a.endPixel === b.endPixel && meterEntriesMatch(a.meterEntries, b.meterEntries) && (a.ppqn ?? 960) === (b.ppqn ?? 960);
|
|
1959
|
-
}
|
|
1960
|
-
function getCachedMusicalTicks(params) {
|
|
1961
|
-
if (cachedParams && cachedResult && paramsMatch(cachedParams, params)) {
|
|
1962
|
-
return cachedResult;
|
|
1963
|
-
}
|
|
1964
|
-
cachedResult = computeMusicalTicks(params);
|
|
1965
|
-
cachedParams = {
|
|
1966
|
-
...params,
|
|
1967
|
-
meterEntries: params.meterEntries.map((e) => ({ ...e }))
|
|
1968
|
-
};
|
|
1969
|
-
return cachedResult;
|
|
1970
|
-
}
|
|
1971
|
-
|
|
1972
|
-
// src/elements/daw-grid.ts
|
|
1973
|
-
var MAX_CANVAS_WIDTH3 = 1e3;
|
|
1974
|
-
var DawGridElement = class extends LitElement9 {
|
|
2231
|
+
var MAX_CANVAS_WIDTH4 = 1e3;
|
|
2232
|
+
var DawGridElement = class extends LitElement10 {
|
|
1975
2233
|
constructor() {
|
|
1976
2234
|
super(...arguments);
|
|
1977
2235
|
this.ticksPerPixel = 24;
|
|
@@ -1999,25 +2257,25 @@ var DawGridElement = class extends LitElement9 {
|
|
|
1999
2257
|
}
|
|
2000
2258
|
}
|
|
2001
2259
|
render() {
|
|
2002
|
-
if (!this._tickData) return
|
|
2260
|
+
if (!this._tickData) return html9``;
|
|
2003
2261
|
const totalWidth = this.length;
|
|
2004
2262
|
const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
|
|
2005
2263
|
const indices = getVisibleChunkIndices(
|
|
2006
2264
|
totalWidth,
|
|
2007
|
-
|
|
2265
|
+
MAX_CANVAS_WIDTH4,
|
|
2008
2266
|
this.visibleStart,
|
|
2009
2267
|
this.visibleEnd
|
|
2010
2268
|
);
|
|
2011
|
-
return
|
|
2269
|
+
return html9`
|
|
2012
2270
|
<div class="container" style="width: ${totalWidth}px; height: ${this.height}px;">
|
|
2013
2271
|
${indices.map((i) => {
|
|
2014
|
-
const width = Math.min(
|
|
2015
|
-
return
|
|
2272
|
+
const width = Math.min(MAX_CANVAS_WIDTH4, totalWidth - i * MAX_CANVAS_WIDTH4);
|
|
2273
|
+
return html9`
|
|
2016
2274
|
<canvas
|
|
2017
2275
|
data-index=${i}
|
|
2018
2276
|
width=${width * dpr}
|
|
2019
2277
|
height=${this.height * dpr}
|
|
2020
|
-
style="left: ${i *
|
|
2278
|
+
style="left: ${i * MAX_CANVAS_WIDTH4}px; width: ${width}px; height: ${this.height}px;"
|
|
2021
2279
|
></canvas>
|
|
2022
2280
|
`;
|
|
2023
2281
|
})}
|
|
@@ -2041,8 +2299,8 @@ var DawGridElement = class extends LitElement9 {
|
|
|
2041
2299
|
const idx = Number(canvas.dataset.index);
|
|
2042
2300
|
const ctx = canvas.getContext("2d");
|
|
2043
2301
|
if (!ctx) continue;
|
|
2044
|
-
const chunkLeft = idx *
|
|
2045
|
-
const canvasWidth = Math.min(
|
|
2302
|
+
const chunkLeft = idx * MAX_CANVAS_WIDTH4;
|
|
2303
|
+
const canvasWidth = Math.min(MAX_CANVAS_WIDTH4, this.length - chunkLeft);
|
|
2046
2304
|
ctx.resetTransform();
|
|
2047
2305
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2048
2306
|
ctx.scale(dpr, dpr);
|
|
@@ -2073,7 +2331,7 @@ var DawGridElement = class extends LitElement9 {
|
|
|
2073
2331
|
}
|
|
2074
2332
|
}
|
|
2075
2333
|
};
|
|
2076
|
-
DawGridElement.styles =
|
|
2334
|
+
DawGridElement.styles = css8`
|
|
2077
2335
|
:host {
|
|
2078
2336
|
display: block;
|
|
2079
2337
|
position: absolute;
|
|
@@ -2091,33 +2349,33 @@ DawGridElement.styles = css7`
|
|
|
2091
2349
|
}
|
|
2092
2350
|
`;
|
|
2093
2351
|
__decorateClass([
|
|
2094
|
-
|
|
2352
|
+
property8({ type: Number, attribute: false })
|
|
2095
2353
|
], DawGridElement.prototype, "ticksPerPixel", 2);
|
|
2096
2354
|
__decorateClass([
|
|
2097
|
-
|
|
2355
|
+
property8({ attribute: false })
|
|
2098
2356
|
], DawGridElement.prototype, "meterEntries", 2);
|
|
2099
2357
|
__decorateClass([
|
|
2100
|
-
|
|
2358
|
+
property8({ type: Number, attribute: false })
|
|
2101
2359
|
], DawGridElement.prototype, "ppqn", 2);
|
|
2102
2360
|
__decorateClass([
|
|
2103
|
-
|
|
2361
|
+
property8({ type: Number, attribute: false })
|
|
2104
2362
|
], DawGridElement.prototype, "visibleStart", 2);
|
|
2105
2363
|
__decorateClass([
|
|
2106
|
-
|
|
2364
|
+
property8({ type: Number, attribute: false })
|
|
2107
2365
|
], DawGridElement.prototype, "visibleEnd", 2);
|
|
2108
2366
|
__decorateClass([
|
|
2109
|
-
|
|
2367
|
+
property8({ type: Number, attribute: false })
|
|
2110
2368
|
], DawGridElement.prototype, "length", 2);
|
|
2111
2369
|
__decorateClass([
|
|
2112
|
-
|
|
2370
|
+
property8({ type: Number, attribute: false })
|
|
2113
2371
|
], DawGridElement.prototype, "height", 2);
|
|
2114
2372
|
DawGridElement = __decorateClass([
|
|
2115
|
-
|
|
2373
|
+
customElement12("daw-grid")
|
|
2116
2374
|
], DawGridElement);
|
|
2117
2375
|
|
|
2118
2376
|
// src/styles/theme.ts
|
|
2119
|
-
import { css as
|
|
2120
|
-
var hostStyles =
|
|
2377
|
+
import { css as css9 } from "lit";
|
|
2378
|
+
var hostStyles = css9`
|
|
2121
2379
|
:host {
|
|
2122
2380
|
--daw-wave-color: #c49a6c;
|
|
2123
2381
|
--daw-progress-color: #63c75f;
|
|
@@ -2133,7 +2391,7 @@ var hostStyles = css8`
|
|
|
2133
2391
|
--daw-clip-header-text: #e0d4c8;
|
|
2134
2392
|
}
|
|
2135
2393
|
`;
|
|
2136
|
-
var clipStyles =
|
|
2394
|
+
var clipStyles = css9`
|
|
2137
2395
|
.clip-container {
|
|
2138
2396
|
position: absolute;
|
|
2139
2397
|
overflow: hidden;
|
|
@@ -2885,7 +3143,11 @@ var PointerHandler = class {
|
|
|
2885
3143
|
e.preventDefault();
|
|
2886
3144
|
this._timeline = this._host.shadowRoot?.querySelector(".timeline");
|
|
2887
3145
|
if (this._timeline) {
|
|
2888
|
-
|
|
3146
|
+
try {
|
|
3147
|
+
this._timeline.setPointerCapture(e.pointerId);
|
|
3148
|
+
} catch (err) {
|
|
3149
|
+
console.warn("[dawcore] setPointerCapture failed: " + String(err));
|
|
3150
|
+
}
|
|
2889
3151
|
const onMove = (me) => clipHandler.onPointerMove(me);
|
|
2890
3152
|
const onUp = (ue) => {
|
|
2891
3153
|
clipHandler.onPointerUp(ue);
|
|
@@ -2907,11 +3169,20 @@ var PointerHandler = class {
|
|
|
2907
3169
|
}
|
|
2908
3170
|
}
|
|
2909
3171
|
this._timeline = this._host.shadowRoot?.querySelector(".timeline");
|
|
2910
|
-
if (!this._timeline)
|
|
3172
|
+
if (!this._timeline) {
|
|
3173
|
+
console.warn(
|
|
3174
|
+
"[dawcore] PointerHandler: .timeline not found in shadow root \u2014 seek/selection ignored"
|
|
3175
|
+
);
|
|
3176
|
+
return;
|
|
3177
|
+
}
|
|
2911
3178
|
this._timelineRect = this._timeline.getBoundingClientRect();
|
|
2912
3179
|
this._dragStartPx = this._pxFromPointer(e);
|
|
2913
3180
|
this._isDragging = false;
|
|
2914
|
-
|
|
3181
|
+
try {
|
|
3182
|
+
this._timeline.setPointerCapture(e.pointerId);
|
|
3183
|
+
} catch (err) {
|
|
3184
|
+
console.warn("[dawcore] setPointerCapture failed: " + String(err));
|
|
3185
|
+
}
|
|
2915
3186
|
this._timeline.addEventListener("pointermove", this._onPointerMove);
|
|
2916
3187
|
this._timeline.addEventListener("pointerup", this._onPointerUp);
|
|
2917
3188
|
};
|
|
@@ -3843,9 +4114,143 @@ async function loadWaveformDataFromUrl(src) {
|
|
|
3843
4114
|
}
|
|
3844
4115
|
}
|
|
3845
4116
|
|
|
4117
|
+
// src/controllers/scroll-sync-controller.ts
|
|
4118
|
+
var LINE_HEIGHT_PX = 16;
|
|
4119
|
+
var ScrollSyncController = class {
|
|
4120
|
+
constructor(host) {
|
|
4121
|
+
this._scrollContainer = null;
|
|
4122
|
+
this._wheelTargets = /* @__PURE__ */ new Set();
|
|
4123
|
+
this._warnedX = false;
|
|
4124
|
+
this._warnedY = false;
|
|
4125
|
+
/** Selector (in host shadow DOM) for the scroll container. */
|
|
4126
|
+
this.scrollSelector = "";
|
|
4127
|
+
/** Selector for the element receiving translate3d(-scrollLeft, 0, 0). */
|
|
4128
|
+
this.xTargetSelector = "";
|
|
4129
|
+
/** Selector for the element receiving translate3d(0, -scrollTop, 0). */
|
|
4130
|
+
this.yTargetSelector = "";
|
|
4131
|
+
/**
|
|
4132
|
+
* Selector (or comma-separated selectors) for elements whose wheel events
|
|
4133
|
+
* forward to the scroll container. All matching elements receive listeners.
|
|
4134
|
+
*/
|
|
4135
|
+
this.wheelForwardSelector = "";
|
|
4136
|
+
this._onScroll = () => {
|
|
4137
|
+
this._apply();
|
|
4138
|
+
};
|
|
4139
|
+
this._onWheel = (e) => {
|
|
4140
|
+
const sc = this._scrollContainer;
|
|
4141
|
+
if (!sc) return;
|
|
4142
|
+
const scale = e.deltaMode === WheelEvent.DOM_DELTA_LINE ? LINE_HEIGHT_PX : e.deltaMode === WheelEvent.DOM_DELTA_PAGE ? sc.clientHeight : 1;
|
|
4143
|
+
const scaleX = e.deltaMode === WheelEvent.DOM_DELTA_PAGE ? sc.clientWidth : scale;
|
|
4144
|
+
const beforeLeft = sc.scrollLeft;
|
|
4145
|
+
const beforeTop = sc.scrollTop;
|
|
4146
|
+
sc.scrollLeft += e.deltaX * scaleX;
|
|
4147
|
+
sc.scrollTop += e.deltaY * scale;
|
|
4148
|
+
if (sc.scrollLeft !== beforeLeft || sc.scrollTop !== beforeTop) {
|
|
4149
|
+
e.preventDefault();
|
|
4150
|
+
}
|
|
4151
|
+
};
|
|
4152
|
+
this._host = host;
|
|
4153
|
+
host.addController(this);
|
|
4154
|
+
}
|
|
4155
|
+
hostConnected() {
|
|
4156
|
+
requestAnimationFrame(() => {
|
|
4157
|
+
if (!this._host.isConnected) return;
|
|
4158
|
+
this._attach();
|
|
4159
|
+
if (!this._scrollContainer && this.scrollSelector) {
|
|
4160
|
+
console.warn(
|
|
4161
|
+
'[dawcore] ScrollSyncController: scroll container not found for "' + this.scrollSelector + '"'
|
|
4162
|
+
);
|
|
4163
|
+
}
|
|
4164
|
+
});
|
|
4165
|
+
}
|
|
4166
|
+
hostDisconnected() {
|
|
4167
|
+
this._scrollContainer?.removeEventListener("scroll", this._onScroll);
|
|
4168
|
+
this._scrollContainer = null;
|
|
4169
|
+
for (const target of this._wheelTargets) {
|
|
4170
|
+
target.removeEventListener("wheel", this._onWheel);
|
|
4171
|
+
}
|
|
4172
|
+
this._wheelTargets.clear();
|
|
4173
|
+
}
|
|
4174
|
+
/**
|
|
4175
|
+
* Re-attach and re-apply transforms from the current scroll position.
|
|
4176
|
+
* Called from the host's updated() so elements created by a re-render
|
|
4177
|
+
* (e.g. the ruler appearing when the first track loads) pick up the
|
|
4178
|
+
* current offset and listeners.
|
|
4179
|
+
*/
|
|
4180
|
+
sync() {
|
|
4181
|
+
this._attach();
|
|
4182
|
+
}
|
|
4183
|
+
_query(selector) {
|
|
4184
|
+
return selector ? this._host.shadowRoot?.querySelector(selector) : null;
|
|
4185
|
+
}
|
|
4186
|
+
_queryAll(selector) {
|
|
4187
|
+
if (!selector) return [];
|
|
4188
|
+
return Array.from(this._host.shadowRoot?.querySelectorAll(selector) ?? []);
|
|
4189
|
+
}
|
|
4190
|
+
_attach() {
|
|
4191
|
+
const container = this._query(this.scrollSelector);
|
|
4192
|
+
if (!container) {
|
|
4193
|
+
if (this._scrollContainer && !this._scrollContainer.isConnected) {
|
|
4194
|
+
console.warn(
|
|
4195
|
+
'[dawcore] ScrollSyncController: scroll container "' + this.scrollSelector + '" was removed from the DOM \u2014 detaching listeners until it reappears.'
|
|
4196
|
+
);
|
|
4197
|
+
this._scrollContainer.removeEventListener("scroll", this._onScroll);
|
|
4198
|
+
this._scrollContainer = null;
|
|
4199
|
+
for (const t of this._wheelTargets) t.removeEventListener("wheel", this._onWheel);
|
|
4200
|
+
this._wheelTargets.clear();
|
|
4201
|
+
}
|
|
4202
|
+
return;
|
|
4203
|
+
}
|
|
4204
|
+
if (container !== this._scrollContainer) {
|
|
4205
|
+
this._scrollContainer?.removeEventListener("scroll", this._onScroll);
|
|
4206
|
+
this._scrollContainer = container;
|
|
4207
|
+
container.addEventListener("scroll", this._onScroll, { passive: true });
|
|
4208
|
+
}
|
|
4209
|
+
const nextTargets = new Set(this._queryAll(this.wheelForwardSelector));
|
|
4210
|
+
for (const old of this._wheelTargets) {
|
|
4211
|
+
if (!nextTargets.has(old)) {
|
|
4212
|
+
old.removeEventListener("wheel", this._onWheel);
|
|
4213
|
+
this._wheelTargets.delete(old);
|
|
4214
|
+
}
|
|
4215
|
+
}
|
|
4216
|
+
for (const next of nextTargets) {
|
|
4217
|
+
if (!this._wheelTargets.has(next)) {
|
|
4218
|
+
next.addEventListener("wheel", this._onWheel, { passive: false });
|
|
4219
|
+
this._wheelTargets.add(next);
|
|
4220
|
+
}
|
|
4221
|
+
}
|
|
4222
|
+
this._apply();
|
|
4223
|
+
}
|
|
4224
|
+
_apply() {
|
|
4225
|
+
const sc = this._scrollContainer;
|
|
4226
|
+
if (!sc) return;
|
|
4227
|
+
const xTarget = this._query(this.xTargetSelector);
|
|
4228
|
+
if (xTarget) {
|
|
4229
|
+
xTarget.style.transform = `translate3d(${-sc.scrollLeft}px, 0, 0)`;
|
|
4230
|
+
this._warnedX = false;
|
|
4231
|
+
} else if (this.xTargetSelector && sc.scrollLeft !== 0 && !this._warnedX) {
|
|
4232
|
+
this._warnedX = true;
|
|
4233
|
+
console.warn(
|
|
4234
|
+
'[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.'
|
|
4235
|
+
);
|
|
4236
|
+
}
|
|
4237
|
+
const yTarget = this._query(this.yTargetSelector);
|
|
4238
|
+
if (yTarget) {
|
|
4239
|
+
yTarget.style.transform = `translate3d(0, ${-sc.scrollTop}px, 0)`;
|
|
4240
|
+
this._warnedY = false;
|
|
4241
|
+
} else if (this.yTargetSelector && sc.scrollTop !== 0 && !this._warnedY) {
|
|
4242
|
+
this._warnedY = true;
|
|
4243
|
+
console.warn(
|
|
4244
|
+
'[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.'
|
|
4245
|
+
);
|
|
4246
|
+
}
|
|
4247
|
+
}
|
|
4248
|
+
};
|
|
4249
|
+
|
|
3846
4250
|
// src/elements/daw-editor.ts
|
|
4251
|
+
var RULER_HEIGHT = 30;
|
|
3847
4252
|
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();";
|
|
3848
|
-
var DawEditorElement = class extends
|
|
4253
|
+
var DawEditorElement = class extends LitElement11 {
|
|
3849
4254
|
constructor() {
|
|
3850
4255
|
super(...arguments);
|
|
3851
4256
|
this._samplesPerPixel = 1024;
|
|
@@ -3904,6 +4309,11 @@ var DawEditorElement = class extends LitElement10 {
|
|
|
3904
4309
|
v.scrollSelector = ".scroll-area";
|
|
3905
4310
|
return v;
|
|
3906
4311
|
})();
|
|
4312
|
+
this._scrollSync = (() => {
|
|
4313
|
+
const s = new ScrollSyncController(this);
|
|
4314
|
+
s.scrollSelector = ".scroll-area";
|
|
4315
|
+
return s;
|
|
4316
|
+
})();
|
|
3907
4317
|
/**
|
|
3908
4318
|
* Cache of the last ViewportState forwarded to the spectrogram controller.
|
|
3909
4319
|
* Lit's `updated()` fires on every reactive state change (`_isPlaying`,
|
|
@@ -4450,6 +4860,13 @@ var DawEditorElement = class extends LitElement10 {
|
|
|
4450
4860
|
}
|
|
4451
4861
|
}
|
|
4452
4862
|
updated(_changed) {
|
|
4863
|
+
this._scrollSync.xTargetSelector = this._showRuler ? ".ruler-content" : "";
|
|
4864
|
+
this._scrollSync.yTargetSelector = this._showControls ? ".controls-column" : "";
|
|
4865
|
+
this._scrollSync.wheelForwardSelector = [
|
|
4866
|
+
this._showControls ? ".controls-viewport" : "",
|
|
4867
|
+
this._showRuler ? ".ruler-viewport" : ""
|
|
4868
|
+
].filter(Boolean).join(", ");
|
|
4869
|
+
this._scrollSync.sync();
|
|
4453
4870
|
if (this._spectrogramController) {
|
|
4454
4871
|
const vs = this._viewport.visibleStart;
|
|
4455
4872
|
const ve = this._viewport.visibleEnd;
|
|
@@ -5611,7 +6028,7 @@ var DawEditorElement = class extends LitElement10 {
|
|
|
5611
6028
|
const w = Math.floor(audibleSamples / renderSpp);
|
|
5612
6029
|
return rs.peaks.map((chPeaks, ch) => {
|
|
5613
6030
|
const slicedPeaks = latencyPixels > 0 ? chPeaks.slice(latencyPixels * 2) : chPeaks;
|
|
5614
|
-
return
|
|
6031
|
+
return html10`
|
|
5615
6032
|
<daw-waveform
|
|
5616
6033
|
data-recording-track=${trackId}
|
|
5617
6034
|
data-recording-channel=${ch}
|
|
@@ -5633,12 +6050,7 @@ var DawEditorElement = class extends LitElement10 {
|
|
|
5633
6050
|
const playhead = this._getPlayhead();
|
|
5634
6051
|
if (!playhead || !this._engine) return;
|
|
5635
6052
|
const engine = this._engine;
|
|
5636
|
-
const
|
|
5637
|
-
const audibleTime = () => {
|
|
5638
|
-
const outputLatency = "outputLatency" in ctx ? ctx.outputLatency : 0;
|
|
5639
|
-
const t = engine.getCurrentTime() - outputLatency - engine.lookAhead;
|
|
5640
|
-
return Number.isFinite(t) ? Math.max(0, t) : 0;
|
|
5641
|
-
};
|
|
6053
|
+
const audibleTime = () => engine.getAudibleTime();
|
|
5642
6054
|
if (this.scaleMode === "beats") {
|
|
5643
6055
|
const secondsToTicksFn = (s) => this._secondsToTicks(s);
|
|
5644
6056
|
playhead.startBeatsAnimationWithMap(audibleTime, secondsToTicksFn, this.ticksPerPixel);
|
|
@@ -5649,10 +6061,7 @@ var DawEditorElement = class extends LitElement10 {
|
|
|
5649
6061
|
_stopPlayhead() {
|
|
5650
6062
|
const playhead = this._getPlayhead();
|
|
5651
6063
|
if (!playhead) return;
|
|
5652
|
-
const
|
|
5653
|
-
const outputLatency = "outputLatency" in ctx ? ctx.outputLatency : 0;
|
|
5654
|
-
const lookAhead = this._engine?.lookAhead ?? 0;
|
|
5655
|
-
const t = this._currentTime - outputLatency - lookAhead;
|
|
6064
|
+
const t = this._currentTime;
|
|
5656
6065
|
const visualTime = Number.isFinite(t) ? Math.max(0, t) : 0;
|
|
5657
6066
|
if (this.scaleMode === "beats") {
|
|
5658
6067
|
playhead.stopBeatsAnimationWithMap(
|
|
@@ -5667,6 +6076,14 @@ var DawEditorElement = class extends LitElement10 {
|
|
|
5667
6076
|
_getPlayhead() {
|
|
5668
6077
|
return this.shadowRoot?.querySelector("daw-playhead");
|
|
5669
6078
|
}
|
|
6079
|
+
/** True when the controls column should be rendered (and its selector is valid). */
|
|
6080
|
+
get _showControls() {
|
|
6081
|
+
return this._getOrderedTracks().length > 0 || this.indefinitePlayback;
|
|
6082
|
+
}
|
|
6083
|
+
/** True when the ruler header band should be rendered (and its selector is valid). */
|
|
6084
|
+
get _showRuler() {
|
|
6085
|
+
return (this._getOrderedTracks().length > 0 || this.scaleMode === "beats" || this.indefinitePlayback) && this.timescale;
|
|
6086
|
+
}
|
|
5670
6087
|
_getOrderedTracks() {
|
|
5671
6088
|
const domOrder = [...this.querySelectorAll("daw-track")].map(
|
|
5672
6089
|
(el) => el.trackId
|
|
@@ -5708,64 +6125,79 @@ var DawEditorElement = class extends LitElement10 {
|
|
|
5708
6125
|
trackHeight: this.waveHeight * numChannels + (this.clipHeaders ? this.clipHeaderHeight : 0)
|
|
5709
6126
|
};
|
|
5710
6127
|
});
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
style="height: ${t.trackHeight}px;"
|
|
5718
|
-
.trackId=${t.trackId}
|
|
5719
|
-
.trackName=${t.descriptor?.name ?? "Untitled"}
|
|
5720
|
-
.volume=${t.descriptor?.volume ?? 1}
|
|
5721
|
-
.pan=${t.descriptor?.pan ?? 0}
|
|
5722
|
-
.muted=${t.descriptor?.muted ?? false}
|
|
5723
|
-
.soloed=${t.descriptor?.soloed ?? false}
|
|
5724
|
-
></daw-track-controls>
|
|
5725
|
-
`
|
|
5726
|
-
)}
|
|
5727
|
-
</div>` : ""}
|
|
5728
|
-
<div class="scroll-area">
|
|
5729
|
-
<div
|
|
5730
|
-
class="timeline ${this._dragOver ? "drag-over" : ""}"
|
|
5731
|
-
style="width: ${this._totalWidth > 0 ? this._totalWidth + "px" : "100%"};"
|
|
5732
|
-
data-playing=${this._isPlaying}
|
|
5733
|
-
@pointerdown=${this._pointer.onPointerDown}
|
|
5734
|
-
@dragover=${this._onDragOver}
|
|
5735
|
-
@dragleave=${this._onDragLeave}
|
|
5736
|
-
@drop=${this._onDrop}
|
|
5737
|
-
>
|
|
5738
|
-
${(orderedTracks.length > 0 || this.scaleMode === "beats" || this.indefinitePlayback) && this.timescale ? html9`<daw-ruler
|
|
5739
|
-
.samplesPerPixel=${spp}
|
|
5740
|
-
.sampleRate=${this.effectiveSampleRate}
|
|
5741
|
-
.duration=${this._duration}
|
|
5742
|
-
.scaleMode=${this.scaleMode}
|
|
5743
|
-
.ticksPerPixel=${this.ticksPerPixel}
|
|
5744
|
-
.meterEntries=${this._meterEntries}
|
|
5745
|
-
.ppqn=${this.ppqn}
|
|
5746
|
-
.totalWidth=${this._totalWidth}
|
|
5747
|
-
></daw-ruler>` : ""}
|
|
5748
|
-
${this.scaleMode === "beats" ? html9`<daw-grid
|
|
5749
|
-
style="top: ${this.timescale ? 30 : 0}px;"
|
|
5750
|
-
.ticksPerPixel=${this.ticksPerPixel}
|
|
5751
|
-
.meterEntries=${this._meterEntries}
|
|
5752
|
-
.ppqn=${this.ppqn}
|
|
5753
|
-
.visibleStart=${this._viewport.visibleStart}
|
|
5754
|
-
.visibleEnd=${this._viewport.visibleEnd}
|
|
5755
|
-
.length=${this._totalWidth}
|
|
5756
|
-
.height=${orderedTracks.length > 0 ? orderedTracks.reduce((sum, t) => sum + t.trackHeight + 1, 0) : this._emptyGridHeight}
|
|
5757
|
-
></daw-grid>` : ""}
|
|
5758
|
-
${orderedTracks.length > 0 || this.scaleMode === "beats" || this.indefinitePlayback ? html9`<daw-selection .startPx=${selStartPx} .endPx=${selEndPx}></daw-selection>
|
|
5759
|
-
<daw-playhead></daw-playhead>` : ""}
|
|
5760
|
-
${orderedTracks.map((t) => {
|
|
5761
|
-
const channelHeight = this.waveHeight;
|
|
5762
|
-
return html9`
|
|
6128
|
+
const showControls = this._showControls;
|
|
6129
|
+
const showRuler = this._showRuler;
|
|
6130
|
+
return html10`
|
|
6131
|
+
${showRuler ? html10`<div class="header-row" style="height: ${RULER_HEIGHT}px;">
|
|
6132
|
+
${showControls ? html10`<div class="ruler-gap"></div>` : ""}
|
|
6133
|
+
<div class="ruler-viewport" @pointerdown=${this._pointer.onPointerDown}>
|
|
5763
6134
|
<div
|
|
5764
|
-
class="
|
|
5765
|
-
style="
|
|
5766
|
-
data-track-id=${t.trackId}
|
|
6135
|
+
class="ruler-content"
|
|
6136
|
+
style="width: ${this._totalWidth > 0 ? this._totalWidth + "px" : "100%"};"
|
|
5767
6137
|
>
|
|
5768
|
-
|
|
6138
|
+
<daw-ruler
|
|
6139
|
+
.samplesPerPixel=${spp}
|
|
6140
|
+
.sampleRate=${this.effectiveSampleRate}
|
|
6141
|
+
.duration=${this._duration}
|
|
6142
|
+
.scaleMode=${this.scaleMode}
|
|
6143
|
+
.ticksPerPixel=${this.ticksPerPixel}
|
|
6144
|
+
.meterEntries=${this._meterEntries}
|
|
6145
|
+
.ppqn=${this.ppqn}
|
|
6146
|
+
.totalWidth=${this._totalWidth}
|
|
6147
|
+
.rulerHeight=${RULER_HEIGHT}
|
|
6148
|
+
></daw-ruler>
|
|
6149
|
+
</div>
|
|
6150
|
+
</div>
|
|
6151
|
+
</div>` : ""}
|
|
6152
|
+
<div class="body">
|
|
6153
|
+
${showControls ? html10`<div class="controls-viewport">
|
|
6154
|
+
<div class="controls-column">
|
|
6155
|
+
${orderedTracks.map(
|
|
6156
|
+
(t) => html10`
|
|
6157
|
+
<daw-track-controls
|
|
6158
|
+
style="height: ${t.trackHeight}px;"
|
|
6159
|
+
.trackId=${t.trackId}
|
|
6160
|
+
.trackName=${t.descriptor?.name ?? "Untitled"}
|
|
6161
|
+
.volume=${t.descriptor?.volume ?? 1}
|
|
6162
|
+
.pan=${t.descriptor?.pan ?? 0}
|
|
6163
|
+
.muted=${t.descriptor?.muted ?? false}
|
|
6164
|
+
.soloed=${t.descriptor?.soloed ?? false}
|
|
6165
|
+
></daw-track-controls>
|
|
6166
|
+
`
|
|
6167
|
+
)}
|
|
6168
|
+
</div>
|
|
6169
|
+
</div>` : ""}
|
|
6170
|
+
<div class="scroll-area">
|
|
6171
|
+
<div
|
|
6172
|
+
class="timeline ${this._dragOver ? "drag-over" : ""}"
|
|
6173
|
+
style="width: ${this._totalWidth > 0 ? this._totalWidth + "px" : "100%"};"
|
|
6174
|
+
data-playing=${this._isPlaying}
|
|
6175
|
+
@pointerdown=${this._pointer.onPointerDown}
|
|
6176
|
+
@dragover=${this._onDragOver}
|
|
6177
|
+
@dragleave=${this._onDragLeave}
|
|
6178
|
+
@drop=${this._onDrop}
|
|
6179
|
+
>
|
|
6180
|
+
${this.scaleMode === "beats" ? html10`<daw-grid
|
|
6181
|
+
style="top: 0px;"
|
|
6182
|
+
.ticksPerPixel=${this.ticksPerPixel}
|
|
6183
|
+
.meterEntries=${this._meterEntries}
|
|
6184
|
+
.ppqn=${this.ppqn}
|
|
6185
|
+
.visibleStart=${this._viewport.visibleStart}
|
|
6186
|
+
.visibleEnd=${this._viewport.visibleEnd}
|
|
6187
|
+
.length=${this._totalWidth}
|
|
6188
|
+
.height=${orderedTracks.length > 0 ? orderedTracks.reduce((sum, t) => sum + t.trackHeight, 0) : this._emptyGridHeight}
|
|
6189
|
+
></daw-grid>` : ""}
|
|
6190
|
+
${orderedTracks.length > 0 || this.scaleMode === "beats" || this.indefinitePlayback ? html10`<daw-selection .startPx=${selStartPx} .endPx=${selEndPx}></daw-selection>
|
|
6191
|
+
<daw-playhead></daw-playhead>` : ""}
|
|
6192
|
+
${orderedTracks.map((t) => {
|
|
6193
|
+
const channelHeight = this.waveHeight;
|
|
6194
|
+
return html10`
|
|
6195
|
+
<div
|
|
6196
|
+
class="track-row ${t.trackId === this._selectedTrackId ? "selected" : ""}"
|
|
6197
|
+
style="height: ${t.trackHeight}px;"
|
|
6198
|
+
data-track-id=${t.trackId}
|
|
6199
|
+
>
|
|
6200
|
+
${t.track.clips.map((clip) => {
|
|
5769
6201
|
const peakData = this._peaksData.get(clip.id);
|
|
5770
6202
|
let clipLeft;
|
|
5771
6203
|
let width;
|
|
@@ -5808,7 +6240,10 @@ var DawEditorElement = class extends LitElement10 {
|
|
|
5808
6240
|
const segEndSample = Math.round(segEndAudioSec * sr);
|
|
5809
6241
|
const totalPeaks = clip.durationSamples / baseScale;
|
|
5810
6242
|
clipSegments.push({
|
|
5811
|
-
peakStart: Math.max(
|
|
6243
|
+
peakStart: Math.max(
|
|
6244
|
+
0,
|
|
6245
|
+
(segStartSample - clip.offsetSamples) / baseScale
|
|
6246
|
+
),
|
|
5812
6247
|
peakEnd: Math.min(
|
|
5813
6248
|
totalPeaks,
|
|
5814
6249
|
(segEndSample - clip.offsetSamples) / baseScale
|
|
@@ -5822,78 +6257,79 @@ var DawEditorElement = class extends LitElement10 {
|
|
|
5822
6257
|
const channels = segmentChannels ?? peakData?.data ?? [new Int16Array(0)];
|
|
5823
6258
|
const hdrH = this.clipHeaders ? this.clipHeaderHeight : 0;
|
|
5824
6259
|
const chH = this.waveHeight;
|
|
5825
|
-
return
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
data-clip-id=${clip.id}
|
|
5833
|
-
data-track-id=${t.trackId}
|
|
5834
|
-
?data-interactive=${this.interactiveClips}
|
|
5835
|
-
>
|
|
5836
|
-
<span>${clip.name || t.descriptor?.name || ""}</span>
|
|
5837
|
-
</div>` : ""}
|
|
5838
|
-
${t.descriptor?.renderMode === "piano-roll" ? html9`<daw-piano-roll
|
|
5839
|
-
style="position:absolute;left:0;top:${hdrH}px;"
|
|
5840
|
-
.midiNotes=${clip.midiNotes ?? []}
|
|
5841
|
-
.length=${peakData?.length ?? width}
|
|
5842
|
-
.waveHeight=${chH * channels.length}
|
|
5843
|
-
.samplesPerPixel=${this._renderSpp}
|
|
5844
|
-
.sampleRate=${this.effectiveSampleRate}
|
|
5845
|
-
.clipOffsetSeconds=${(clip.offsetSamples ?? 0) / this.effectiveSampleRate}
|
|
5846
|
-
.visibleStart=${this._viewport.visibleStart}
|
|
5847
|
-
.visibleEnd=${this._viewport.visibleEnd}
|
|
5848
|
-
.originX=${clipLeft}
|
|
5849
|
-
?selected=${t.trackId === this._selectedTrackId}
|
|
5850
|
-
></daw-piano-roll>` : t.descriptor?.renderMode === "spectrogram" ? channels.map(
|
|
5851
|
-
(_chPeaks, chIdx) => html9`<daw-spectrogram
|
|
5852
|
-
style="position:absolute;left:0;top:${hdrH + chIdx * chH}px;height:${chH}px;width:${peakData?.length ?? width}px;"
|
|
5853
|
-
.clipId=${clip.id}
|
|
5854
|
-
.trackId=${t.trackId}
|
|
5855
|
-
.channelIndex=${chIdx}
|
|
5856
|
-
.length=${peakData?.length ?? width}
|
|
5857
|
-
.waveHeight=${chH}
|
|
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
|
-
></daw-spectrogram>`
|
|
5865
|
-
) : channels.map(
|
|
5866
|
-
(chPeaks, chIdx) => html9` <daw-waveform
|
|
5867
|
-
style="position:absolute;left:0;top:${hdrH + chIdx * chH}px;"
|
|
5868
|
-
.peaks=${chPeaks}
|
|
5869
|
-
.length=${peakData?.length ?? width}
|
|
5870
|
-
.waveHeight=${chH}
|
|
5871
|
-
.barWidth=${this.barWidth}
|
|
5872
|
-
.barGap=${this.barGap}
|
|
5873
|
-
.visibleStart=${this._viewport.visibleStart}
|
|
5874
|
-
.visibleEnd=${this._viewport.visibleEnd}
|
|
5875
|
-
.originX=${clipLeft}
|
|
5876
|
-
.segments=${clipSegments}
|
|
5877
|
-
></daw-waveform>`
|
|
5878
|
-
)}
|
|
5879
|
-
${this.interactiveClips ? html9` <div
|
|
5880
|
-
class="clip-boundary"
|
|
5881
|
-
data-boundary-edge="left"
|
|
5882
|
-
data-clip-id=${clip.id}
|
|
5883
|
-
data-track-id=${t.trackId}
|
|
5884
|
-
></div>
|
|
5885
|
-
<div
|
|
5886
|
-
class="clip-boundary"
|
|
5887
|
-
data-boundary-edge="right"
|
|
6260
|
+
return html10` <div
|
|
6261
|
+
class="clip-container"
|
|
6262
|
+
style="left:${clipLeft}px;top:0;width:${width}px;height:${t.trackHeight}px;"
|
|
6263
|
+
data-clip-id=${clip.id}
|
|
6264
|
+
>
|
|
6265
|
+
${hdrH > 0 ? html10`<div
|
|
6266
|
+
class="clip-header"
|
|
5888
6267
|
data-clip-id=${clip.id}
|
|
5889
6268
|
data-track-id=${t.trackId}
|
|
5890
|
-
|
|
5891
|
-
|
|
6269
|
+
?data-interactive=${this.interactiveClips}
|
|
6270
|
+
>
|
|
6271
|
+
<span>${clip.name || t.descriptor?.name || ""}</span>
|
|
6272
|
+
</div>` : ""}
|
|
6273
|
+
${t.descriptor?.renderMode === "piano-roll" ? html10`<daw-piano-roll
|
|
6274
|
+
style="position:absolute;left:0;top:${hdrH}px;"
|
|
6275
|
+
.midiNotes=${clip.midiNotes ?? []}
|
|
6276
|
+
.length=${peakData?.length ?? width}
|
|
6277
|
+
.waveHeight=${chH * channels.length}
|
|
6278
|
+
.samplesPerPixel=${this._renderSpp}
|
|
6279
|
+
.sampleRate=${this.effectiveSampleRate}
|
|
6280
|
+
.clipOffsetSeconds=${(clip.offsetSamples ?? 0) / this.effectiveSampleRate}
|
|
6281
|
+
.visibleStart=${this._viewport.visibleStart}
|
|
6282
|
+
.visibleEnd=${this._viewport.visibleEnd}
|
|
6283
|
+
.originX=${clipLeft}
|
|
6284
|
+
?selected=${t.trackId === this._selectedTrackId}
|
|
6285
|
+
></daw-piano-roll>` : t.descriptor?.renderMode === "spectrogram" ? channels.map(
|
|
6286
|
+
(_chPeaks, chIdx) => html10`<daw-spectrogram
|
|
6287
|
+
style="position:absolute;left:0;top:${hdrH + chIdx * chH}px;height:${chH}px;width:${peakData?.length ?? width}px;"
|
|
6288
|
+
.clipId=${clip.id}
|
|
6289
|
+
.trackId=${t.trackId}
|
|
6290
|
+
.channelIndex=${chIdx}
|
|
6291
|
+
.length=${peakData?.length ?? width}
|
|
6292
|
+
.waveHeight=${chH}
|
|
6293
|
+
.samplesPerPixel=${this._renderSpp}
|
|
6294
|
+
.sampleRate=${this.effectiveSampleRate}
|
|
6295
|
+
.clipOffsetSeconds=${(clip.offsetSamples ?? 0) / this.effectiveSampleRate}
|
|
6296
|
+
.visibleStart=${this._viewport.visibleStart}
|
|
6297
|
+
.visibleEnd=${this._viewport.visibleEnd}
|
|
6298
|
+
.originX=${clipLeft}
|
|
6299
|
+
></daw-spectrogram>`
|
|
6300
|
+
) : channels.map(
|
|
6301
|
+
(chPeaks, chIdx) => html10` <daw-waveform
|
|
6302
|
+
style="position:absolute;left:0;top:${hdrH + chIdx * chH}px;"
|
|
6303
|
+
.peaks=${chPeaks}
|
|
6304
|
+
.length=${peakData?.length ?? width}
|
|
6305
|
+
.waveHeight=${chH}
|
|
6306
|
+
.barWidth=${this.barWidth}
|
|
6307
|
+
.barGap=${this.barGap}
|
|
6308
|
+
.visibleStart=${this._viewport.visibleStart}
|
|
6309
|
+
.visibleEnd=${this._viewport.visibleEnd}
|
|
6310
|
+
.originX=${clipLeft}
|
|
6311
|
+
.segments=${clipSegments}
|
|
6312
|
+
></daw-waveform>`
|
|
6313
|
+
)}
|
|
6314
|
+
${this.interactiveClips ? html10` <div
|
|
6315
|
+
class="clip-boundary"
|
|
6316
|
+
data-boundary-edge="left"
|
|
6317
|
+
data-clip-id=${clip.id}
|
|
6318
|
+
data-track-id=${t.trackId}
|
|
6319
|
+
></div>
|
|
6320
|
+
<div
|
|
6321
|
+
class="clip-boundary"
|
|
6322
|
+
data-boundary-edge="right"
|
|
6323
|
+
data-clip-id=${clip.id}
|
|
6324
|
+
data-track-id=${t.trackId}
|
|
6325
|
+
></div>` : ""}
|
|
6326
|
+
</div>`;
|
|
5892
6327
|
})}
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
6328
|
+
${this._renderRecordingPreview(t.trackId, channelHeight)}
|
|
6329
|
+
</div>
|
|
6330
|
+
`;
|
|
5896
6331
|
})}
|
|
6332
|
+
</div>
|
|
5897
6333
|
</div>
|
|
5898
6334
|
</div>
|
|
5899
6335
|
<slot></slot>
|
|
@@ -5902,21 +6338,48 @@ var DawEditorElement = class extends LitElement10 {
|
|
|
5902
6338
|
};
|
|
5903
6339
|
DawEditorElement.styles = [
|
|
5904
6340
|
hostStyles,
|
|
5905
|
-
|
|
6341
|
+
css10`
|
|
5906
6342
|
:host {
|
|
5907
6343
|
display: flex;
|
|
6344
|
+
flex-direction: column;
|
|
5908
6345
|
position: relative;
|
|
5909
6346
|
background: var(--daw-background, #1a1a2e);
|
|
5910
6347
|
overflow: hidden;
|
|
5911
6348
|
}
|
|
5912
|
-
.
|
|
6349
|
+
.header-row {
|
|
6350
|
+
display: flex;
|
|
6351
|
+
flex-shrink: 0;
|
|
6352
|
+
}
|
|
6353
|
+
.ruler-gap {
|
|
6354
|
+
flex-shrink: 0;
|
|
6355
|
+
width: var(--daw-controls-width, 180px);
|
|
6356
|
+
}
|
|
6357
|
+
.ruler-viewport {
|
|
6358
|
+
flex: 1;
|
|
6359
|
+
position: relative;
|
|
6360
|
+
overflow: hidden;
|
|
6361
|
+
cursor: text;
|
|
6362
|
+
}
|
|
6363
|
+
.ruler-content {
|
|
6364
|
+
will-change: transform;
|
|
6365
|
+
}
|
|
6366
|
+
.body {
|
|
6367
|
+
flex: 1;
|
|
6368
|
+
min-height: 0;
|
|
6369
|
+
display: flex;
|
|
6370
|
+
}
|
|
6371
|
+
.controls-viewport {
|
|
5913
6372
|
flex-shrink: 0;
|
|
5914
6373
|
width: var(--daw-controls-width, 180px);
|
|
6374
|
+
overflow: hidden;
|
|
6375
|
+
}
|
|
6376
|
+
.controls-column {
|
|
6377
|
+
will-change: transform;
|
|
5915
6378
|
}
|
|
5916
6379
|
.scroll-area {
|
|
5917
6380
|
flex: 1;
|
|
5918
|
-
overflow
|
|
5919
|
-
overflow-
|
|
6381
|
+
overflow: auto;
|
|
6382
|
+
overflow-anchor: none;
|
|
5920
6383
|
min-height: var(--daw-min-height, 200px);
|
|
5921
6384
|
}
|
|
5922
6385
|
.timeline {
|
|
@@ -5926,6 +6389,7 @@ DawEditorElement.styles = [
|
|
|
5926
6389
|
}
|
|
5927
6390
|
.track-row {
|
|
5928
6391
|
position: relative;
|
|
6392
|
+
box-sizing: border-box;
|
|
5929
6393
|
background: var(--daw-track-background, #16213e);
|
|
5930
6394
|
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
|
5931
6395
|
}
|
|
@@ -5950,70 +6414,70 @@ DawEditorElement.styles = [
|
|
|
5950
6414
|
];
|
|
5951
6415
|
DawEditorElement._CONTROL_PROPS = /* @__PURE__ */ new Set(["volume", "pan", "muted", "soloed"]);
|
|
5952
6416
|
__decorateClass([
|
|
5953
|
-
|
|
6417
|
+
property9({ type: Number, attribute: "samples-per-pixel", noAccessor: true })
|
|
5954
6418
|
], DawEditorElement.prototype, "samplesPerPixel", 1);
|
|
5955
6419
|
__decorateClass([
|
|
5956
|
-
|
|
6420
|
+
property9({ type: Number, attribute: "wave-height" })
|
|
5957
6421
|
], DawEditorElement.prototype, "waveHeight", 2);
|
|
5958
6422
|
__decorateClass([
|
|
5959
|
-
|
|
6423
|
+
property9({ type: Boolean })
|
|
5960
6424
|
], DawEditorElement.prototype, "timescale", 2);
|
|
5961
6425
|
__decorateClass([
|
|
5962
|
-
|
|
6426
|
+
property9({ type: Boolean })
|
|
5963
6427
|
], DawEditorElement.prototype, "mono", 2);
|
|
5964
6428
|
__decorateClass([
|
|
5965
|
-
|
|
6429
|
+
property9({ type: Number, attribute: "bar-width" })
|
|
5966
6430
|
], DawEditorElement.prototype, "barWidth", 2);
|
|
5967
6431
|
__decorateClass([
|
|
5968
|
-
|
|
6432
|
+
property9({ type: Number, attribute: "bar-gap" })
|
|
5969
6433
|
], DawEditorElement.prototype, "barGap", 2);
|
|
5970
6434
|
__decorateClass([
|
|
5971
|
-
|
|
6435
|
+
property9({ type: Boolean, attribute: "file-drop" })
|
|
5972
6436
|
], DawEditorElement.prototype, "fileDrop", 2);
|
|
5973
6437
|
__decorateClass([
|
|
5974
|
-
|
|
6438
|
+
property9({ type: Boolean, attribute: "clip-headers" })
|
|
5975
6439
|
], DawEditorElement.prototype, "clipHeaders", 2);
|
|
5976
6440
|
__decorateClass([
|
|
5977
|
-
|
|
6441
|
+
property9({ type: Number, attribute: "clip-header-height" })
|
|
5978
6442
|
], DawEditorElement.prototype, "clipHeaderHeight", 2);
|
|
5979
6443
|
__decorateClass([
|
|
5980
|
-
|
|
6444
|
+
property9({ type: Boolean, attribute: "interactive-clips" })
|
|
5981
6445
|
], DawEditorElement.prototype, "interactiveClips", 2);
|
|
5982
6446
|
__decorateClass([
|
|
5983
|
-
|
|
6447
|
+
property9({ type: Boolean, attribute: "indefinite-playback" })
|
|
5984
6448
|
], DawEditorElement.prototype, "indefinitePlayback", 2);
|
|
5985
6449
|
__decorateClass([
|
|
5986
|
-
|
|
6450
|
+
property9({ attribute: false, noAccessor: true })
|
|
5987
6451
|
], DawEditorElement.prototype, "spectrogramConfig", 1);
|
|
5988
6452
|
__decorateClass([
|
|
5989
|
-
|
|
6453
|
+
property9({ attribute: false, noAccessor: true })
|
|
5990
6454
|
], DawEditorElement.prototype, "spectrogramColorMap", 1);
|
|
5991
6455
|
__decorateClass([
|
|
5992
|
-
|
|
6456
|
+
property9({ type: String, attribute: "scale-mode" })
|
|
5993
6457
|
], DawEditorElement.prototype, "scaleMode", 2);
|
|
5994
6458
|
__decorateClass([
|
|
5995
|
-
|
|
6459
|
+
property9({ type: Number, attribute: "ticks-per-pixel", noAccessor: true })
|
|
5996
6460
|
], DawEditorElement.prototype, "ticksPerPixel", 1);
|
|
5997
6461
|
__decorateClass([
|
|
5998
|
-
|
|
6462
|
+
property9({ type: Number, noAccessor: true })
|
|
5999
6463
|
], DawEditorElement.prototype, "bpm", 1);
|
|
6000
6464
|
__decorateClass([
|
|
6001
|
-
|
|
6465
|
+
property9({ attribute: false })
|
|
6002
6466
|
], DawEditorElement.prototype, "timeSignature", 2);
|
|
6003
6467
|
__decorateClass([
|
|
6004
|
-
|
|
6468
|
+
property9({ attribute: false })
|
|
6005
6469
|
], DawEditorElement.prototype, "meterEntries", 2);
|
|
6006
6470
|
__decorateClass([
|
|
6007
|
-
|
|
6471
|
+
property9({ type: Number, noAccessor: true })
|
|
6008
6472
|
], DawEditorElement.prototype, "ppqn", 1);
|
|
6009
6473
|
__decorateClass([
|
|
6010
|
-
|
|
6474
|
+
property9({ type: String, attribute: "snap-to" })
|
|
6011
6475
|
], DawEditorElement.prototype, "snapTo", 2);
|
|
6012
6476
|
__decorateClass([
|
|
6013
|
-
|
|
6477
|
+
property9({ attribute: false })
|
|
6014
6478
|
], DawEditorElement.prototype, "secondsToTicks", 2);
|
|
6015
6479
|
__decorateClass([
|
|
6016
|
-
|
|
6480
|
+
property9({ attribute: false })
|
|
6017
6481
|
], DawEditorElement.prototype, "ticksToSeconds", 2);
|
|
6018
6482
|
__decorateClass([
|
|
6019
6483
|
state3()
|
|
@@ -6037,246 +6501,15 @@ __decorateClass([
|
|
|
6037
6501
|
state3()
|
|
6038
6502
|
], DawEditorElement.prototype, "_dragOver", 2);
|
|
6039
6503
|
__decorateClass([
|
|
6040
|
-
|
|
6504
|
+
property9({ attribute: false })
|
|
6041
6505
|
], DawEditorElement.prototype, "adapter", 1);
|
|
6042
6506
|
__decorateClass([
|
|
6043
|
-
|
|
6507
|
+
property9({ attribute: "eager-resume" })
|
|
6044
6508
|
], DawEditorElement.prototype, "eagerResume", 2);
|
|
6045
6509
|
DawEditorElement = __decorateClass([
|
|
6046
|
-
|
|
6510
|
+
customElement13("daw-editor")
|
|
6047
6511
|
], DawEditorElement);
|
|
6048
6512
|
|
|
6049
|
-
// src/elements/daw-ruler.ts
|
|
6050
|
-
import { LitElement as LitElement11, html as html10, css as css10 } from "lit";
|
|
6051
|
-
import { customElement as customElement13, property as property9 } from "lit/decorators.js";
|
|
6052
|
-
|
|
6053
|
-
// src/utils/time-format.ts
|
|
6054
|
-
function formatTime(milliseconds) {
|
|
6055
|
-
const seconds = Math.floor(milliseconds / 1e3);
|
|
6056
|
-
const s = seconds % 60;
|
|
6057
|
-
const m = (seconds - s) / 60;
|
|
6058
|
-
return `${m}:${String(s).padStart(2, "0")}`;
|
|
6059
|
-
}
|
|
6060
|
-
|
|
6061
|
-
// src/utils/smart-scale.ts
|
|
6062
|
-
var timeinfo = /* @__PURE__ */ new Map([
|
|
6063
|
-
[700, { marker: 1e3, bigStep: 500, smallStep: 100 }],
|
|
6064
|
-
[1500, { marker: 2e3, bigStep: 1e3, smallStep: 200 }],
|
|
6065
|
-
[2500, { marker: 2e3, bigStep: 1e3, smallStep: 500 }],
|
|
6066
|
-
[5e3, { marker: 5e3, bigStep: 1e3, smallStep: 500 }],
|
|
6067
|
-
[1e4, { marker: 1e4, bigStep: 5e3, smallStep: 1e3 }],
|
|
6068
|
-
[12e3, { marker: 15e3, bigStep: 5e3, smallStep: 1e3 }],
|
|
6069
|
-
[Infinity, { marker: 3e4, bigStep: 1e4, smallStep: 5e3 }]
|
|
6070
|
-
]);
|
|
6071
|
-
function getScaleInfo(samplesPerPixel) {
|
|
6072
|
-
for (const [resolution, config] of timeinfo) {
|
|
6073
|
-
if (samplesPerPixel < resolution) {
|
|
6074
|
-
return config;
|
|
6075
|
-
}
|
|
6076
|
-
}
|
|
6077
|
-
return { marker: 3e4, bigStep: 1e4, smallStep: 5e3 };
|
|
6078
|
-
}
|
|
6079
|
-
function computeTemporalTicks(samplesPerPixel, sampleRate, duration, rulerHeight) {
|
|
6080
|
-
const widthX = Math.ceil(duration * sampleRate / samplesPerPixel);
|
|
6081
|
-
const config = getScaleInfo(samplesPerPixel);
|
|
6082
|
-
const { marker, bigStep, smallStep } = config;
|
|
6083
|
-
const canvasInfo = /* @__PURE__ */ new Map();
|
|
6084
|
-
const labels = [];
|
|
6085
|
-
const pixPerSec = sampleRate / samplesPerPixel;
|
|
6086
|
-
for (let counter = 0; ; counter += smallStep) {
|
|
6087
|
-
const pix = Math.floor(counter / 1e3 * pixPerSec);
|
|
6088
|
-
if (pix >= widthX) break;
|
|
6089
|
-
if (counter % marker === 0) {
|
|
6090
|
-
canvasInfo.set(pix, rulerHeight);
|
|
6091
|
-
labels.push({ pix, text: formatTime(counter) });
|
|
6092
|
-
} else if (counter % bigStep === 0) {
|
|
6093
|
-
canvasInfo.set(pix, Math.floor(rulerHeight / 2));
|
|
6094
|
-
} else if (counter % smallStep === 0) {
|
|
6095
|
-
canvasInfo.set(pix, Math.floor(rulerHeight / 5));
|
|
6096
|
-
}
|
|
6097
|
-
}
|
|
6098
|
-
return { widthX, canvasInfo, labels };
|
|
6099
|
-
}
|
|
6100
|
-
|
|
6101
|
-
// src/elements/daw-ruler.ts
|
|
6102
|
-
var MAX_CANVAS_WIDTH4 = 1e3;
|
|
6103
|
-
var DawRulerElement = class extends LitElement11 {
|
|
6104
|
-
constructor() {
|
|
6105
|
-
super(...arguments);
|
|
6106
|
-
this.samplesPerPixel = 1024;
|
|
6107
|
-
this.sampleRate = 48e3;
|
|
6108
|
-
this.duration = 0;
|
|
6109
|
-
this.rulerHeight = 30;
|
|
6110
|
-
this.scaleMode = "temporal";
|
|
6111
|
-
this.ticksPerPixel = 4;
|
|
6112
|
-
this.meterEntries = [
|
|
6113
|
-
{ tick: 0, numerator: 4, denominator: 4 }
|
|
6114
|
-
];
|
|
6115
|
-
this.ppqn = 960;
|
|
6116
|
-
this.totalWidth = 0;
|
|
6117
|
-
this._tickData = null;
|
|
6118
|
-
this._musicalTickData = null;
|
|
6119
|
-
}
|
|
6120
|
-
willUpdate() {
|
|
6121
|
-
if (this.scaleMode === "beats" && this.totalWidth > 0) {
|
|
6122
|
-
this._musicalTickData = getCachedMusicalTicks({
|
|
6123
|
-
meterEntries: this.meterEntries,
|
|
6124
|
-
ticksPerPixel: this.ticksPerPixel,
|
|
6125
|
-
startPixel: 0,
|
|
6126
|
-
endPixel: this.totalWidth,
|
|
6127
|
-
ppqn: this.ppqn
|
|
6128
|
-
});
|
|
6129
|
-
this._tickData = null;
|
|
6130
|
-
} else if (this.duration > 0 || this.totalWidth > 0) {
|
|
6131
|
-
const widthDerivedDuration = this.totalWidth * this.samplesPerPixel / this.sampleRate;
|
|
6132
|
-
const effectiveDuration = Math.max(this.duration, widthDerivedDuration);
|
|
6133
|
-
this._musicalTickData = null;
|
|
6134
|
-
this._tickData = computeTemporalTicks(
|
|
6135
|
-
this.samplesPerPixel,
|
|
6136
|
-
this.sampleRate,
|
|
6137
|
-
effectiveDuration,
|
|
6138
|
-
this.rulerHeight
|
|
6139
|
-
);
|
|
6140
|
-
} else {
|
|
6141
|
-
this._musicalTickData = null;
|
|
6142
|
-
this._tickData = null;
|
|
6143
|
-
}
|
|
6144
|
-
}
|
|
6145
|
-
render() {
|
|
6146
|
-
const widthX = this.scaleMode === "beats" ? this.totalWidth : this._tickData?.widthX ?? 0;
|
|
6147
|
-
if (widthX <= 0) return html10``;
|
|
6148
|
-
const totalChunks = Math.ceil(widthX / MAX_CANVAS_WIDTH4);
|
|
6149
|
-
const indices = Array.from({ length: totalChunks }, (_, i) => i);
|
|
6150
|
-
const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
|
|
6151
|
-
const beatsLabels = this.scaleMode === "beats" ? this._musicalTickData?.ticks.filter((t) => t.label) ?? [] : [];
|
|
6152
|
-
const temporalLabels = this.scaleMode !== "beats" ? this._tickData?.labels ?? [] : [];
|
|
6153
|
-
return html10`
|
|
6154
|
-
<div class="container" style="width: ${widthX}px; height: ${this.rulerHeight}px;">
|
|
6155
|
-
${indices.map((i) => {
|
|
6156
|
-
const width = Math.min(MAX_CANVAS_WIDTH4, widthX - i * MAX_CANVAS_WIDTH4);
|
|
6157
|
-
return html10`
|
|
6158
|
-
<canvas
|
|
6159
|
-
data-index=${i}
|
|
6160
|
-
width=${width * dpr}
|
|
6161
|
-
height=${this.rulerHeight * dpr}
|
|
6162
|
-
style="left: ${i * MAX_CANVAS_WIDTH4}px; width: ${width}px; height: ${this.rulerHeight}px;"
|
|
6163
|
-
></canvas>
|
|
6164
|
-
`;
|
|
6165
|
-
})}
|
|
6166
|
-
${this.scaleMode === "beats" ? beatsLabels.map(
|
|
6167
|
-
(t) => html10`<span
|
|
6168
|
-
class="label ${t.pixel > 0 ? "centered" : ""}"
|
|
6169
|
-
style="left: ${t.pixel > 0 ? t.pixel : t.pixel + 4}px;"
|
|
6170
|
-
>${t.label}</span
|
|
6171
|
-
>`
|
|
6172
|
-
) : temporalLabels.map(
|
|
6173
|
-
({ pix, text }) => html10`<span class="label" style="left: ${pix + 4}px;">${text}</span>`
|
|
6174
|
-
)}
|
|
6175
|
-
</div>
|
|
6176
|
-
`;
|
|
6177
|
-
}
|
|
6178
|
-
updated() {
|
|
6179
|
-
this._drawTicks();
|
|
6180
|
-
}
|
|
6181
|
-
_drawTicks() {
|
|
6182
|
-
const canvases = this.shadowRoot?.querySelectorAll("canvas");
|
|
6183
|
-
if (!canvases) return;
|
|
6184
|
-
const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
|
|
6185
|
-
const rulerColor = getComputedStyle(this).getPropertyValue("--daw-ruler-color").trim() || "#c49a6c";
|
|
6186
|
-
const widthX = this.scaleMode === "beats" ? this.totalWidth : this._tickData?.widthX ?? 0;
|
|
6187
|
-
for (const canvas of canvases) {
|
|
6188
|
-
const idx = Number(canvas.dataset.index);
|
|
6189
|
-
const ctx = canvas.getContext("2d");
|
|
6190
|
-
if (!ctx) continue;
|
|
6191
|
-
const canvasWidth = Math.min(MAX_CANVAS_WIDTH4, widthX - idx * MAX_CANVAS_WIDTH4);
|
|
6192
|
-
const globalOffset = idx * MAX_CANVAS_WIDTH4;
|
|
6193
|
-
ctx.resetTransform();
|
|
6194
|
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
6195
|
-
ctx.scale(dpr, dpr);
|
|
6196
|
-
ctx.strokeStyle = rulerColor;
|
|
6197
|
-
ctx.lineWidth = 1;
|
|
6198
|
-
if (this.scaleMode === "beats" && this._musicalTickData) {
|
|
6199
|
-
const h = this.rulerHeight;
|
|
6200
|
-
for (const tick of this._musicalTickData.ticks) {
|
|
6201
|
-
const localX = tick.pixel - globalOffset;
|
|
6202
|
-
if (localX < 0 || localX >= canvasWidth) continue;
|
|
6203
|
-
const tickH = tick.type === "major" ? h * 0.6 : tick.type === "minor" ? h * 0.35 : h * 0.15;
|
|
6204
|
-
ctx.globalAlpha = tick.type === "major" ? 1 : 0.5;
|
|
6205
|
-
ctx.beginPath();
|
|
6206
|
-
ctx.moveTo(localX + 0.5, h);
|
|
6207
|
-
ctx.lineTo(localX + 0.5, h - tickH);
|
|
6208
|
-
ctx.stroke();
|
|
6209
|
-
}
|
|
6210
|
-
ctx.globalAlpha = 1;
|
|
6211
|
-
} else if (this._tickData) {
|
|
6212
|
-
for (const [pix, height] of this._tickData.canvasInfo) {
|
|
6213
|
-
const localX = pix - globalOffset;
|
|
6214
|
-
if (localX < 0 || localX >= canvasWidth) continue;
|
|
6215
|
-
ctx.beginPath();
|
|
6216
|
-
ctx.moveTo(localX + 0.5, this.rulerHeight);
|
|
6217
|
-
ctx.lineTo(localX + 0.5, this.rulerHeight - height);
|
|
6218
|
-
ctx.stroke();
|
|
6219
|
-
}
|
|
6220
|
-
}
|
|
6221
|
-
}
|
|
6222
|
-
}
|
|
6223
|
-
};
|
|
6224
|
-
DawRulerElement.styles = css10`
|
|
6225
|
-
:host {
|
|
6226
|
-
display: block;
|
|
6227
|
-
position: relative;
|
|
6228
|
-
background: var(--daw-ruler-background, #0f0f1a);
|
|
6229
|
-
}
|
|
6230
|
-
.container {
|
|
6231
|
-
position: relative;
|
|
6232
|
-
}
|
|
6233
|
-
canvas {
|
|
6234
|
-
position: absolute;
|
|
6235
|
-
top: 0;
|
|
6236
|
-
}
|
|
6237
|
-
.label {
|
|
6238
|
-
position: absolute;
|
|
6239
|
-
font-size: 0.7rem;
|
|
6240
|
-
line-height: 1;
|
|
6241
|
-
white-space: nowrap;
|
|
6242
|
-
color: var(--daw-ruler-color, #c49a6c);
|
|
6243
|
-
top: 1px;
|
|
6244
|
-
}
|
|
6245
|
-
.label.centered {
|
|
6246
|
-
transform: translateX(-50%);
|
|
6247
|
-
}
|
|
6248
|
-
`;
|
|
6249
|
-
__decorateClass([
|
|
6250
|
-
property9({ type: Number, attribute: false })
|
|
6251
|
-
], DawRulerElement.prototype, "samplesPerPixel", 2);
|
|
6252
|
-
__decorateClass([
|
|
6253
|
-
property9({ type: Number, attribute: false })
|
|
6254
|
-
], DawRulerElement.prototype, "sampleRate", 2);
|
|
6255
|
-
__decorateClass([
|
|
6256
|
-
property9({ type: Number, attribute: false })
|
|
6257
|
-
], DawRulerElement.prototype, "duration", 2);
|
|
6258
|
-
__decorateClass([
|
|
6259
|
-
property9({ type: Number, attribute: false })
|
|
6260
|
-
], DawRulerElement.prototype, "rulerHeight", 2);
|
|
6261
|
-
__decorateClass([
|
|
6262
|
-
property9({ type: String, attribute: false })
|
|
6263
|
-
], DawRulerElement.prototype, "scaleMode", 2);
|
|
6264
|
-
__decorateClass([
|
|
6265
|
-
property9({ type: Number, attribute: false })
|
|
6266
|
-
], DawRulerElement.prototype, "ticksPerPixel", 2);
|
|
6267
|
-
__decorateClass([
|
|
6268
|
-
property9({ attribute: false })
|
|
6269
|
-
], DawRulerElement.prototype, "meterEntries", 2);
|
|
6270
|
-
__decorateClass([
|
|
6271
|
-
property9({ type: Number, attribute: false })
|
|
6272
|
-
], DawRulerElement.prototype, "ppqn", 2);
|
|
6273
|
-
__decorateClass([
|
|
6274
|
-
property9({ type: Number, attribute: false })
|
|
6275
|
-
], DawRulerElement.prototype, "totalWidth", 2);
|
|
6276
|
-
DawRulerElement = __decorateClass([
|
|
6277
|
-
customElement13("daw-ruler")
|
|
6278
|
-
], DawRulerElement);
|
|
6279
|
-
|
|
6280
6513
|
// src/elements/daw-selection.ts
|
|
6281
6514
|
import { LitElement as LitElement12, html as html11, css as css11 } from "lit";
|
|
6282
6515
|
import { customElement as customElement14, property as property10 } from "lit/decorators.js";
|