Skip to content

Commit

Permalink
feat: Added marker support, closes #5 (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikarh committed Mar 18, 2024
1 parent 3bce8f7 commit 4b634ab
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 57 deletions.
20 changes: 12 additions & 8 deletions Mother Project.RPP
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<REAPER_PROJECT 0.1 "7.11/linux-x86_64" 1710608575
<REAPER_PROJECT 0.1 "7.11/linux-x86_64" 1710765457
<NOTES 0 2
>
RIPPLE 0
Expand All @@ -16,8 +16,8 @@
TIMEMODE 1 5 -1 30 0 0 -1
VIDEO_CONFIG 0 0 256
PANMODE 3
CURSOR 1126.9562400000714
ZOOM 0.96542783854914 0 0
CURSOR 843.13022400005377
ZOOM 0.96502131908623 0 0
VZOOMEX 0 0
USE_REC_CFG 0
RECMODE 1
Expand Down Expand Up @@ -65,8 +65,8 @@
GROUP_NAME 0 "Group 1"
GROUP_NAME 1 "Group 2"
GROUP_NAME 2 "Group 3"
SELECTION 684.52156800004377 1126.9562400000714
SELECTION2 684.52156800004377 1126.9562400000714
SELECTION 1126.9562400000714 684.52156800004377
SELECTION2 1126.9562400000714 684.52156800004377
MASTERAUTOMODE 0
MASTERTRACKHEIGHT 0 0
MASTERPEAKCOL 16576
Expand Down Expand Up @@ -95,15 +95,19 @@
DEFSHAPE 1 -1 -1
PT 0.000000000001 115.0000287500 1
>
MARKER 1 0 "" 0 0 1 B {1F9B8B34-1C66-84DF-D437-2AD7A326359B} 0
MARKER 1 0.00000000000097 "Song 1" 1 0 1 B {BAA5B1BE-F406-6AE8-77EA-111BEE4305F7} 0
MARKER 1 0 "Song 1" 1 0 1 B {BAA5B1BE-F406-6AE8-77EA-111BEE4305F7} 0
MARKER 1 250.43472000001663 "" 1
MARKER 1 0.000000000001 "" 0 0 1 B {1F9B8B34-1C66-84DF-D437-2AD7A326359B} 0
MARKER 2 333.91296000002183 "Song 2" 1 25921319 1 B {48FB3B12-9C2D-B592-5400-2AE20785DF92} 0
MARKER 2 550.95638400003531 "" 1
MARKER 2 333.91296000002183 "" 0 0 1 B {C5377EDF-29FC-FEAA-0D4E-B2069F2AE417} 0
MARKER 3 684.52156800004377 "Song 3" 1 20716939 1 B {06E043B5-5ED2-0A7D-A4E9-43018CD84F17} 0
MARKER 3 1126.9562400000714 "" 1
MARKER 3 684.52156800004377 "" 0 0 1 B {D49AE53A-CE94-B9E2-9615-1CA54E4E9C2D} 0
MARKER 4 767.99980800004903 a 0 0 1 B {B3288D66-0FFD-C8D3-464A-1FEAB765C9B8} 0
MARKER 5 843.13022400005377 "" 0 17715871 1 B {5CD95A30-4F1E-F14C-A20F-E6A1A59AE7CC} 0
MARKER 6 943.30411200005994 "" 0 16777216 1 B {2204888A-45F3-66BD-3378-73652DF4690C} 0
MARKER 7 1043.4780000000662 "" 0 0 1 B {DFCC72D3-B7F0-0A1A-492B-C976E1A373FA} 0
<PROJBAY
>
<TRACK {93203F69-DDEF-ED48-8FC3-902D10C8FDA2}
Expand Down Expand Up @@ -145,7 +149,7 @@
ISBUS 0 0
BUSCOMP 0 0 0 0 0
SHOWINMIX 1 0.6667 0.5 1 0.5 0 -1 0
SEL 1
SEL 0
REC 0 0 1 0 0 0 0 0
VU 2
TRACKHEIGHT 31 0 1 0 0 0 0
Expand Down
Binary file modified screenshots/Reaper Project.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Web - Control.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const SUBSCRIPTIONS = [
{ request: "TRANSPORT", interval: 100 },
// Query every 100ms for peak levels
{ request: "TRACK", interval: 100 },
{ request: "REGION", interval: 4000 },
{ request: "REGION;MARKER", interval: 4000 },
{ request: "GET/PROJEXTSTATE/BANDUI/regions", interval: 4000 },
];

