@onjmin/dtm 0.1.57 → 0.1.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +307 -85
- package/dist/index.mjs +307 -85
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -5020,8 +5020,6 @@ var DAW_CSS = `
|
|
|
5020
5020
|
max-height: 180px;
|
|
5021
5021
|
overflow-y: auto;
|
|
5022
5022
|
padding: 8px 10px 10px;
|
|
5023
|
-
overflow-x: auto;
|
|
5024
|
-
white-space: nowrap;
|
|
5025
5023
|
scrollbar-width: none;
|
|
5026
5024
|
display: flex;
|
|
5027
5025
|
flex-direction: column;
|
|
@@ -5050,6 +5048,7 @@ var DAW_CSS = `
|
|
|
5050
5048
|
.dtm-cp-bar {
|
|
5051
5049
|
display: flex;
|
|
5052
5050
|
align-items: center;
|
|
5051
|
+
flex-wrap: wrap;
|
|
5053
5052
|
gap: 2px;
|
|
5054
5053
|
margin-top: 2px;
|
|
5055
5054
|
}
|
|
@@ -6752,11 +6751,13 @@ var loadDrumFont = (ctx, pitch) => {
|
|
|
6752
6751
|
_drumLoading.set(pitch, p);
|
|
6753
6752
|
return p;
|
|
6754
6753
|
};
|
|
6754
|
+
var BAR_SEP = /[|ll→]/;
|
|
6755
|
+
var NON_EVENT_RE = /^[=_]$|^N\.C\.$|^N$/i;
|
|
6755
6756
|
var buildDisplayLines = (chords, eventsCount) => {
|
|
6756
6757
|
const rawLines = chords.split("\n").map((l) => l.trim()).filter((l) => l);
|
|
6757
6758
|
const displayLines = [];
|
|
6758
6759
|
let eventCounter = 0;
|
|
6759
|
-
let colorIdx =
|
|
6760
|
+
let colorIdx = 0;
|
|
6760
6761
|
for (const line of rawLines) {
|
|
6761
6762
|
if (/^#/.test(line)) {
|
|
6762
6763
|
const label = line.replace(/^#\s*/, "").trim();
|
|
@@ -6764,19 +6765,21 @@ var buildDisplayLines = (chords, eventsCount) => {
|
|
|
6764
6765
|
if (/^tone\s*=/i.test(label)) continue;
|
|
6765
6766
|
if (/^instrument\s*=/i.test(label)) continue;
|
|
6766
6767
|
if (/^metronome/i.test(label)) continue;
|
|
6767
|
-
colorIdx++;
|
|
6768
|
+
if (displayLines.length > 0 || eventCounter > 0) colorIdx++;
|
|
6768
6769
|
displayLines.push({
|
|
6769
6770
|
type: "section",
|
|
6770
6771
|
section: label,
|
|
6771
|
-
colorIdx
|
|
6772
|
+
colorIdx
|
|
6772
6773
|
});
|
|
6773
6774
|
continue;
|
|
6774
6775
|
}
|
|
6775
|
-
const segments = line.split(
|
|
6776
|
-
if (segments.length
|
|
6776
|
+
const segments = line.split(BAR_SEP);
|
|
6777
|
+
if (segments.length === 0) continue;
|
|
6778
|
+
const hasMultiSeg = segments.length > 1;
|
|
6777
6779
|
const parts = [];
|
|
6778
6780
|
for (let i = 0; i < segments.length; i++) {
|
|
6779
|
-
if (i > 0)
|
|
6781
|
+
if (hasMultiSeg && i > 0)
|
|
6782
|
+
parts.push({ text: "|", isChord: false, eventIdx: -1 });
|
|
6780
6783
|
const bar = segments[i].trim();
|
|
6781
6784
|
if (!bar) continue;
|
|
6782
6785
|
const splitAt = [];
|
|
@@ -6799,7 +6802,7 @@ var buildDisplayLines = (chords, eventsCount) => {
|
|
|
6799
6802
|
splitAt.push(j + 1);
|
|
6800
6803
|
continue;
|
|
6801
6804
|
}
|
|
6802
|
-
if (/^[A-G]
|
|
6805
|
+
if (/^[A-G]$/.test(char)) {
|
|
6803
6806
|
const prev = bar[j - 1];
|
|
6804
6807
|
const prev2 = bar.slice(Math.max(0, j - 2), j);
|
|
6805
6808
|
if (prev === "/" || prev2.toLowerCase() === "on") continue;
|
|
@@ -6808,12 +6811,13 @@ var buildDisplayLines = (chords, eventsCount) => {
|
|
|
6808
6811
|
}
|
|
6809
6812
|
const uniqueSplitAt = Array.from(new Set(splitAt)).filter((idx) => idx >= 0 && idx < bar.length).sort((a, b) => a - b);
|
|
6810
6813
|
if (uniqueSplitAt.length === 0) {
|
|
6814
|
+
const isEvent = !NON_EVENT_RE.test(bar);
|
|
6811
6815
|
parts.push({
|
|
6812
6816
|
text: bar,
|
|
6813
6817
|
isChord: true,
|
|
6814
|
-
eventIdx: eventCounter < eventsCount ? eventCounter : -1
|
|
6818
|
+
eventIdx: isEvent && eventCounter < eventsCount ? eventCounter : -1
|
|
6815
6819
|
});
|
|
6816
|
-
eventCounter++;
|
|
6820
|
+
if (isEvent) eventCounter++;
|
|
6817
6821
|
continue;
|
|
6818
6822
|
}
|
|
6819
6823
|
for (let ci = 0; ci < uniqueSplitAt.length; ci++) {
|
|
@@ -6822,19 +6826,20 @@ var buildDisplayLines = (chords, eventsCount) => {
|
|
|
6822
6826
|
const end = ci < uniqueSplitAt.length - 1 ? uniqueSplitAt[ci + 1] : bar.length;
|
|
6823
6827
|
const symbol = bar.slice(start, end).trim();
|
|
6824
6828
|
if (symbol) {
|
|
6829
|
+
const isEvent = !NON_EVENT_RE.test(symbol);
|
|
6825
6830
|
parts.push({
|
|
6826
6831
|
text: symbol,
|
|
6827
6832
|
isChord: true,
|
|
6828
|
-
eventIdx: eventCounter < eventsCount ? eventCounter : -1
|
|
6833
|
+
eventIdx: isEvent && eventCounter < eventsCount ? eventCounter : -1
|
|
6829
6834
|
});
|
|
6830
|
-
eventCounter++;
|
|
6835
|
+
if (isEvent) eventCounter++;
|
|
6831
6836
|
}
|
|
6832
6837
|
}
|
|
6833
6838
|
}
|
|
6834
6839
|
if (parts.length > 0) {
|
|
6835
6840
|
displayLines.push({
|
|
6836
6841
|
type: "bar",
|
|
6837
|
-
colorIdx
|
|
6842
|
+
colorIdx,
|
|
6838
6843
|
parts
|
|
6839
6844
|
});
|
|
6840
6845
|
}
|
|
@@ -8768,6 +8773,18 @@ var MidiSearchClient = class {
|
|
|
8768
8773
|
if (!res.ok) throw new Error(`picotune fetch failed: ${res.status}`);
|
|
8769
8774
|
return res.arrayBuffer();
|
|
8770
8775
|
}
|
|
8776
|
+
async searchRechord(word) {
|
|
8777
|
+
if (!this.enabled) return [];
|
|
8778
|
+
const qs = new URLSearchParams();
|
|
8779
|
+
qs.set("word", word);
|
|
8780
|
+
qs.set("guest", "true");
|
|
8781
|
+
const url2 = `${this.baseUrl}/rechord/scores?${qs.toString()}`;
|
|
8782
|
+
const res = await fetch(url2, { headers: this.headers() });
|
|
8783
|
+
if (!res.ok) throw new Error(`rechord search failed: ${res.status}`);
|
|
8784
|
+
const body = await res.json();
|
|
8785
|
+
const list = body.result ?? body.data ?? body;
|
|
8786
|
+
return Array.isArray(list) ? list : [];
|
|
8787
|
+
}
|
|
8771
8788
|
};
|
|
8772
8789
|
|
|
8773
8790
|
// src/linked-list.ts
|
|
@@ -11192,6 +11209,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
11192
11209
|
<div style="display: inline-flex; align-items: center; gap: 6px;">
|
|
11193
11210
|
<span class="dtm-label">\u548C\u97F3</span>
|
|
11194
11211
|
<button class="dtm-infobtn" data-dtm="chord-info" title="\u30B3\u30FC\u30C9\u9032\u884C\u306E\u66F8\u304D\u65B9\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
11212
|
+
${showMidiSearch ? `<button class="dtm-btn dtm-btn--ghost" data-dtm="chord-search" title="\u30B3\u30FC\u30C9\u9032\u884C\u691C\u7D22" style="min-height: 24px; min-width: auto; height: 24px; padding: 0 6px; font-size: 11px; display: inline-flex; align-items: center;">\u30B3\u30FC\u30C9\u691C\u7D22</button>` : ""}
|
|
11195
11213
|
</div>
|
|
11196
11214
|
<select class="dtm-select" data-dtm="chord-pattern">
|
|
11197
11215
|
<option value="block">\u30D6\u30ED\u30C3\u30AF</option>
|
|
@@ -11227,6 +11245,14 @@ var mountDAW = (target, options = {}) => {
|
|
|
11227
11245
|
save();
|
|
11228
11246
|
applyChord();
|
|
11229
11247
|
});
|
|
11248
|
+
const searchChordBtn = div.querySelector(
|
|
11249
|
+
'[data-dtm="chord-search"]'
|
|
11250
|
+
);
|
|
11251
|
+
if (searchChordBtn) {
|
|
11252
|
+
searchChordBtn.addEventListener("click", () => {
|
|
11253
|
+
openChordSearchModal(input);
|
|
11254
|
+
});
|
|
11255
|
+
}
|
|
11230
11256
|
}
|
|
11231
11257
|
};
|
|
11232
11258
|
const switchTrack = (id) => {
|
|
@@ -12090,6 +12116,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
12090
12116
|
searchPreviewBtn = null;
|
|
12091
12117
|
}
|
|
12092
12118
|
};
|
|
12119
|
+
let mmlSearchCache = null;
|
|
12120
|
+
let chordSearchCache = null;
|
|
12093
12121
|
const wireMidiSearch = () => {
|
|
12094
12122
|
if (!midiSearchClient) return;
|
|
12095
12123
|
refs.midiSearchOpenBtn.addEventListener("click", () => {
|
|
@@ -12100,6 +12128,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
12100
12128
|
<input type="text" class="dtm-input dtm-grow" data-dtm="modal-midi-search-input" placeholder="\u66F2\u540D\u3067MML\u691C\u7D22" style="min-width:0">
|
|
12101
12129
|
<button class="dtm-btn dtm-btn--primary" data-dtm="modal-midi-search-btn" style="flex-shrink:0">\u691C\u7D22</button>
|
|
12102
12130
|
</div>
|
|
12131
|
+
<div data-dtm="modal-midi-search-status" style="font-size:11px;color:rgba(255,255,255,0.5);min-height:1.4em"></div>
|
|
12103
12132
|
<div class="dtm-row" data-dtm="modal-midi-search-results" style="flex-direction:column;align-items:stretch;gap:4px"></div>
|
|
12104
12133
|
`
|
|
12105
12134
|
);
|
|
@@ -12109,9 +12138,17 @@ var mountDAW = (target, options = {}) => {
|
|
|
12109
12138
|
const searchBtn = refs.modalBody.querySelector(
|
|
12110
12139
|
'[data-dtm="modal-midi-search-btn"]'
|
|
12111
12140
|
);
|
|
12141
|
+
const statusEl = refs.modalBody.querySelector(
|
|
12142
|
+
'[data-dtm="modal-midi-search-status"]'
|
|
12143
|
+
);
|
|
12112
12144
|
const results = refs.modalBody.querySelector(
|
|
12113
12145
|
'[data-dtm="modal-midi-search-results"]'
|
|
12114
12146
|
);
|
|
12147
|
+
if (mmlSearchCache) {
|
|
12148
|
+
input.value = mmlSearchCache.query;
|
|
12149
|
+
statusEl.textContent = `\u300C${mmlSearchCache.query}\u300D\u306E\u691C\u7D22\u7D50\u679C\u3000${mmlSearchCache.count}\u4EF6\u306E\u30D2\u30C3\u30C8`;
|
|
12150
|
+
mmlSearchCache.renderResults(results);
|
|
12151
|
+
}
|
|
12115
12152
|
const runSearch = async () => {
|
|
12116
12153
|
const q2 = input.value.trim();
|
|
12117
12154
|
if (!q2) return;
|
|
@@ -12119,37 +12156,85 @@ var mountDAW = (target, options = {}) => {
|
|
|
12119
12156
|
searchBtn.disabled = true;
|
|
12120
12157
|
searchBtn.textContent = "\u691C\u7D22\u4E2D...";
|
|
12121
12158
|
results.innerHTML = "";
|
|
12159
|
+
statusEl.textContent = "";
|
|
12122
12160
|
try {
|
|
12123
12161
|
const songs = await midiSearchClient.searchSongs({ title: q2 });
|
|
12124
12162
|
if (songs.length === 0) {
|
|
12163
|
+
statusEl.textContent = `\u300C${q2}\u300D\u306E\u691C\u7D22\u7D50\u679C\u30000\u4EF6\u306E\u30D2\u30C3\u30C8`;
|
|
12125
12164
|
results.innerHTML = '<span class="dtm-label" style="color:var(--dtm-warn)">\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F</span>';
|
|
12165
|
+
mmlSearchCache = {
|
|
12166
|
+
query: q2,
|
|
12167
|
+
count: 0,
|
|
12168
|
+
renderResults: (c) => {
|
|
12169
|
+
c.innerHTML = '<span class="dtm-label" style="color:var(--dtm-warn)">\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F</span>';
|
|
12170
|
+
}
|
|
12171
|
+
};
|
|
12126
12172
|
return;
|
|
12127
12173
|
}
|
|
12128
|
-
|
|
12129
|
-
|
|
12130
|
-
|
|
12131
|
-
const
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
12138
|
-
|
|
12139
|
-
|
|
12140
|
-
|
|
12141
|
-
|
|
12142
|
-
|
|
12143
|
-
|
|
12144
|
-
|
|
12145
|
-
|
|
12146
|
-
|
|
12147
|
-
|
|
12148
|
-
|
|
12149
|
-
|
|
12150
|
-
|
|
12151
|
-
|
|
12174
|
+
statusEl.textContent = `\u300C${q2}\u300D\u306E\u691C\u7D22\u7D50\u679C\u3000${songs.length}\u4EF6\u306E\u30D2\u30C3\u30C8`;
|
|
12175
|
+
const renderMmlResults = (container) => {
|
|
12176
|
+
container.innerHTML = "";
|
|
12177
|
+
for (const song of songs) {
|
|
12178
|
+
const box = document.createElement("div");
|
|
12179
|
+
box.className = "dtm-modal-sample-box";
|
|
12180
|
+
const row = document.createElement("div");
|
|
12181
|
+
row.className = "dtm-row";
|
|
12182
|
+
row.style.cssText = "flex-wrap:nowrap;gap:4px;padding:2px 0";
|
|
12183
|
+
const label = document.createElement("span");
|
|
12184
|
+
label.className = "dtm-label";
|
|
12185
|
+
label.style.cssText = "flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap";
|
|
12186
|
+
label.textContent = `${song.title} - ${song.user}`;
|
|
12187
|
+
const previewBtn = document.createElement("button");
|
|
12188
|
+
previewBtn.className = "dtm-btn dtm-btn--ghost";
|
|
12189
|
+
previewBtn.style.cssText = "flex-shrink:0";
|
|
12190
|
+
previewBtn.textContent = "\u25B6 \u8A66\u8074";
|
|
12191
|
+
const loadBtn = document.createElement("button");
|
|
12192
|
+
loadBtn.className = "dtm-btn dtm-btn--primary";
|
|
12193
|
+
loadBtn.style.cssText = "flex-shrink:0";
|
|
12194
|
+
loadBtn.textContent = "\u8AAD\u307F\u8FBC\u307F";
|
|
12195
|
+
const playerContainer = document.createElement("div");
|
|
12196
|
+
playerContainer.className = "dtm-modal-sample-player-container";
|
|
12197
|
+
previewBtn.addEventListener("click", async () => {
|
|
12198
|
+
if (searchPreviewBtn === previewBtn) {
|
|
12199
|
+
if (searchPreviewPlayer?.isPlaying()) {
|
|
12200
|
+
searchPreviewPlayer.stop();
|
|
12201
|
+
} else {
|
|
12202
|
+
stop();
|
|
12203
|
+
previewBtn.textContent = "\u8AAD\u8FBC\u4E2D...";
|
|
12204
|
+
try {
|
|
12205
|
+
const midi = await fetchVerifiedMidi(song.file);
|
|
12206
|
+
const mml = buildPreviewMml(midi);
|
|
12207
|
+
playerContainer.innerHTML = "";
|
|
12208
|
+
const player = mountMmlPlayer(playerContainer, mml, {
|
|
12209
|
+
onPlayNote: options.onPlayNote,
|
|
12210
|
+
onPlayDrum: options.onPlayDrum,
|
|
12211
|
+
onResumeAudio: options.onResumeAudio,
|
|
12212
|
+
getAudioTime: options.getAudioTime,
|
|
12213
|
+
singingVoices: options.singingVoices,
|
|
12214
|
+
drumPatterns: options.drumPatterns,
|
|
12215
|
+
volume: masterVolume,
|
|
12216
|
+
_skipInfoModals: true,
|
|
12217
|
+
onStop: () => {
|
|
12218
|
+
if (searchPreviewBtn === previewBtn) {
|
|
12219
|
+
previewBtn.textContent = "\u25B6 \u8A66\u8074";
|
|
12220
|
+
previewBtn.classList.remove("dtm-btn--danger");
|
|
12221
|
+
previewBtn.classList.add("dtm-btn--ghost");
|
|
12222
|
+
}
|
|
12223
|
+
}
|
|
12224
|
+
});
|
|
12225
|
+
searchPreviewPlayer = player;
|
|
12226
|
+
searchPreviewBtn = previewBtn;
|
|
12227
|
+
player.play();
|
|
12228
|
+
previewBtn.textContent = "\u25A0 \u505C\u6B62";
|
|
12229
|
+
previewBtn.classList.remove("dtm-btn--ghost");
|
|
12230
|
+
previewBtn.classList.add("dtm-btn--danger");
|
|
12231
|
+
} catch (e) {
|
|
12232
|
+
console.error("[dtm] MIDI preview failed", e);
|
|
12233
|
+
previewBtn.textContent = "\u5931\u6557";
|
|
12234
|
+
}
|
|
12235
|
+
}
|
|
12152
12236
|
} else {
|
|
12237
|
+
collapseSearchPreview();
|
|
12153
12238
|
stop();
|
|
12154
12239
|
previewBtn.textContent = "\u8AAD\u8FBC\u4E2D...";
|
|
12155
12240
|
try {
|
|
@@ -12184,31 +12269,169 @@ var mountDAW = (target, options = {}) => {
|
|
|
12184
12269
|
previewBtn.textContent = "\u5931\u6557";
|
|
12185
12270
|
}
|
|
12186
12271
|
}
|
|
12272
|
+
});
|
|
12273
|
+
loadBtn.addEventListener("click", async () => {
|
|
12274
|
+
loadBtn.disabled = true;
|
|
12275
|
+
loadBtn.textContent = "\u8AAD\u8FBC\u4E2D...";
|
|
12276
|
+
try {
|
|
12277
|
+
const pending = await fetchVerifiedMidi(song.file);
|
|
12278
|
+
const analysis = analyzeMidiTracks(pending);
|
|
12279
|
+
const sel = analysis.filter((a) => a.selected).map((a) => a.index);
|
|
12280
|
+
collapseSearchPreview();
|
|
12281
|
+
overlayDuring(() => applyMidiSelection(pending, sel));
|
|
12282
|
+
refs.modalOverlay.setAttribute("hidden", "");
|
|
12283
|
+
} catch (e) {
|
|
12284
|
+
console.error("[dtm] MIDI fetch failed", e);
|
|
12285
|
+
loadBtn.textContent = "\u5931\u6557";
|
|
12286
|
+
} finally {
|
|
12287
|
+
loadBtn.disabled = false;
|
|
12288
|
+
}
|
|
12289
|
+
});
|
|
12290
|
+
row.appendChild(label);
|
|
12291
|
+
row.appendChild(previewBtn);
|
|
12292
|
+
row.appendChild(loadBtn);
|
|
12293
|
+
box.appendChild(row);
|
|
12294
|
+
box.appendChild(playerContainer);
|
|
12295
|
+
container.appendChild(box);
|
|
12296
|
+
}
|
|
12297
|
+
};
|
|
12298
|
+
renderMmlResults(results);
|
|
12299
|
+
mmlSearchCache = {
|
|
12300
|
+
query: q2,
|
|
12301
|
+
count: songs.length,
|
|
12302
|
+
renderResults: renderMmlResults
|
|
12303
|
+
};
|
|
12304
|
+
} catch (e) {
|
|
12305
|
+
console.error("[dtm] MIDI search failed", e);
|
|
12306
|
+
results.innerHTML = '<span class="dtm-label" style="color:var(--dtm-warn)">\u691C\u7D22\u306B\u5931\u6557\u3057\u307E\u3057\u305F</span>';
|
|
12307
|
+
} finally {
|
|
12308
|
+
searchBtn.disabled = false;
|
|
12309
|
+
searchBtn.textContent = "\u691C\u7D22";
|
|
12310
|
+
}
|
|
12311
|
+
};
|
|
12312
|
+
searchBtn.addEventListener("click", () => void runSearch());
|
|
12313
|
+
input.addEventListener("keydown", (e) => {
|
|
12314
|
+
if (e.key === "Enter") void runSearch();
|
|
12315
|
+
});
|
|
12316
|
+
input.focus();
|
|
12317
|
+
});
|
|
12318
|
+
};
|
|
12319
|
+
const openChordSearchModal = (chordTextArea) => {
|
|
12320
|
+
if (!midiSearchClient) return;
|
|
12321
|
+
const active = trackStates.find((t) => t.config.id === activeTrackId);
|
|
12322
|
+
if (!active) return;
|
|
12323
|
+
showModal(
|
|
12324
|
+
"\u30B3\u30FC\u30C9\u9032\u884C\u691C\u7D22",
|
|
12325
|
+
`
|
|
12326
|
+
<div class="dtm-row" style="flex-wrap:nowrap">
|
|
12327
|
+
<input type="text" class="dtm-input dtm-grow" data-dtm="modal-chord-search-input" placeholder="\u66F2\u540D\u3084\u30B3\u30FC\u30C9\u9032\u884C\u3067\u691C\u7D22" style="min-width:0">
|
|
12328
|
+
<button class="dtm-btn dtm-btn--primary" data-dtm="modal-chord-search-btn" style="flex-shrink:0">\u691C\u7D22</button>
|
|
12329
|
+
</div>
|
|
12330
|
+
<div data-dtm="modal-chord-search-status" style="font-size:11px;color:rgba(255,255,255,0.5);min-height:1.4em"></div>
|
|
12331
|
+
<div class="dtm-row" data-dtm="modal-chord-search-results" style="flex-direction:column;align-items:stretch;gap:4px"></div>
|
|
12332
|
+
`
|
|
12333
|
+
);
|
|
12334
|
+
const input = refs.modalBody.querySelector(
|
|
12335
|
+
'[data-dtm="modal-chord-search-input"]'
|
|
12336
|
+
);
|
|
12337
|
+
const searchBtn = refs.modalBody.querySelector(
|
|
12338
|
+
'[data-dtm="modal-chord-search-btn"]'
|
|
12339
|
+
);
|
|
12340
|
+
const statusEl = refs.modalBody.querySelector(
|
|
12341
|
+
'[data-dtm="modal-chord-search-status"]'
|
|
12342
|
+
);
|
|
12343
|
+
const results = refs.modalBody.querySelector(
|
|
12344
|
+
'[data-dtm="modal-chord-search-results"]'
|
|
12345
|
+
);
|
|
12346
|
+
if (chordSearchCache) {
|
|
12347
|
+
input.value = chordSearchCache.query;
|
|
12348
|
+
statusEl.textContent = `\u300C${chordSearchCache.query}\u300D\u306E\u691C\u7D22\u7D50\u679C\u3000${chordSearchCache.count}\u4EF6\u306E\u30D2\u30C3\u30C8`;
|
|
12349
|
+
chordSearchCache.renderResults(results);
|
|
12350
|
+
}
|
|
12351
|
+
const runSearch = async () => {
|
|
12352
|
+
const q2 = input.value.trim();
|
|
12353
|
+
if (!q2) return;
|
|
12354
|
+
collapseSearchPreview();
|
|
12355
|
+
searchBtn.disabled = true;
|
|
12356
|
+
searchBtn.textContent = "\u691C\u7D22\u4E2D...";
|
|
12357
|
+
results.innerHTML = "";
|
|
12358
|
+
statusEl.textContent = "";
|
|
12359
|
+
try {
|
|
12360
|
+
const scores = await midiSearchClient.searchRechord(q2);
|
|
12361
|
+
if (scores.length === 0) {
|
|
12362
|
+
statusEl.textContent = `\u300C${q2}\u300D\u306E\u691C\u7D22\u7D50\u679C\u30000\u4EF6\u306E\u30D2\u30C3\u30C8`;
|
|
12363
|
+
results.innerHTML = '<span class="dtm-label" style="color:var(--dtm-warn)">\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F</span>';
|
|
12364
|
+
chordSearchCache = {
|
|
12365
|
+
query: q2,
|
|
12366
|
+
count: 0,
|
|
12367
|
+
renderResults: (c) => {
|
|
12368
|
+
c.innerHTML = '<span class="dtm-label" style="color:var(--dtm-warn)">\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F</span>';
|
|
12369
|
+
}
|
|
12370
|
+
};
|
|
12371
|
+
return;
|
|
12372
|
+
}
|
|
12373
|
+
statusEl.textContent = `\u300C${q2}\u300D\u306E\u691C\u7D22\u7D50\u679C\u3000${scores.length}\u4EF6\u306E\u30D2\u30C3\u30C8`;
|
|
12374
|
+
const renderChordResults = (container) => {
|
|
12375
|
+
container.innerHTML = "";
|
|
12376
|
+
for (const score of scores) {
|
|
12377
|
+
const box = document.createElement("div");
|
|
12378
|
+
box.className = "dtm-modal-sample-box";
|
|
12379
|
+
const row = document.createElement("div");
|
|
12380
|
+
row.className = "dtm-row";
|
|
12381
|
+
row.style.cssText = "flex-wrap:nowrap;gap:4px;padding:2px 0";
|
|
12382
|
+
const label = document.createElement("span");
|
|
12383
|
+
label.className = "dtm-label";
|
|
12384
|
+
label.style.cssText = "flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap";
|
|
12385
|
+
label.textContent = `${score.title}${score.user?.screen_name ? ` - ${score.user.screen_name}` : ""}`;
|
|
12386
|
+
const previewBtn = document.createElement("button");
|
|
12387
|
+
previewBtn.className = "dtm-btn dtm-btn--ghost";
|
|
12388
|
+
previewBtn.style.cssText = "flex-shrink:0";
|
|
12389
|
+
previewBtn.textContent = "\u25B6 \u8A66\u8074";
|
|
12390
|
+
const loadBtn = document.createElement("button");
|
|
12391
|
+
loadBtn.className = "dtm-btn dtm-btn--primary";
|
|
12392
|
+
loadBtn.style.cssText = "flex-shrink:0";
|
|
12393
|
+
loadBtn.textContent = "\u8AAD\u307F\u8FBC\u307F";
|
|
12394
|
+
const playerContainer = document.createElement("div");
|
|
12395
|
+
playerContainer.className = "dtm-modal-sample-player-container";
|
|
12396
|
+
previewBtn.addEventListener("click", async () => {
|
|
12397
|
+
if (searchPreviewBtn === previewBtn) {
|
|
12398
|
+
if (searchPreviewPlayer?.isPlaying()) {
|
|
12399
|
+
searchPreviewPlayer.stop();
|
|
12400
|
+
} else {
|
|
12401
|
+
stop();
|
|
12402
|
+
previewBtn.textContent = "\u518D\u751F\u4E2D...";
|
|
12403
|
+
try {
|
|
12404
|
+
searchPreviewPlayer?.play();
|
|
12405
|
+
previewBtn.textContent = "\u25A0 \u505C\u6B62";
|
|
12406
|
+
previewBtn.classList.remove("dtm-btn--ghost");
|
|
12407
|
+
previewBtn.classList.add("dtm-btn--danger");
|
|
12408
|
+
} catch (e) {
|
|
12409
|
+
console.error("[dtm] Chord preview play failed", e);
|
|
12410
|
+
previewBtn.textContent = "\u5931\u6557";
|
|
12411
|
+
}
|
|
12412
|
+
}
|
|
12187
12413
|
} else {
|
|
12188
12414
|
collapseSearchPreview();
|
|
12189
12415
|
stop();
|
|
12190
12416
|
previewBtn.textContent = "\u8AAD\u8FBC\u4E2D...";
|
|
12191
12417
|
try {
|
|
12192
|
-
const midi = await fetchVerifiedMidi(song.file);
|
|
12193
|
-
const mml = buildPreviewMml(midi);
|
|
12194
12418
|
playerContainer.innerHTML = "";
|
|
12195
|
-
const player =
|
|
12196
|
-
|
|
12197
|
-
|
|
12198
|
-
|
|
12199
|
-
|
|
12200
|
-
|
|
12201
|
-
|
|
12202
|
-
|
|
12203
|
-
|
|
12204
|
-
|
|
12205
|
-
|
|
12206
|
-
|
|
12207
|
-
|
|
12208
|
-
previewBtn.classList.add("dtm-btn--ghost");
|
|
12419
|
+
const player = mountChordPlayer(
|
|
12420
|
+
playerContainer,
|
|
12421
|
+
score.content,
|
|
12422
|
+
{
|
|
12423
|
+
volume: masterVolume,
|
|
12424
|
+
bpm: score.bpm ?? bpm ?? 120,
|
|
12425
|
+
_skipInfoModals: true,
|
|
12426
|
+
onStop: () => {
|
|
12427
|
+
if (searchPreviewBtn === previewBtn) {
|
|
12428
|
+
previewBtn.textContent = "\u25B6 \u8A66\u8074";
|
|
12429
|
+
previewBtn.classList.remove("dtm-btn--danger");
|
|
12430
|
+
previewBtn.classList.add("dtm-btn--ghost");
|
|
12431
|
+
}
|
|
12209
12432
|
}
|
|
12210
12433
|
}
|
|
12211
|
-
|
|
12434
|
+
);
|
|
12212
12435
|
searchPreviewPlayer = player;
|
|
12213
12436
|
searchPreviewBtn = previewBtn;
|
|
12214
12437
|
player.play();
|
|
@@ -12216,49 +12439,48 @@ var mountDAW = (target, options = {}) => {
|
|
|
12216
12439
|
previewBtn.classList.remove("dtm-btn--ghost");
|
|
12217
12440
|
previewBtn.classList.add("dtm-btn--danger");
|
|
12218
12441
|
} catch (e) {
|
|
12219
|
-
console.error("[dtm]
|
|
12442
|
+
console.error("[dtm] Chord preview mount failed", e);
|
|
12220
12443
|
previewBtn.textContent = "\u5931\u6557";
|
|
12221
12444
|
}
|
|
12222
12445
|
}
|
|
12223
12446
|
});
|
|
12224
|
-
loadBtn.addEventListener("click",
|
|
12225
|
-
|
|
12226
|
-
|
|
12227
|
-
|
|
12228
|
-
|
|
12229
|
-
|
|
12230
|
-
const sel = analysis.filter((a) => a.selected).map((a) => a.index);
|
|
12231
|
-
collapseSearchPreview();
|
|
12232
|
-
overlayDuring(() => applyMidiSelection(pending, sel));
|
|
12233
|
-
refs.modalOverlay.setAttribute("hidden", "");
|
|
12234
|
-
} catch (e) {
|
|
12235
|
-
console.error("[dtm] MIDI fetch failed", e);
|
|
12236
|
-
loadBtn.textContent = "\u5931\u6557";
|
|
12237
|
-
} finally {
|
|
12238
|
-
loadBtn.disabled = false;
|
|
12447
|
+
loadBtn.addEventListener("click", () => {
|
|
12448
|
+
collapseSearchPreview();
|
|
12449
|
+
chordTextArea.value = score.content;
|
|
12450
|
+
active.savedChordInput = score.content;
|
|
12451
|
+
if (score.bpm) {
|
|
12452
|
+
setBpm(score.bpm);
|
|
12239
12453
|
}
|
|
12454
|
+
applyChord();
|
|
12455
|
+
refs.modalOverlay.setAttribute("hidden", "");
|
|
12240
12456
|
});
|
|
12241
12457
|
row.appendChild(label);
|
|
12242
12458
|
row.appendChild(previewBtn);
|
|
12243
12459
|
row.appendChild(loadBtn);
|
|
12244
12460
|
box.appendChild(row);
|
|
12245
12461
|
box.appendChild(playerContainer);
|
|
12246
|
-
|
|
12462
|
+
container.appendChild(box);
|
|
12247
12463
|
}
|
|
12248
|
-
}
|
|
12249
|
-
|
|
12250
|
-
|
|
12251
|
-
|
|
12252
|
-
|
|
12253
|
-
|
|
12254
|
-
}
|
|
12255
|
-
}
|
|
12256
|
-
|
|
12257
|
-
|
|
12258
|
-
|
|
12259
|
-
|
|
12260
|
-
|
|
12464
|
+
};
|
|
12465
|
+
renderChordResults(results);
|
|
12466
|
+
chordSearchCache = {
|
|
12467
|
+
query: q2,
|
|
12468
|
+
count: scores.length,
|
|
12469
|
+
renderResults: renderChordResults
|
|
12470
|
+
};
|
|
12471
|
+
} catch (e) {
|
|
12472
|
+
console.error("[dtm] Chord search failed", e);
|
|
12473
|
+
results.innerHTML = '<span class="dtm-label" style="color:var(--dtm-warn)">\u691C\u7D22\u306B\u5931\u6557\u3057\u307E\u3057\u305F</span>';
|
|
12474
|
+
} finally {
|
|
12475
|
+
searchBtn.disabled = false;
|
|
12476
|
+
searchBtn.textContent = "\u691C\u7D22";
|
|
12477
|
+
}
|
|
12478
|
+
};
|
|
12479
|
+
searchBtn.addEventListener("click", () => void runSearch());
|
|
12480
|
+
input.addEventListener("keydown", (e) => {
|
|
12481
|
+
if (e.key === "Enter") void runSearch();
|
|
12261
12482
|
});
|
|
12483
|
+
input.focus();
|
|
12262
12484
|
};
|
|
12263
12485
|
const onKeyDown = (e) => {
|
|
12264
12486
|
if (!(e.ctrlKey || e.metaKey)) return;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"author": "onjmin",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"name": "@onjmin/dtm",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.58",
|
|
6
6
|
"description": "MMLを中間言語に用いた、モバイルファーストなDAW / ピアノロール打ち込みコンポーネント",
|
|
7
7
|
"homepage": "https://onjmin.github.io/dtm",
|
|
8
8
|
"repository": {
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@biomejs/biome": "2.2.3",
|
|
46
|
-
"@discord/embedded-app-sdk": "2.5.0",
|
|
47
46
|
"@hono/node-server": "1.19.5",
|
|
47
|
+
"@types/node": "26.1.1",
|
|
48
48
|
"esbuild": "0.28.1",
|
|
49
49
|
"hono": "4.10.1",
|
|
50
50
|
"rimraf": "6.0.1",
|