]> git.dabkitsch.com - m29-web-sfp.git/commitdiff
regions can be created with a hotkey, cleaned up interface sections, fixed bugs in...
authorequilet <2237372+equilet@users.noreply.github.com>
Wed, 20 Mar 2024 06:58:52 +0000 (01:58 -0500)
committerequilet <2237372+equilet@users.noreply.github.com>
Wed, 20 Mar 2024 06:58:52 +0000 (01:58 -0500)
app.js [new file with mode: 0644]
index.html
style/style.css

diff --git a/app.js b/app.js
new file mode 100644 (file)
index 0000000..c15f501
--- /dev/null
+++ b/app.js
@@ -0,0 +1,406 @@
+const num_slots = 16;
+let num_regions = 0;
+let phase;
+let curr_region = -1;
+//let filepath = "media/basic-break.wav";
+let filepath = "media/Berio-criesoflondon.wav";
+let global_dict = new Object();
+let text_input, text_butt;
+let btn_r = [];
+let btn_tp = [];
+let btn_misc = [];
+let ws;
+let wsr;
+
+//https://medium.com/analytics-vidhya/local-storage-with-vanilla-javascript-c87e3923163a
+
+//initialization---------------------------------------------------------------------
+//
+
+//REGIONS ISSUE:
+//https://wavesurfer.xyz/example/regions/
+//https://wavesurfer.xyz/example/plugin-system/
+
+const setup = async() => {
+    initialize();
+    buttons_make();
+}
+
+//main routine-----------------------------------------------------------------------
+//
+
+document.addEventListener('DOMContentLoaded', function(){
+    setup();
+});
+
+//functions--------------------------------------------------------------------------
+//
+// dynamic loading 
+// ws.load('/some/path/to/wave.wav');
+//
+
+
+function add_one_region() {
+    const dur = ws.getDuration();
+    const pad = 0.2;
+    const currtime = ws.getCurrentTime();
+
+    //let randstart = (Math.random() * dur) - pad;
+    //let randend = randstart + 3;
+
+    wsr.addRegion({
+        channelIdx: num_regions, 
+        content: "region" + num_regions + "text",
+        //id: "cue " + i, 
+        id: 'region',
+        start: currtime, 
+        end: currtime + pad, 
+        loop: false, 
+        color: 'hsla(184, 32%, 72%, 0.1)'
+    });
+    num_regions++;
+}
+function add_3_regions() {
+    const dur = ws.getDuration();
+    const pad = 0.2;
+
+    for(let i=0; i<3; i++){
+
+        let randstart = (Math.random() * dur) - pad;
+        let randend = randstart + 3;
+
+        wsr.addRegion({
+            channelIdx: i, 
+            content: "region" + i + "text",
+            //id: "cue " + i, 
+            id: 'region',
+            start: randstart, 
+            end: randend, 
+            loop: false, 
+            color: 'hsla(184, 32%, 72%, 0.1)'
+        });
+        num_regions++;
+    }
+}
+
+function buttons_reset() {
+        btn_tp_reset();
+        btn_r_reset();
+        btn_m_reset();
+        marker_reset();
+}
+
+function marker_add() {
+    num_regions++;
+
+}
+
+function marker_reset(){
+    curr_region = -1;
+    text_input.value = "no marker selected";
+}
+
+//-------------------------------------------------------------
+//localStorage read/write/clear/etc
+function localstorage_get() {
+    return JSON.stringify(localStorage);
+}
+
+function localstorage_write(data) {
+    Object.keys(data).forEach( function(key) { 
+        localStorage.setItem(key, data[key])
+    });
+}
+
+//-------------------------------------------------------------
+
+function initialize(){
+    
+    let activeregion = null;
+
+    ws = WaveSurfer.create({
+        container: '#waveform',
+        waveColor: 'hsla(184, 32%, 72%, 0.5)',
+        progressColor: 'hsla(184, 0%, 72%, 0.5)',
+        url: filepath
+        /*
+        , plugins: [
+            WaveSurfer.Regions.create({})
+        ]
+        */
+    });
+
+    //let RegionsPlugin = window.WaveSurfer.regions;
+    //wsr = window.WaveSurfer.regions;
+    wsr = ws.registerPlugin(WaveSurfer.Regions.create())
+
+    ws.on('ready', function (){
+        console.log("wavesurfer ready.");
+    });
+
+    //put a text element over the ws while this is loading
+    ws.on('loading', (percent) => {
+        console.log('loading', percent, '%');
+    });
+
+    ws.on('click', (relativeX) => {
+        ws.seekTo(relativeX);
+        ws.play();
+        buttons_reset();
+    });
+
+    wsr.on('region-updated', (region) => {
+        console.log("a region with id", region.channelIdx, "was updated.");
+        console.log("the new start:", region.start);
+        console.log("the new end:", region.end);
+        //do something here to update json or re-popuplate all marker data
+    });
+
+    wsr.on('region-clicked', (region, e) => {
+        e.stopPropagation();
+        activeregion = region;
+        region.play();
+        buttons_reset();
+
+        text_input.value = region.content.innerHTML;
+        curr_region = region.channelIdx; //zero-based
+
+        console.log("a region with id", region.channelIdx, "was clicked.");
+        console.log("this region's start time is", region.start);
+        //console.log("this region's text:", region.content.innerHTML);
+    });
+
+    //key events -----------------------------------------------------------------
+    //
+
+    window.addEventListener("keydown", (e) => {
+        if(!e.repeat && e.key == 'm') {
+            //console.log('the m key was pressed'); 
+            add_one_region();
+        } 
+    });
+
+    //user data ------------------------------------------------------------------
+    //
+    
+    global_dict = {
+        "soundfile" : filepath,
+        "m0" : [2.4, 3., "m1 label"], 
+        "m1" : [8.2, 3., "m2 label"], 
+        "m2" : [11.7, 3., "m3 label"], 
+        "m3" : [14.9, 3., "m4 label"]
+    };
+
+    text_input = document.getElementById("textinput");
+    text_butt = document.getElementById("textsubmit");
+
+    //marker text
+    text_butt.addEventListener('click', () => {
+        console.log("the text entered was", text_input.value);
+
+        if(curr_region){
+            //wsr[curr_region].content.innerHTML = text_input.value;
+            //do stuff here to display region text
+        }
+
+    });
+    //interface data--------------------------------------------------------------
+    //
+    
+    //generate cue marker section
+    for(let i=0; i<num_slots; i++){
+        let temp = {
+            id: "button-" + i, 
+            text: (i + 1), 
+            clicked: false, 
+            call_action: function(){
+                btn_r_reset();
+                console.log('recall button', i, 'clicked');
+            },
+        };
+        btn_r.push(temp);
+    }
+
+    btn_tp = [
+        {
+            id: "button1",
+            text: "play/resume",
+            clicked: false,
+            call_action: function () {
+                ws.play();
+            },
+        },
+        {
+            id: "button2",
+            text: "pause",
+            clicked: false,
+            call_action: function () {
+                ws.pause();
+            },
+        },
+        {
+            id: "button3",
+            text: "stop [+ cue]",
+            clicked: false,
+            call_action: function () {
+                ws.stop();
+            },
+        }
+    ];
+
+    btn_misc = [
+        {
+            id: "generate",
+            text: "generate markers",
+            clicked: false,
+            call_action: function () {
+                console.log("generate button clicked");
+                wsr.clearRegions();
+                add_3_regions();
+            },
+        }, 
+        {
+            id: "clear",
+            text: "clear markers", 
+            clicked: false, 
+            call_action: function () {
+                wsr.clearRegions();
+                num_regions = -1;
+            },
+        }
+    ];
+}
+
+function linear_map(phase, imn, imx, omn, omx){
+    return (phase - imn) * (omx - omn) / (imx - imn) + omn;
+}
+
+function file_to_server() {
+    //let dictstr = JSON.stringify(global_dict);
+    //fs = new File("media/test.json", dictstr);
+    //fs.writeFile();
+}
+
+//try to abstract this to be one function
+function btn_tp_reset() {
+
+    btn_tp.forEach((button, index) => {
+
+        btn_tp[index].clicked = false;
+        const elem = document.getElementById(button.id);
+        
+        if (elem) {
+            elem.classList.remove("clicked");
+        }
+
+    });
+}
+
+//try to abstract this to be one function
+function btn_r_reset() {
+
+    btn_r.forEach((button, index) => {
+
+        btn_r[index].clicked = false;
+        const elem = document.getElementById(button.id);
+        
+        if (elem) {
+            elem.classList.remove("clicked");
+        }
+
+    });
+}
+
+function btn_m_reset() {
+    console.log('btn_m_reset() called');
+
+    btn_misc.forEach((button, index) => {
+        btn_misc[index].clicked = false;
+        const elem = document.getElementById(button.id);
+
+        if (elem) {
+            elem.classList.remove("clicked");
+        }
+    });
+}
+
+function buttons_make() {
+
+    const cont_tp = document.getElementById("container_tp");
+    const cont_cue = document.getElementById("container_cue");
+    const cont_misc = document.getElementById("container_misc");
+    
+    //transport button area -----------------------------------------------
+    //
+    btn_tp.forEach((button) => {
+        const button_elem = document.createElement("div");
+
+        button_elem.id = button.id;
+        button_elem.classList.add("buttons");
+        button_elem.innerHTML = `<h2>${button.text}</h2>`;
+
+        button_elem.addEventListener("click", () => {
+
+            if (!button.clicked) {
+                btn_tp_reset();
+                button.clicked = true;
+                button.call_action();
+                button_elem.classList.add("clicked");
+            }
+
+        });
+
+        cont_tp.appendChild(button_elem);
+    });
+
+    //cue marker area -----------------------------------------------------
+    btn_r.forEach((button) => {
+
+        const button_elem = document.createElement("div");
+
+        button_elem.id = button.id;
+        button_elem.classList.add("buttons");
+        button_elem.innerHTML = `<h2>${button.text}</h2>`;
+
+        button_elem.addEventListener("click", () => {
+
+            if (!button.clicked) {
+                btn_r_reset();
+                button.clicked = true;
+                button.call_action();
+                button_elem.classList.add("clicked");
+            }
+
+        });
+
+        cont_cue.appendChild(button_elem);
+    });
+
+    //misc button area ----------------------------------------------------
+    //
+
+    btn_misc.forEach((button) => {
+        const button_elem = document.createElement("div");
+
+        button_elem.id = button.id;
+        button_elem.classList.add("buttons");
+        button_elem.innerHTML = `<h2>${button.text}</h2>`;
+
+        button_elem.addEventListener("mousedown", () => {
+            if (!button.clicked) {
+                btn_m_reset();
+                button.clicked = true;
+                button.call_action();
+                button_elem.classList.add("clicked");
+            }
+        });
+        button_elem.addEventListener("mouseup", () => {
+            if (button.clicked) {
+                button.clicked = false;
+                button_elem.classList.remove("clicked");
+            }
+        });
+        cont_misc.appendChild(button_elem);
+    });
+
+}
index 76c23e89539712ffb25fb67f3b9d7f0d14ccac26..4882157367d2f70c65de66b62df2ae927631e265 100644 (file)
@@ -5,7 +5,7 @@
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
     <meta name="theme-color" content="#000000">
     