Expand Down
156 changes: 117 additions & 39 deletions src/Components/Control/Regions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import {
import { useReaper } from "../../Data/Context";
import {
type CurrentTime,
type ParsedMeta,
type Marker,
PlayState,
type Region,
type RegionMeta,
type RegionsMeta,
} from "../../Data/State";
import { Icons } from "../UI/Icons";
import { Toggle } from "../UI/Toggle";
Expand Down Expand Up @@ -41,11 +42,6 @@ function time(totalSeconds: number): string {
function Progress(p: { region: Region; currentTime: CurrentTime }) {
return (
<>
<div
class="absolute top-0 right-0 bottom-0 left-0 bg-black opacity-40"
style={{ width: `${progress(p.region, p.currentTime.seconds)}%` }}
/>

<div class="absolute top-0 right-0 bottom-0 flex items-center px-1 opacity-90">
<p class="rounded-lg bg-neutral-900/40 p-1 font-mono text-gray-300 text-xs">
{time(p.currentTime.seconds - p.region.startTime)} /{" "}
Expand All @@ -64,7 +60,10 @@ function filterRegions(regions: RegionWithMeta[]): Region[] {
return regions.filter((r) => !(r.meta?.disabled ?? false));
}

function prepareRegions(regions: Region[], meta: ParsedMeta): RegionWithMeta[] {
function prepareRegions(
regions: Region[],
meta: RegionsMeta,
): RegionWithMeta[] {
const result = regions.map((r) => ({ ...r, meta: meta[r.id] }));
result.sort(
(a, b) => (a.meta?.index ?? 10000 + a.id) - (b.meta?.index ?? 10000 + b.id),
Expand All @@ -84,10 +83,37 @@ function playStateClass(playState: PlayState): string {
}
}

function markerPosition(region: Region, marker: Marker): number {
return (
((marker.startTime - region.startTime) /
(region.endTime - region.startTime)) *
100
);
}

function textColor(color?: string): "text-white" | "text-black" {
if (color == null) {
return "text-white";
}

const squareDist =
color
.match(/^#(..)(..)(..)$/)
?.slice(1)
?.map((c) => Number.parseInt(c, 16) ** 2)
?.reduce((acc, c) => acc + c, 0) ?? 0;

if (squareDist > (255 * 255 * 3) / 2) {
return "text-black";
}

return "text-white";
}

function RegionList() {
const {
actions: { moveToRegion },
data: { playState, currentTime, regions, regionMeta },
actions: { moveToRegion, moveToMarker },
data: { playState, currentTime, regions, regionMeta, regionMarkers },
} = useReaper();

const isPlaying = createSelector(
Expand All @@ -101,36 +127,88 @@ function RegionList() {
);

return (
<div class="flex flex-col">
<For each={processedRegions()}>
{(region) => (
<button
type="button"
class={`btn-outlined relative my-1 flex h-10 grow overflow-clip px-3 hover:brightness-125 ${
isPlaying(region) && `selected ${playStateClass(playState())}`
}`}
style={
region.color != null ? { "background-color": region.color } : {}
}
onClick={() => moveToRegion(region)}
>
{isPlaying(region) && (
<Progress region={region} currentTime={currentTime()} />
)}

<div class="absolute top-1 bottom-0 left-0.5 opacity-90">
<div class="rounded-lg bg-neutral-900/40 p-1 font-normal text-base text-gray-200">
{region.id}. {region.name}
<div>
<div
class="flex justify-center rounded-md shadow-sm h-10 mb-4"
role="group"
>
<button
class="flex items-center btn-primary border rounded-none rounded-l basis-1/2"
type="button"
onclick={() => moveToMarker("previous")}
>
<Icons.Left />
<span class="flex-grow">Previous marker</span>
</button>
<button
class="flex items-center btn-primary border border-l-0 rounded-none rounded-r basis-1/2"
type="button"
onclick={() => moveToMarker("next")}
>
<span class="flex-grow">Next marker</span>
<Icons.Right />
</button>
</div>

<div class="flex flex-col">
<For each={processedRegions()}>
{(region) => (
<button
type="button"
class={`btn-outlined relative my-1 flex h-10 grow overflow-clip px-3 hover:brightness-125 ${
isPlaying(region) && `selected ${playStateClass(playState())}`
}`}
style={
region.color != null ? { "background-color": region.color } : {}
}
onClick={() => moveToRegion(region)}
>
{isPlaying(region) && (
<div
class="absolute top-0 right-0 bottom-0 left-0 bg-black opacity-40"
style={{
width: `${progress(region, currentTime().seconds)}%`,
}}
/>
)}

<For each={regionMarkers()[region.id] ?? []}>
{(marker) => (
<div
class="absolute top-0 bottom-0 border-l border-solid border-red-600 opacity-50"
style={{
left: `${markerPosition(region, marker)}%`,
"border-color": marker.color,
}}
>
<div
class={`absolute top-[-3px] text-xs bg-red-600 px-1 rounded-br-md ${textColor(
marker.color,
)}`}
style={{ "background-color": marker.color }}
>
{marker.id}
</div>
</div>
)}
</For>
{isPlaying(region) && (
<Progress region={region} currentTime={currentTime()} />
)}
<div class="absolute top-0 bottom-0 left-0.5 opacity-90 flex justify-center items-center">
<div class="rounded-lg bg-neutral-900/40 p-1 font-normal text-base text-gray-200">
{region.id}. {region.name}
</div>
</div>
</div>
</button>
)}
</For>
</button>
)}
</For>
</div>
</div>
);
}

function moveUp(regions: RegionWithMeta[], index: number): ParsedMeta {
function moveUp(regions: RegionWithMeta[], index: number): RegionsMeta {
const newRegions = [...regions];

const temp = newRegions[index];
Expand All @@ -145,10 +223,10 @@ function moveUp(regions: RegionWithMeta[], index: number): ParsedMeta {
};

return acc;
}, {} as ParsedMeta);
}, {} as RegionsMeta);
}

function moveDown(regions: RegionWithMeta[], index: number): ParsedMeta {
function moveDown(regions: RegionWithMeta[], index: number): RegionsMeta {
const newRegions = [...regions];

const temp = newRegions[index];
Expand All @@ -163,10 +241,10 @@ function moveDown(regions: RegionWithMeta[], index: number): ParsedMeta {
};

return acc;
}, {} as ParsedMeta);
}, {} as RegionsMeta);
}

function toggleEnabled(regions: RegionWithMeta[], index: number): ParsedMeta {
function toggleEnabled(regions: RegionWithMeta[], index: number): RegionsMeta {
const parsedMeta = regions.reduce((acc, r, i) => {
acc[r.id] = {
id: r.id,
Expand All @@ -175,7 +253,7 @@ function toggleEnabled(regions: RegionWithMeta[], index: number): ParsedMeta {
};

return acc;
}, {} as ParsedMeta);
}, {} as RegionsMeta);

parsedMeta[regions[index].id].disabled = !(
regions[index].meta?.disabled ?? false
Expand Down
36 changes: 36 additions & 0 deletions src/Components/UI/Icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,40 @@ const Up = () => (
</svg>
);

const Left = (p: { class?: string }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width={1.5}
stroke="currentColor"
class={`h-5 w-5 ${p.class}`}
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15.75 19.5 8.25 12l7.5-7.5"
/>
</svg>
);

const Right = (p: { class?: string }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width={1.5}
stroke="currentColor"
class={`h-5 w-5 ${p.class}`}
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="m8.25 4.5 7.5 7.5-7.5 7.5"
/>
</svg>
);

const Control = (p: { class?: string }) => (
<svg
class={`mb-1 h-6 w-6 ${p.class}`}
Expand Down Expand Up @@ -177,6 +211,8 @@ export const Icons = {
Checked,
Down,
Up,
Left,
Right,

Control,
Mix,
Expand Down
16 changes: 15 additions & 1 deletion src/Data/Actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ interface SetRegionsMeta {
value: string;
}

interface PreviousMarker {
type: "PreviousMarker";
}

interface NextMarker {
type: "NextMarker";
}

export type Action =
| PlayAction
| PauseAction
Expand All @@ -55,7 +63,9 @@ export type Action =
| SetSendVolumeAction
| ToggleSendMuteAction
| ToggleRepeatAction
| SetRegionsMeta;
| SetRegionsMeta
| PreviousMarker
| NextMarker;

export function reduceActions(actions: Action[]): Action[] {
const latest: { [k: string]: Action } = {};
Expand Down Expand Up @@ -132,6 +142,10 @@ export function actionsToCommands(actions: Action[]): string {
return "1013;TRANSPORT";
case "ToggleRepeat":
return "1068;TRANSPORT";
case "PreviousMarker":
return "40172;TRANSPORT";
case "NextMarker":
return "40173;TRANSPORT";
case "Move":
return `SET/POS/${action.end};40626;SET/POS/${action.pos};40625;TRANSPORT`;
case "SetTrackVolume":
Expand Down
Loading

0 comments on commit 4b634ab

Please sign in to comment.