save and load audioLayer and audioPlayer

dependencies hashes:
openFrameworks d78075f4bca6be2a2533c6e51a75cc1f18404501
ofxMsdfgen e14da13d02c4dff04fb69d7923469f606924e6c3
ofxGPUFont d482bb7cbdf6b296fa4ab5abcf73fb5ff8c8b239
ofxVariableLab 0b5f9bdebc1e5550621957e73c040c258ec6317b
ofxProfiler a868e34fa1a79189dd4fbdede2938e308535e5e8
theatre c60e63f5be4466e21b6bf06f6580f6100687306b
This commit is contained in:
themancalledjakob 2024-04-13 18:03:44 +02:00
parent ef308f61b2
commit 8075cf2b16
7 changed files with 172 additions and 32 deletions

View file

@ -1162,7 +1162,7 @@ const Audio = function(tp, record) {
} }
}); });
} else { } else {
console.log("getUserMedia not supported on your browser!"); console.log("Audio::init","getUserMedia not supported on your browser!");
} }
const visualize = () => { const visualize = () => {

View file

@ -1,5 +1,6 @@
import { import {
sanitizeTheatreKey sanitizeTheatreKey,
arraysEqual,
} from './utils.js'; } from './utils.js';
const AudioLayer = function(tp, audioLayerID, values = false, autoInit = true) { const AudioLayer = function(tp, audioLayerID, values = false, autoInit = true) {
@ -14,14 +15,34 @@ const AudioLayer = function(tp, audioLayerID, values = false, autoInit = true) {
props[Object.keys(values)[0]] = tp.core.types.boolean(false); props[Object.keys(values)[0]] = tp.core.types.boolean(false);
} }
const onValuesChangeCallbacks = [];
// private functions // private functions
// //
const onValuesChange = (values) => { const onValuesChange = (values) => {
console.log(values); console.log(values);
const n_callbacks = onValuesChangeCallbacks.length;
const successes = [];
if (n_callbacks > 0) {
for (let i = 0; i < n_callbacks; i++) {
if (typeof onValuesChangeCallbacks[i] === 'function') {
if(onValuesChangeCallbacks[i](values)) {
successes.unshift(i);
}
} else {
console.log('AudioLayer::onValuesChange', 'holy shit, the callback is not a function');
}
}
successes.forEach((i) => {
onValuesChangeCallbacks.splice(i, 1);
});
}
}; };
const findInjectPanel = () => { const findInjectPanel = () => {
console.log('find and inject'); console.log('AudioLayer::findInjectPanel');
const sequencePanel = tp.getSequencePanel();
const sequencePanelLeft = tp.getSequencePanelLeft();
}; };
const setTime = (filename, start, stop) => { const setTime = (filename, start, stop) => {
@ -104,13 +125,33 @@ const AudioLayer = function(tp, audioLayerID, values = false, autoInit = true) {
values[filename] = false; values[filename] = false;
props[filename] = tp.core.types.boolean(values[filename]); props[filename] = tp.core.types.boolean(values[filename]);
this.props = props; this.props = props;
tp.changeObject(audioLayerID, {
dummy: true const setDummy = () => {
tp.changeObject(audioLayerID, {
dummy: true
});
};
onValuesChangeCallbacks.push((changedValues) => {
if (changedValues.dummy) {
// NOTE: any idea how to avoid this ugly nesting?
onValuesChangeCallbacks.push((againChangedValues) => {
const expectedValueKeys = Object.keys(values);
const givenValueKeys = Object.keys(againChangedValues);
if (arraysEqual(expectedValueKeys, givenValueKeys)) {
resolve();
return true;
} else {
return false;
}
});
tp.changeObject(audioLayerID, this.props);
return true;
} else {
return false;
}
}); });
setTimeout(() => { setDummy();
tp.changeObject(audioLayerID, this.props);
resolve();
}, 100);
}); });
}; };
this.removeFile = (filename) => { this.removeFile = (filename) => {
@ -120,13 +161,26 @@ const AudioLayer = function(tp, audioLayerID, values = false, autoInit = true) {
delete values[filename]; delete values[filename];
delete props[filename]; delete props[filename];
this.props = props; this.props = props;
tp.changeObject(audioLayerID, { const setDummy = () => {
dummy: true tp.changeObject(audioLayerID, {
dummy: true
});
};
onValuesChangeCallbacks.push((changedValues) => {
if (changedValues.dummy) {
// NOTE: any idea how to avoid this ugly nesting?
onValuesChangeCallbacks.push((againChangedValues) => {
const expectedValueKeys = Object.keys(values);
const givenValueKeys = Object.keys(againChangedValues);
if (arraysEqual(expectedValueKeys, givenValueKeys)) {
resolve();
}
});
tp.changeObject(audioLayerID, this.props);
}
}); });
setTimeout(() => { setDummy();
tp.changeObject(audioLayerID, this.props);
resolve();
}, 100);
}); });
}; };
this.setTime = setTime; this.setTime = setTime;