-    <title>M29 Soundfile Presenter</title>
+    <title>M29 Soundfile Presenter: test</title>
 
     <link rel="stylesheet" href="style/style.css">
     <link rel="preconnect" href="https://fonts.googleapis.com">
 
         <div id="transport">
             <h2>Transport</h2>
-            <div class="container" id="container_tp"></div>
+            <div id="container_tp" class="container_horiz"></div>
         </div>
         
         <div id="marker_cue">
-            <h2>Cue Marker</h2>
-            <div class="container" id="cue"></div>
+            <div id="cue_label">
+                <h2>Cue Marker</h2>
+            </div>
+            <div id="container_cue" class="container_horiz"></div>
         </div>
 
-        <div id="marker_loop">
-            <h2>Loop Marker</h2>
-            <div class="container" id="loop"></div>
+        <div id="misc" class="container_vert">
+            <h2>Misc. functions</h2>
+            <div id="container_misc" class="container_horiz"></div>
+        </div>
+
+        <div id="loop" class="container_vert">
+            <h2>Loop Playback of Region</h2>
+            <div class="container_horiz" id="loop_check">
+                <input type="checkbox" checked="${loop}" />
+            </div>
         </div>
 
         <div id="marker_edit">
             <h2>Edit Marker</h2>
+            <input id="textinput" value="default text"></input>
+            <button id="textsubmit"></button>
         </div>
 
 
