From 387b1287a1c818d60d178b7a0730cf95f26958d9 Mon Sep 17 00:00:00 2001 From: Stefano Garuti Date: Fri, 2 Feb 2024 11:14:00 +0100 Subject: [PATCH] Associate .pushpush files with app (#14) * Associate file_handlers * Import .pushpush files on double clicking it * rename functions to be more coherent * rename fileImport() function --- docs/index.html | 6 ++-- docs/js/app.js | 84 ++++++++++++++++++++++++---------------------- docs/manifest.json | 8 +++++ 3 files changed, 55 insertions(+), 43 deletions(-) diff --git a/docs/index.html b/docs/index.html index 59b691f..cf290c2 100644 --- a/docs/index.html +++ b/docs/index.html @@ -49,8 +49,8 @@

Push Push Editor

- [Export to file] - [Import from file] + [Export to file] + [Import from file]

Import failed

Push Push said:

@@ -292,7 +292,7 @@

Configure Push Push

- +
diff --git a/docs/js/app.js b/docs/js/app.js index 1826908..739544b 100644 --- a/docs/js/app.js +++ b/docs/js/app.js @@ -85,15 +85,15 @@ function connect( ){ fromPushPush.addListener("sysex", parseSysEx); } -function store(){ +function storeInPushPush(){ Alpine.store('pp').pp_loading = true; var sysex = []; sysex.push(X_REQ, X_SET); - sysex = syx_enqueue( sysex ); + sysex = sysEnqueueParams( sysex ); toPushPush.sendSysex(PP_MANUF, sysex); } -function syx_enqueue( sysex ){ +function sysEnqueueParams( sysex ){ sysex.push(Alpine.store('pp').pp_ver_major, Alpine.store('pp').pp_ver_minor, Alpine.store('pp').pp_ver_patch, Alpine.store('pp').pp_model_id, Alpine.store('pp').pp_num_buttons, Alpine.store('pp').pp_keys_sequence_size); var parameters = Alpine.store('pp').pp_parameters @@ -107,12 +107,12 @@ function syx_enqueue( sysex ){ return sysex; } -function syx_is_pushpush( sysex ){ +function syxIsPushPush( sysex ){ if ( sysex[1] != PP_MIDI_MANUF_ID_1 || sysex[2] != PP_MIDI_MANUF_ID_2 || sysex[3] != PP_MIDI_PRODUCT_ID ) return false; // Discard all SysEx that's not for this device return true; } -function syx_is_repl( sysex ){ +function sysIsReply( sysex ){ if ( sysex[4] != X_REP ) return false; // Discard all messages that are not a reply return true; } @@ -150,8 +150,8 @@ function assignParams( sysex ){ function parseSysEx( sysex ){ console.log('sysex: ', sysex ); - if ( !syx_is_pushpush ( sysex.data ) ) return null; - if ( !syx_is_repl ( sysex.data ) ) return null; + if ( !syxIsPushPush ( sysex.data ) ) return null; + if ( !sysIsReply ( sysex.data ) ) return null; Alpine.store('pp').pp_loading = false; @@ -181,7 +181,7 @@ function parseSysEx( sysex ){ } } -async function file_import(){ +async function openFilePicker(){ let fileHandle; try{ const pickerOpts = { @@ -189,48 +189,53 @@ async function file_import(){ { description: "Push Push editor files", accept: { - "*/*": [".pushpush"], + "text/pushpush": [".pushpush"], }, }, ], excludeAcceptAllOption: true, multiple: false, }; - [fileHandle] = await window.showOpenFilePicker( pickerOpts ); - const file = await fileHandle.getFile(); - const content = await file.text(); - const sysex = content.split(" "); - try{ - - if( sysex[0] != 240 || sysex[sysex.length -1] != 247 ) throw new TypeError("Wrong data format"); - if ( !syx_is_pushpush ( sysex ) ) throw new TypeError("Data not for Push Push"); - if( Alpine.store('pp').device ){ - if ( Alpine.store('pp').pp_model_id != sysex[9] ) throw new TypeError("Data not for the connected Push Push model"); - } - if ( !syx_is_repl ( sysex ) ) throw new TypeError("Data not for Push Push config"); - if( sysex[5] != X_GET ) throw new TypeError("Data not for Push Push config file"); - if( sysex.length != 2+11+sysex[10]*sysex[11]*2 ) throw new TypeError("Invalid data"); - - assignParams( sysex ); - } - catch (e) { - console.error(e.message); - Alpine.store('pp').pp_import_error = e.message; + [fileHandle] = await window.showopenFilePicker( pickerOpts ); + fileImport( fileHandle ); + + } + catch (e) { + console.error(e.message); + } +} + +async function fileImport( fileHandle ){ + const file = await fileHandle.getFile(); + const content = await file.text(); + const sysex = content.split(" "); + try{ + + if( sysex[0] != 240 || sysex[sysex.length -1] != 247 ) throw new TypeError("Wrong data format"); + if ( !syxIsPushPush ( sysex ) ) throw new TypeError("Data not for Push Push"); + if( Alpine.store('pp').device ){ + if ( Alpine.store('pp').pp_model_id != sysex[9] ) throw new TypeError("Data not for the connected Push Push model"); } + if ( !sysIsReply ( sysex ) ) throw new TypeError("Data not for Push Push config"); + if( sysex[5] != X_GET ) throw new TypeError("Data not for Push Push config file"); + if( sysex.length != 2+11+sysex[10]*sysex[11]*2 ) throw new TypeError("Invalid data"); + + assignParams( sysex ); } catch (e) { console.error(e.message); + Alpine.store('pp').pp_import_error = e.message; } } -async function file_export() { +async function fileExport() { try{ const options = { types: [ { description: 'Push Push editor files', accept: { - '*/*': ['.pushpush'], + "text/pushpush": ['.pushpush'], }, }, ], @@ -239,7 +244,7 @@ async function file_export() { var sysex = []; sysex.push( 240, PP_MIDI_MANUF_ID_1, PP_MIDI_MANUF_ID_2, PP_MIDI_PRODUCT_ID, X_REP, X_GET); - sysex = syx_enqueue( sysex ); + sysex = sysEnqueueParams( sysex ); sysex.push(247); sysex = sysex.join(' '); @@ -259,12 +264,11 @@ async function file_export() { } -// fileHandle is an instance of FileSystemFileHandle.. -async function writeFile(fileHandle, contents) { - // Create a FileSystemWritableFileStream to write to. - const writable = await fileHandle.createWritable(); - // Write the contents of the file to the stream. - await writable.write(contents); - // Close the file and write the contents to disk. - await writable.close(); +if ("launchQueue" in window) { + launchQueue.setConsumer(async (launchParams) => { + console.log("launchQueue"); + for (const fileHandle of launchParams.files) { + fileImport( fileHandle ); + } + }); } \ No newline at end of file diff --git a/docs/manifest.json b/docs/manifest.json index 94b9b89..5a348b7 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -39,5 +39,13 @@ "description": "An animated preview of the editor", "form_factor": "narrow" } + ], + "file_handlers": [ + { + "action": "./index.html", + "accept": { + "text/pushpush": [".pushpush"] + } + } ] } \ No newline at end of file