import: a .rsbank lands as a new bank, whole or not at all
Four collisions answered explicitly: ids reminted, names never overwritten, content deduped before the write, bank name auto-suffixed. Degraded ledger refuses before the picker.
This commit is contained in:
@@ -48,7 +48,7 @@ live in `shell/bank_ops`, a sibling directory, not here.
|
||||
## Modules
|
||||
|
||||
- `bank_panel` (`shell/panel/`: `panel_window` / `panel_layout` / `panel_render` / `panel_input` / `panel_drag` / `panel_thumbnails` / `panel_audition` / `panel_bank_ops`, sharing state via `panel_state.h` — Q-W2 split of the former god-module into eight TUs) — docked LICE-drawn grid with three-zone layout: top toolbar (Capture → Maintenance → Placement via `action_bar`, short labels, More (⋯) overflow menu via `overflow_menu`), bottom toolbar (four opposite-mode tag buttons + Show Both), and footer (`[Arrange|Design]` toggle, Tail button, Prune via `footer_bar`). Grid renders in sparse slot order with gap cells, drop dispatch, metadata overlay, and selection via `accent/tertiary` purple border. Draws through the L1 kit by palette role; OS drag-out via `drag_out` + `drag_out_win`. `panel_window` owns the SWELL dialog lifecycle + dialog proc + drop-target opt-in; `panel_layout` the toolbar/footer/menu rects + vertical-split geometry (the one geometry source both paint and hit-test read); `panel_render` the WM_PAINT draw; `panel_input` click/wheel/keyboard routing + the new-content auto-tag timer; `panel_drag` the hover + card-drag state machine + drop dispatch; `panel_thumbnails` the PCM→envelope thumbnail cache + the bank-change fingerprint pass; `panel_audition` the preview-playback engine; `panel_bank_ops` the menu/prompt UX skin over the promptless `shell/bank_ops` verbs. `draw_kit` (shared with the VST3 editor) stays a separate TU.
|
||||
- `panel_window` — SWELL dialog lifecycle + dialog proc + drop-target opt-in.
|
||||
- `panel_window` — SWELL dialog lifecycle + dialog proc + drop-target opt-in. The drop splits by extension: a `.rsbank` is a whole bank and routes to the package-import action (one NEW bank each), everything else keeps the audio-ingest route.
|
||||
- `panel_layout` — toolbar/footer/menu rects + vertical-split geometry (the one geometry source both paint and hit-test read).
|
||||
- `panel_render` — the WM_PAINT draw.
|
||||
- `panel_input` — click/wheel/keyboard routing + the new-content auto-tag timer.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "shell/panel/panel_state.h"
|
||||
#include "shell/panel/panel_bank_ops.h"
|
||||
|
||||
#include "shell/actions/package_import_action.h" // doImportBankPackage — the menu's import row
|
||||
#include "shell/bank_ops/bank_ops.h" // bankOp* promptless verbs
|
||||
#include "shell/persist/session.h" // ReaSamplerSession — the live session the ops mutate
|
||||
|
||||
@@ -242,6 +243,7 @@ enum : unsigned int {
|
||||
kMenuEvacuate,
|
||||
kMenuCreate,
|
||||
kMenuRemove, // remove selected sample(s) from the source bank
|
||||
kMenuImportPackage, // land a .rsbank as a NEW bank (never merges into this one)
|
||||
kMenuMoveBase = 1000, // move-to-bank: kMenuMoveBase + destination index
|
||||
kMenuCopyBase = 2000, // copy-to-bank: kMenuCopyBase + destination index
|
||||
};
|
||||
@@ -267,6 +269,7 @@ void showTabMenu(int screenX, int screenY, const std::string& bankId) {
|
||||
menuAppend(menu, kMenuDelete, "Delete...");
|
||||
menuSeparator(menu);
|
||||
menuAppend(menu, kMenuCreate, "New bank...");
|
||||
menuAppend(menu, kMenuImportPackage, "Import bank package...");
|
||||
|
||||
const int cmd = TrackPopupMenu(menu, TPM_RETURNCMD, screenX, screenY, 0,
|
||||
g_panel.hwnd, nullptr);
|
||||
@@ -278,6 +281,11 @@ void showTabMenu(int screenX, int screenY, const std::string& bankId) {
|
||||
case kMenuEvacuate: doEvacuateBank(bankId); break;
|
||||
case kMenuDelete: doDeleteBank(bankId); break;
|
||||
case kMenuCreate: doCreateBank(); break;
|
||||
// Always a NEW bank, never a merge into the right-clicked one — the row sits
|
||||
// here because this is the panel's bank menu, not because it targets this bank.
|
||||
case kMenuImportPackage:
|
||||
if (g_panel.session) doImportBankPackage(*g_panel.session);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "shell/panel/draw_kit.h"
|
||||
#include "shell/actions/ingest.h"
|
||||
#include "shell/actions/package_import_action.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windowsx.h> // GET_X_LPARAM / GET_Y_LPARAM (SWELL supplies them on mac/linux)
|
||||
@@ -40,12 +41,24 @@ PanelState g_panel;
|
||||
|
||||
namespace {
|
||||
|
||||
bool isPackagePath(const std::string& path) {
|
||||
static const std::string kExt = ".rsbank";
|
||||
if (path.size() <= kExt.size()) return false;
|
||||
std::string tail = path.substr(path.size() - kExt.size());
|
||||
for (char& c : tail)
|
||||
if (c >= 'A' && c <= 'Z') c = static_cast<char>(c - 'A' + 'a');
|
||||
return tail == kExt;
|
||||
}
|
||||
|
||||
// DragQueryFile(hDrop, 0xFFFFFFFF, ...) returns the file count; each path is then
|
||||
// queried by index (length first, excludes NUL, then a sized buffer). DragFinish
|
||||
// always frees the shell-allocated drop buffer. Multi-file drop imports all into
|
||||
// the active bank (bank-fill only — no assignment to any live instance).
|
||||
// always frees the shell-allocated drop buffer. A .rsbank is a whole bank, not audio,
|
||||
// so it routes to the import verb (one new bank each); everything else keeps the
|
||||
// existing ingest route — multi-file drop imports all into the active bank (bank-fill
|
||||
// only, no assignment to any live instance).
|
||||
void handleDropFiles(HDROP hDrop) {
|
||||
std::vector<std::string> paths;
|
||||
std::vector<std::string> packages;
|
||||
const UINT count = DragQueryFile(hDrop, 0xFFFFFFFF, nullptr, 0);
|
||||
paths.reserve(count);
|
||||
for (UINT i = 0; i < count; ++i) {
|
||||
@@ -54,9 +67,14 @@ void handleDropFiles(HDROP hDrop) {
|
||||
std::vector<char> buf(static_cast<std::size_t>(len) + 1, '\0');
|
||||
DragQueryFile(hDrop, i, buf.data(), static_cast<UINT>(buf.size()));
|
||||
std::string p(buf.data());
|
||||
if (!p.empty()) paths.push_back(std::move(p));
|
||||
if (p.empty()) continue;
|
||||
if (isPackagePath(p)) packages.push_back(std::move(p));
|
||||
else paths.push_back(std::move(p));
|
||||
}
|
||||
DragFinish(hDrop);
|
||||
if (g_panel.session)
|
||||
for (const std::string& pkg : packages)
|
||||
doImportBankPackageFile(*g_panel.session, pkg);
|
||||
if (!paths.empty()) ingestDroppedFiles(paths);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user