index 198ec40918b04de782a558e8a3a96567f37acad3..8ea02a38cb64051969195d2ec319248f5dc80ee4 100644 (file)
@@ -3,7 +3,6 @@ html, body {
     padding: 0;
 }
 
-
 #sp-root {
     height: 100vh;
     width: 100vw;
@@ -16,6 +15,20 @@ html, body {
     z-index: -1;
 }
 
+
+#waveform ::part(region) {
+    font-family: "Roboto Condensed", sans-serif;
+    font-weight: 400;
+    font-style: normal;
+    /*
+        background-color: rgba(0, 0, 100, 0.25) !important;
+        border: 1px solid #fff;
+        padding: 1px;
+        text-indent: 10px;
+        text-decoration: underline;
+        */
+}
+
 h1, h2, p {
     font-family: "Roboto Condensed", sans-serif;
     font-weight: 400;
@@ -31,29 +44,46 @@ h2, em {
     font-size: 15px;
 }
 
-.slidecontain {
-    width: 100%;
+/* all button sections */
+.container {
 }
-
-#params {
-
+.container_vert {
+    display: flex;
+    flex-direction: column;
+    flex-basis: auto;
+    justify-content: space-between;
+}
+.container_horiz {
+    display: flex;
+    flex-direction: row;
+    flex-basis: auto;
+    justify-content: space-between;
 }
 
-#params > div { 
+/*
+#container_tp {
+    width: 30%;
     display: flex;
     flex-direction: row;
     flex-basis: auto;
     justify-content: space-between;
 }
+*/
+
+#textsubmit {
+    background: #000000; 
+    width: 100px;
+    height: 20px;
+}
 
 .buttons {
     display: flex;
     flex-wrap: wrap;
-    border: 5px solid black;
+    /* border: 2px solid black; */
     justify-content: center;
-    background: #b7bbd3;
+    background: #b6bfd3;
     color: #000000;
-    padding: 10px;
+    padding: 5px 20px 5px 20px;
     margin: 5px;
 
 }