View file

@ -30,7 +30,7 @@ const AudioPlayer = function() {
this.addMany = (manyAudioElements) => { this.addMany = (manyAudioElements) => {
manyAudioElements.forEach((e) => { manyAudioElements.forEach((e) => {
this.add(e.audioID, e.layerID, e.propTitle, e.file); this.add(e.audioID, e.layerID, e.propTitle, e.file, e.startTime);
}); });
}; };

View file

@ -604,7 +604,7 @@ const addAudioLayer = (filename = false) => {
}); });
}; };
const addExistingAudioLayer = (audioLayerID, values) => { const addExistingAudioLayer = (audioLayerID, values = false) => {
return new Promise((resolve) => { return new Promise((resolve) => {
const audioLayer = new AudioLayer(tp, audioLayerID, values, false); const audioLayer = new AudioLayer(tp, audioLayerID, values, false);
audioLayers.push(audioLayer); audioLayers.push(audioLayer);

View file

@ -248,6 +248,14 @@ const Record = function(tp) {
if (cPropTitle.indexOf('color.') === 0) { if (cPropTitle.indexOf('color.') === 0) {
cPropTitle = 'color'; cPropTitle = 'color';
} }
const propTitleDom = tp.getPanelPropTitle(cPropTitle);
if (propTitleDom === null) {
// whoops, probably currently transitioning,
// so it will not be necessary to remove the class
// when it will be recreated on demand,
// it won't have the class anyways.
return;
}
const button = tp const button = tp
.getPanelPropTitle(cPropTitle) .getPanelPropTitle(cPropTitle)
.parentNode.parentNode .parentNode.parentNode

View file

@ -23,6 +23,10 @@ const TheatrePlay = function(autoInit = false) {
const theatreObjects = {}; const theatreObjects = {};
let theatrePanel = null; let theatrePanel = null;
let sequencePanelLeft = null; let sequencePanelLeft = null;
const getSequencePanel = () => {
sequencePanelLeft = tp.shadowRoot.querySelector('[data-testid="SequencePanel-Object"]');
return sequencePanelLeft;
};
const getSequencePanelLeft = () => { const getSequencePanelLeft = () => {
sequencePanelLeft = tp.shadowRoot.querySelector('[data-testid="SequencePanel-Left"]'); sequencePanelLeft = tp.shadowRoot.querySelector('[data-testid="SequencePanel-Left"]');
return sequencePanelLeft; return sequencePanelLeft;
@ -321,6 +325,7 @@ const TheatrePlay = function(autoInit = false) {
}; };
this.isSequenced = isSequenced; this.isSequenced = isSequenced;
this.getSequenceButton = getSequenceButton; this.getSequenceButton = getSequenceButton;
this.getSequencePanel = getSequencePanel;
this.getSequencePanelLeft = getSequencePanelLeft; this.getSequencePanelLeft = getSequencePanelLeft;
this.getPanel = getPanel; this.getPanel = getPanel;
this.getPanelPropTitle = getPanelPropTitle; this.getPanelPropTitle = getPanelPropTitle;
@ -589,6 +594,28 @@ const TheatrePlay = function(autoInit = false) {
audioMapping: audio.getMapping(), audioMapping: audio.getMapping(),
}; };
const theatre = tp.studio.createContentOfSaveFile(currentProjectId); const theatre = tp.studio.createContentOfSaveFile(currentProjectId);
// yeaaaah we don't want to fuck with theatre's saveFile stuff
// let's do this ourselves
const audioLayers = getAudioLayers();
if (audioLayers.length > 0) {
vt_params['audioLayers'] = {};
audioLayers.forEach((audioLayer) => {
vt_params['audioLayers'][audioLayer.id()] = getKeyframes(audioLayer);
});
const audioPlayerElements = audio
.audioPlayer
.audioElements
.map((e) => {
return {
audioID: e.audioID,
layerID: e.layerID,
propTitle: e.propTitle,
file: e.file,
startTime: e.startTime
};
});
vt_params['audioPlayerElements'] = audioPlayerElements;
}
return this.theatre2variableTime(theatre, vt_params); return this.theatre2variableTime(theatre, vt_params);
}; };
this.saveProject = (projectId = project.address.projectId, vt_project = false, silent = true) => { this.saveProject = (projectId = project.address.projectId, vt_project = false, silent = true) => {
@ -709,12 +736,12 @@ const TheatrePlay = function(autoInit = false) {
}) => { }) => {
set(window.getArtboard().theatreObject.props, artboardProps); set(window.getArtboard().theatreObject.props, artboardProps);
}); });
if (project.hasOwnProperty('audioMapping')) { if (project.hasOwnProperty('audioMapping')) {
audio.setMapping(project.audioMapping); audio.setMapping(project.audioMapping);
} }
if (project.hasOwnProperty('audioSavedMapping')) { if (project.hasOwnProperty('audioSavedMapping')) {
audio.setSavedMapping(project.audioSavedMapping); audio.setSavedMapping(project.audioSavedMapping);
} }
// load layers // load layers
const layerPromises = []; const layerPromises = [];
@ -723,17 +750,48 @@ const TheatrePlay = function(autoInit = false) {
.forEach((layerId) => { .forEach((layerId) => {
window.setLoadingTask(`setting up the shapes of ${layerId} to come`, 90); window.setLoadingTask(`setting up the shapes of ${layerId} to come`, 90);
window.project_fontsHashMap = project.fontsHashMap; window.project_fontsHashMap = project.fontsHashMap;
layerPromises.push(window.addExistingLayer(layerId, objects[layerId])); //layerPromises.push(window.addExistingLayer(layerId, objects[layerId]));
layerPromises.push(() => {
return new Promise((r) => {
window.addExistingLayer(layerId, objects[layerId]).then(() => {
r();
});
});
});
}); });
//console.log(clone(objects)); if (typeof project['audioPlayerElements'] === 'object') {
Object.keys(objects) audio.audioPlayer.addMany(project['audioPlayerElements']);
.filter((e) => e.indexOf('audio-') === 0) }
.forEach((layerId) => { if (typeof project['audioLayers'] === 'object') {
window.setLoadingTask(`setting up the sounds of ${layerId} to come`, 90); const audioLayerIDs = Object.keys(project['audioLayers']);
window.project_fontsHashMap = project.fontsHashMap; audioLayerIDs.forEach((audioLayerID) => {
layerPromises.push(window.addExistingAudioLayer(layerId, objects[layerId])); layerPromises.push(() => {
window.setLoadingTask(`setting up the sounds of ${audioLayerID} to come`, 90);
return new Promise((r) => {
window.addExistingAudioLayer(audioLayerID).then((audioLayer) => {
const promises = [];
project['audioLayers'][audioLayerID].forEach((keyframeCombo) => {
const filename = keyframeCombo.path.join('');
promises.push(() => {
return new Promise((rr) => {
audioLayer.addFile(filename)
.then(() => {
rr(); // resolve
});
});
});
});
sequencialPromises(promises, () => {
tp.addKeyframes(audioLayer, project['audioLayers'][audioLayerID]);
r(); // resolve
});
});
});
});
}); });
Promise.all(layerPromises).then(() => { }
sequencialPromises(layerPromises, () => {
window.layerOrder.set(project.layerOrder); window.layerOrder.set(project.layerOrder);
this.duration = this.core.val(this.sheet.sequence.pointer.length); this.duration = this.core.val(this.sheet.sequence.pointer.length);
if (project.layerOrder.length > 0) { if (project.layerOrder.length > 0) {

View file

@ -531,6 +531,25 @@ const getNestedProperty = (o, a, verify = false) => {
return o[b[0]]; return o[b[0]];
}; };
const findNestedObjectKey = (o, k, exact = true, history = [], result = []) => {
const oks = Object.keys(o);
for (let i = 0; i < oks.length; i++) {
if (k === oks[i] || (!exact && oks[i].indexOf(k) >= 0)) {
history.push(oks[i]);
result.push({found: o[oks[i]], history});
}
if (typeof o[oks[i]] === 'object') {
const ok = Object.keys(o[oks[i]]);
const ok_history = clone(history);
ok_history.push(oks[i]);
findNestedObjectKey(o[oks[i]], k, exact, ok_history, result);
}
}
if (history.length === 0) {
return result;
}
};
// NOTE: all input values are range 0-1 // NOTE: all input values are range 0-1
const rgbaToHexa = (rgba) => { const rgbaToHexa = (rgba) => {
return '#' + ( return '#' + (
@ -610,6 +629,7 @@ export {
flattenObject, flattenObject,
deFlattenObject, deFlattenObject,
getNestedProperty, getNestedProperty,
findNestedObjectKey,
rgbaToHexa, rgbaToHexa,
hexaToRgba, hexaToRgba,
getFileExtensionFromMimeType, getFileExtensionFromMimeType,