diff options
author | Richard <q@1bpm.net> | 2025-04-13 18:48:02 +0100 |
---|---|---|
committer | Richard <q@1bpm.net> | 2025-04-13 18:48:02 +0100 |
commit | 9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22 (patch) | |
tree | 291bd79ce340e67affa755a8a6b4f6a83cce93ea /site/app/twine/_hOLD/index_workingold.html | |
download | apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.gz apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.bz2 apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.zip |
initial
Diffstat (limited to 'site/app/twine/_hOLD/index_workingold.html')
-rw-r--r-- | site/app/twine/_hOLD/index_workingold.html | 1251 |
1 files changed, 1251 insertions, 0 deletions
diff --git a/site/app/twine/_hOLD/index_workingold.html b/site/app/twine/_hOLD/index_workingold.html new file mode 100644 index 0000000..21812d7 --- /dev/null +++ b/site/app/twine/_hOLD/index_workingold.html @@ -0,0 +1,1251 @@ +<html>
+<head>
+<title>twine</title>
+<link rel="stylesheet" href="../base/theme.css">
+<link rel="stylesheet" href="../twirl/twirl.css">
+<style type="text/css">
+
+body {
+ font-family: var(--fontFace);
+ color: var(--fgColor1);
+ font-size: var(--fontSizeDefault);
+ user-select: none;
+ cursor: arrow;
+ font-size: 11pt;
+}
+
+#twine_menubar {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ width: 100%;
+ right: 0px;
+ height: 20px;
+ z-index: 6;
+}
+
+.transparentinput {
+ font-size: var(--fontSizeSmall);
+ background-color: var(--bgColor3);
+ color: var(--fgColor2);
+ border: none;
+}
+
+.slider {
+ background: var(--bgColor3);
+ accent-color: var(--fgColor2);
+}
+
+#twine_header {
+ position: absolute;
+ top: 20px;
+ height: 30px;
+ left: 0px;
+ width: 100%;
+ background-color: var(--bgColor1);
+ overflow: none;
+}
+
+.drag_selection {
+ position: fixed;
+ background-color: #323232;
+ opacity: 0.5;
+ z-index: 101;
+}
+
+#twine_headertable {
+ height: 30px;
+}
+
+#twine_clipdetails {
+ display: none;
+}
+
+#twine_channeldetailslow {
+ display: none;
+}
+
+#loading {
+ opacity: 0.7;
+ background-color: #767676;
+ position: fixed;
+ left: 0px;
+ top: 0px;
+ width: 100%;
+ height: 100%;
+ display: none;
+ z-index: 666;
+}
+
+#loading_centre {
+ z-index: 667;
+ position: relative;
+ height: 200px;
+}
+
+#loading_text {
+ font-size: 24pt;
+ margin: 0;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ font-size: 72pt;
+ text-align: center;
+}
+
+#start {
+ z-index: 200;
+ position: fixed;
+ left: 0px;
+ top: 0px;
+ width: 100%;
+ height: 100%;
+ background-color: #343434;
+}
+
+#start_centre {
+ z-index: 201;
+ position: relative;
+ height: 200px;
+}
+
+#start_invoke {
+ z-index: 202;
+ margin: 0;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ font-size: 72pt;
+ cursor: pointer;
+}
+
+#twine_main {
+ position: absolute;
+ top: 50px;
+ bottom: 0px;
+ left: 0px;
+ width: 100%;
+}
+
+#twine_timeline {
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ width: 100%;
+ height: 70%;
+}
+
+#twine_timelineoverlay {
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ width: 100%;
+ height: 100%;
+ opacity: 0.1;
+ background-color: #ffffff;
+}
+
+
+.timelinetext {
+ font-size: var(--fontSizeSmall);
+ opacity: 0.9;
+ position: absolute;
+ color: var(--fgColor3);
+ top: 2px;
+ z-index: 21;
+}
+
+.timelinemarker {
+ width: 1px;
+ position: absolute;
+ background-color: #bdbdbd;
+ opacity: 0.9;
+ height: 100%;
+ top: 0px;
+ z-index: 20;
+}
+
+.smbut {
+ font-size: 8pt;
+ background-color: var(--bgColor2);
+ color: var(--fgColor2);
+ border: 1px solid black;
+}
+
+.knoblabel {
+ font-size: 8pt;
+ text-align: center;
+}
+
+#twine_details {
+ position: absolute;
+ left: 0px;
+ bottom: 0px;
+ width: 100%;
+ height: 30%;
+ background-color: var(--bgColor1);
+}
+
+#twine_clipdetailsleft {
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ width: 30%;
+ height: 100%;
+ font-size: var(--fontSizeSmall);
+ background-color: var(--bgColor2);
+}
+
+#twine_clipdetailsright {
+ position: absolute;
+ left: 30%;
+ top: 0px;
+ width: 70%;
+ height: 100%;
+ background-color: var(--bgColor3);
+}
+
+.channel {
+ height: 30px;
+ width: 100%;
+ border-bottom: 1px solid #aaaaaa;
+ left: 0px;
+}
+
+.channeldetails {
+ user-select: none;
+ position: absolute;
+ height: 30px;
+ left: 0px;
+ width: 10%;
+}
+
+.channelclips {
+ position: absolute;
+ height: 30px;
+ left: 10%;
+ width: 90%;
+ background-color: var(--bgColor2);
+}
+
+.clip {
+ user-select: none;
+ position: absolute;
+ padding: 0px;
+ cursor: move;
+ z-index: 70;
+ width: 50px;
+ height: 30px;
+ background-color: #CC3333;
+ color: #000000;
+ overflow: hidden;
+}
+</style>
+<script type="text/javascript" src="/code/jquery.js"></script>
+<script type="text/javascript" src="../base/base.js"></script>
+<script type="text/javascript" src="../twirl/twirl.js"></script>
+<script type="text/javascript" src="../base/waveform.js"></script>
+<script type="text/javascript" src="ui-elements.js"></script>
+<script type="text/javascript" src="/code/input-knobs.js"></script>
+<script type="text/javascript">
+
+
+
+var clips = {};
+var channels = [];
+var maxID = 0;
+var chanHeight = 30;
+
+
+function getID() {
+ return maxID++;
+}
+
+
+
+function setupUI(twine) {
+ var ui = {};
+ ui.clip = {
+ audition: new PlayButton({
+ target: "twine_clip_audition",
+ change: function(v, obj) {
+ if (obj.state == true) {
+ twine.selectedClip.play(function(ndata) {
+ if (ndata.status == 0) {
+ obj.setValue(false);
+ app.removeCallback(ndata.cbid);
+ }
+ });
+ } else {
+ app.insertScore("ecpseq_stop");
+ }
+ }
+ }),
+ name: new TextInput({
+ target: "twine_clip_name",
+ change: function(val) {
+ twine.selectedClip.setData("name", val);
+ }
+ }),
+ colour: new ColourInput({
+ target: "twine_clip_colour",
+ change: function(val) {
+ twine.selectedClip.colour = val;
+ }
+ }),
+ warp: new StandardToggle({
+ label: "Warp",
+ target: "twine_clip_warp",
+ change: function(val) {
+ twine.selectedClip.setData("warp", val);
+ twine.selectedClip.setSize();
+ }
+ }),
+ loop: new StandardToggle({
+ label: "Loop",
+ target: "twine_clip_loop",
+ change: function(val) {
+ twine.selectedClip.setData("loop", val);
+ twine.selectedClip.setSize();
+ }
+ }),
+ readType: new ComboBox({
+ target: "twine_clip_readtype",
+ options: [
+ "Repitch", "Grain", "FFTab", "FFT"
+ ],
+ change: function(val) {
+ twine.selectedClip.setData("warpMode", val);
+ },
+ stateAlter: function(val) {
+ twine.ui.clip.fftSize.hide();
+ twine.ui.clip.winSize.hide();
+ twine.ui.clip.winRandom.hide();
+ twine.ui.clip.winOverlap.hide();
+ twine.ui.clip.winType.hide();
+ if (val == 1) {
+ twine.ui.clip.winSize.show();
+ twine.ui.clip.winRandom.show();
+ twine.ui.clip.winOverlap.show();
+ twine.ui.clip.winType.show();
+ } else if (val > 1) {
+ twine.ui.clip.fftSize.show();
+ }
+ }
+ }),
+ amp: new Slider({
+ label: "Gain",
+ valueLabel: true,
+ value: 1,
+ size: 32,
+ target: "twine_clipparamsbottom",
+ changeOnInput: true,
+ change: function(val) {
+ twine.selectedClip.setData("amp", val);
+ }
+ }),
+ pitch: new Slider({
+ label: "Pitch",
+ valueLabel: true,
+ min: -12,
+ max: 12,
+ step: 1,
+ value: 0,
+ size: 32,
+ target: "twine_clipparamsbottom",
+ changeOnInput: true,
+ change: function(val) {
+ var c = twine.selectedClip;
+ var pitch = Math.pow(2, (val / 12));
+ c.setData("pitch", pitch);
+ if (c.warpMode == 0 && c.loop == 0 && c.warp == 0) {
+ c.setSize();
+ }
+ }
+ }),
+ fftSize: new ComboBox({
+ label: "FFT Size",
+ asRow: true,
+ target: "twine_clipparamsbottom",
+ options: [
+ "256", "512", "1024", "2048"
+ ],
+ asValue: true,
+ change: function(val) {
+ twine.selectedClip.setData("fftSize", val);
+ }
+ }),
+ winSize: new Slider({
+ label: "Window size",
+ valueLabel: true,
+ min: 44,
+ max: 4410,
+ step: 1,
+ value: 4410,
+ size: 32,
+ target: "twine_clipparamsbottom",
+ change: function(val) {
+ twine.selectedClip.setData("txtWinSize", val);
+ }
+ }),
+ winRandom: new Slider({
+ label: "Window random",
+ valueLabel: true,
+ min: 0,
+ max: 441,
+ step: 1,
+ value: 441,
+ size: 32,
+ target: "twine_clipparamsbottom",
+ change: function(val) {
+ twine.selectedClip.setData("txtRandom", val);
+ }
+ }),
+ winOverlap: new Slider({
+ label: "Window overlap",
+ valueLabel: true,
+ min: 0,
+ max: 16,
+ step: 1,
+ value: 4,
+ size: 32,
+ target: "twine_clipparamsbottom",
+ change: function(val) {
+ twine.selectedClip.setData("txtOverlap", val);
+ }
+ }),
+ winType: new ComboBox({
+ label: "Window type",
+ asRow: true,
+ target: "twine_clipparamsbottom",
+ options: [
+ "Hanning", "Hamming", "Half sine"
+ ],
+ change: function(val) {
+ twine.selectedClip.setData("txtWinType", val);
+ }
+ })
+ };
+
+ ui.head = {
+ play: new PlayButton({
+ target: "twine_head_play",
+ fontsize: "14pt",
+ change: function(v, obj) {
+ if (obj.state == true) {
+ twine.play();
+ } else {
+ twine.stop();
+ obj.setValue(false);
+ }
+ }
+ }),
+ snap: new StandardToggle({
+ label: "Snap",
+ target: "twine_head_snap",
+ change: function(val) {
+ twine.timeline.snapToGrid = val;
+ }
+ }),
+ grid: new StandardToggle({
+ label: "Grid",
+ target: "twine_head_showgrid",
+ change: function(val) {
+ twine.timeline.gridVisible = val;
+ }
+ })
+ };
+ return ui;
+} // end setupUI
+
+
+var TimelineGrid = function(twine, data) {
+ var self = this;
+
+ if (!data) {
+ var data = {
+ snapToGrid: true,
+ gridVisible: true,
+ timeSigMarker: 4,
+ resolution: null,
+ startBeat: 0,
+ endBeat: 16,
+ bpm: 120
+ };
+ }
+
+ this.getSaveData = function() {
+ return data;
+ };
+
+ function calcViewport() {
+ data.minLeft = (window.screen.width / 100) * 10;
+ var width = window.screen.width - data.minLeft;
+ var beats = data.endBeat - data.startBeat;
+ data.pixelsPerBeat = width / beats;
+ return {
+ minLeft: data.minLeft,
+ width: width,
+ beats: beats,
+ pixelsPerBeat: Math.round(data.pixelsPerBeat)
+ }
+ }
+
+ function draw() {
+ $(".timelinemarker").remove();
+ $(".timelinetext").remove();
+ if (!data.gridVisible) {
+ return;
+ }
+
+ var target = $("#twine_timeline");
+ var geometry = calcViewport();
+
+ var beat = data.startBeat;
+
+ var width;
+ var fontWeight;
+ for (var x = geometry.minLeft; x < window.screen.width; x += geometry.pixelsPerBeat) {
+ if ((beat - 1) % data.timeSigMarker == 0) {
+ width = 2;
+ fontWeight = "bold";
+ } else {
+ width = 1;
+ fontWeight = "normal";
+ }
+ $("<div />").attr("class", "timelinemarker").appendTo(target).css("width", width).css("left", x);
+ $("<div />").attr("class", "timelinetext").appendTo(target).css("font-weight", fontWeight).css("left", x + 2).text(beat);
+ beat ++;
+ }
+ }
+
+ Object.defineProperty(this, "startBeat", {
+ get: function() { return data.startBeat; },
+ set: function(x) {
+ data.startBeat = x;
+ draw();
+ }
+ });
+
+ Object.defineProperty(this, "bpm", {
+ get: function() { return data.bpm; },
+ set: function(x) {
+ data.bpm = x;
+ app.insertScore("ecpweb_setbpm", [0, 1, data.bpm]);
+ }
+ });
+
+ Object.defineProperty(this, "endBeat", {
+ get: function() { return data.endBeat; },
+ set: function(x) {
+ data.endBeat = x;
+ draw();
+ }
+ });
+
+ Object.defineProperty(this, "minLeft", {
+ get: function() { return data.minLeft; },
+ set: function(x) {}
+ });
+
+ Object.defineProperty(this, "pixelsPerBeat", {
+ get: function() { return data.pixelsPerBeat; },
+ set: function(x) {}
+ });
+
+ Object.defineProperty(this, "snapToGrid", {
+ get: function() { return data.snapToGrid; },
+ set: function(x) {
+ data.snapToGrid = (x == 1);
+ }
+ });
+
+ Object.defineProperty(this, "gridVisible", {
+ get: function() { return data.gridVisible; },
+ set: function(x) {
+ data.gridVisible = (x == 1);
+ draw();
+ }
+ });
+
+ var dragHandleTime;
+ function handleMousedown(e) {
+ dragHandleTime = {};
+ dragHandleTime.pageX0 = e.pageX;
+ dragHandleTime.pageY0 = e.pageY;
+ dragHandleTime.elem = this;
+ dragHandleTime.offset0 = $(this).offset();
+ dragHandleTime.selection = $("<div />").addClass("drag_selection").css("left", e.pageX).css("top", e.pageY).appendTo($("#twine_timeline"));
+
+ function handleDrag(e) {
+ var left = dragHandleTime.offset0.left + (e.pageX - dragHandleTime.pageX0);
+ var minLeft = (window.screen.width / 100) * 10;
+
+ if (twine.timeline.snapToGrid) {
+ left = (Math.floor((left - minLeft) / twine.timeline.pixelsPerBeat) * twine.timeline.pixelsPerBeat) + minLeft;
+ }
+
+ if (left < minLeft) {
+ left = minLeft
+ }
+
+ var top = dragHandleTime.offset0.top + (e.pageY - dragHandleTime.pageY0);
+ top = Math.floor(top / chanHeight) * chanHeight;
+ var maxTop = chanHeight * channels.length;
+ if (top > maxTop) {
+ top = maxTop;
+ } else if (top < 30) {
+ top = 30;
+ }
+
+ $(dragHandleTime.elem)
+ .css("height", top - dragHandleTime.pageY0)
+ .css("width", left - dragHandleTime.pageX0);
+
+ }
+
+ function handleMouseUp(e) {
+ $("body")
+ .off("mousemove", handleDrag)
+ .off("mouseup", handleMouseUp);
+ dragHandleTime.selection.remove();
+ }
+
+ $("body").on("mouseup", handleMouseUp).on("mousemove", handleDrag);
+ }
+ //$("#twine_timeline").mousedown(handleMousedown); // selection area
+ draw();
+};
+
+
+var Sequencer = function(twine, data) {
+ var self = this;
+ var gridSnap = 0;
+ var timeScale = 1;
+
+ if (!data) {
+ var data = {
+ tempo: 120,
+ playing: false
+ };
+ }
+
+ this.userImportedFiles = [];
+
+ this.setTempo = function(v) {
+ insertScore("ecpweb_setglobal", [0, 1, 0, v]);
+ };
+
+ this.getSaveData = function() {
+ var sdata = {"sequencer": data, "channels": [], "clips": {}};
+ for (var x in channels) {
+ sdata.channels.push(channels[x].getSaveData());
+ }
+ for (var x in clips) {
+ sdata.clips[x] = clips[x].getSaveData();
+ }
+ return sdata;
+ };
+
+ this.loadSaveData = function(v) {
+ data = v.sequencer;
+ for (var x in v.channels) {
+ new Channel(v.channels[x]);
+ }
+ };
+
+ Object.defineProperty(this, "playing", {
+ get: function() { return data.playing; },
+ set: function(x) {
+ data.playing = x;
+ }
+ });
+};
+
+
+var Channel = function(data) {
+ var self = this;
+ channels.push(this);
+
+ if (!data) {
+ var index = channels.length;
+ var data = {
+ name: "Channel " + index,
+ index: index
+ };
+ } else {
+ var index = data.index;
+ }
+
+ function channelClick() {
+ $("#twine_clipdetails").hide();
+ $("#twine_channeldetailslow").show();
+
+ }
+
+ var element = $("<div />").attr("id", "twine_channel" + index).attr("class", "channel").appendTo("#twine_timeline").append(
+ $("<div />").attr("id", "twine_channeldetails" + index).attr("class", "channeldetails").text(data.name).click(channelClick)
+ ).append(
+ $("<div />").attr("id", "twine_channelclips" + index).attr("class", "channelclips")
+ );
+};
+
+var Clip = function(channel, data, parent) {
+ var self = this;
+ var loaded = false;
+ var hasTwin = (parent) ? true : false;
+ var waveformClip;
+ var waveformEdit;
+ var datatable;
+
+ if (!data) {
+ var id = getID();
+ var data = {
+ name: "Clip " + id,
+ channel: channel,
+ id: id,
+ clipindex: null,
+ playLength: 1,
+ colour: "#" + (Math.random() * 0xFFFFFF << 0).toString(16),
+ position: 0,
+ };
+ }
+
+ clips[data.id] = this;
+ var elWaveEdit = $("<div />").css({width: "100%", height: "100%", top: "0px", left: "0px"});
+
+ var element = $("<div />").attr("class", "clip").attr("id", "clip" + data.id).click(function() {
+ twine.selectedClip = self;
+
+ $("#twine_channeldetailslow").hide();
+ $("#twine_clipdetails").show();
+ var cui = twine.ui.clip;
+ cui.name.setValue(data.name);
+ cui.colour.setValue(data.colour);
+ cui.amp.setValue(data.amp);
+ cui.warp.setValue(data.warp);
+ cui.loop.setValue(data.loop);
+ cui.readType.setValue(data.warpMode);
+ cui.pitch.setValue(Math.round((Math.log(data.pitch) / Math.log(2)) * 12));
+ cui.fftSize.setValue(data.fftSize);
+ cui.winSize.setValue(data.txtWinSize);
+ cui.winRandom.setValue(data.txtRandom);
+ cui.winOverlap.setValue(data.txtOverlap);
+ cui.winType.setValue(data.txtWinType);
+
+ showEditWaveform($("#twine_clipdetailsright"));
+
+ }).css("top", (channel * chanHeight) + "px").css("background-color", data.colour).mousedown(handle_mousedown)
+ .css("left", ((data.position * twine.timeline.pixelsPerBeat)) + "px")
+ .appendTo($("#twine_channelclips" + channel));
+
+ this.el = element;
+ // resizable()
+ var elWaveClip = $("<div />").css({position: "absolute", width: "100%", height: "100%", top: "0px", left: "0px"}).appendTo(element);
+ var elWaveText = $("<div />").css({position: "absolute", width: "100%", height: "100%", top: "0px", left: "0px", "font-size": "var(--fontSizeSmall)", color: "var(--fgColor1)"}).text(data.name).appendTo(element);
+
+
+ Object.defineProperty(this, "colour", {
+ get: function() { return data.colour; },
+ set: function(x) {
+ data.colour = x;
+ element.css("background-color", data.colour);
+ }
+ });
+
+ Object.defineProperty(this, "position", {
+ get: function() { return data.position; },
+ set: function(x) {
+ self.setData("position", x);
+ }
+ });
+
+
+// debug
+this.ddata = data;
+ var dataMode = {
+ fnL: 0,
+ fnR: 1,
+ divisionsPerBeat: 2,
+ duration: 3,
+ beatsLength: 4,
+ utilisedLength: 5,
+ warpMode: 6,
+ pitch: 7,
+ amp: 8,
+ fftSize: 9,
+ txtWinSize: 10,
+ txtRandom: 11,
+ txtOverlap: 12,
+ loop: 13,
+ warp: 14,
+ txtWinType: 15,
+ // warp points are 16 + in table
+
+ position: -1,
+ name: -2,
+ soundPath: -3,
+ channel: -4,
+ clipindex: -5,
+ playLength: -6
+ };
+
+ async function getDataFromTable(key) {
+ async function setFromKey(key) {
+ if (dataMode[key] < 0) return;
+ var value = await app.getCsound().tableGet(datatable, dataMode[key])
+ data[key] = value;
+ }
+
+ for (var k in dataMode) {
+ setFromKey(k);
+ }
+ }
+
+ async function getMarkers() {
+
+ }
+
+
+ this.setData = function(modeString, v, onComplete) {
+ if (dataMode[modeString] < 0) {
+ data[modeString] = v;
+ if (modeString == "name") {
+ elWaveText.text(data.name);
+ }
+ return;
+ }
+
+ function doSetData() {
+ app.getCsound().tableSet(datatable, dataMode[modeString], v);
+ data[modeString] = v;
+ }
+
+ if (hasTwin) {
+ app.insertScore("ecpweb_cloneclip", [0, 1, app.createCallback(function(ndata) {
+ hasTwin = false;
+ data.clipindex = ndata.clipindex;
+ datatable = ndata.datatable;
+ doSetData();
+ if (onComplete) onComplete();
+ })]);
+ } else {
+ doSetData();
+ if (onComplete) onComplete();
+ }
+ }
+
+ this.getPlaybackArgs = function(cbid, time) {
+ return [(time) ? time: 0, 1, cbid, data.clipindex, "mxchan" + (data.channel - 1)];
+ };
+
+ this.play = function(onCallback) {
+ var cbid = app.createCallback(function(ndata) {
+ if (onCallback) onCallback(ndata);
+ }, true);
+ app.insertScore("ecp_playback", self.getPlaybackArgs(cbid));
+ }
+
+ this.loadTest = function() {
+ self.loadFromPath("test.mp3");
+ };
+
+
+ async function getSourceTables() {
+ var wavedata = [];
+ var tbL = await app.getTable(data.fnL);
+ wavedata.push(tbL);
+ if (data.hasOwnProperty("fnR") && data.fnR > 0) {
+ var tbR = await app.getTable(data.fnR);
+ wavedata.push(tbR);
+ }
+ return wavedata;
+ }
+
+ async function setClipWaveform() {
+ if (!waveformClip) {
+ waveformClip = new Waveform({
+ target: elWaveClip,
+ allowSelect: false,
+ showGrid: false,
+ bgColor: "rgb(255, 255, 255, 0)",
+ fgColor: "#000000"
+ });
+ setTimeout(async function(){
+ var sourceTables = await getSourceTables();
+ waveformClip.setData(sourceTables, data.duration);
+ }, 100);
+ } else {
+ waveformClip.redraw();
+ }
+ }
+
+ async function showEditWaveform(target) {
+ target.empty().append(elWaveEdit);
+ if (!waveformEdit) {
+ waveformEdit = new Waveform({
+ target: elWaveEdit,
+ allowSelect: true,
+ showGrid: true,
+ latencyCorrection: twirl.latencyCorrection // , markers:
+ });
+ setTimeout(async function(){
+ var sourceTables = await getSourceTables();
+ waveformEdit.setData(sourceTables, data.duration);
+ }, 100);
+ } else {
+ waveformEdit.redraw();
+ }
+ }
+
+ this.setSize = function() {
+ var beattime = 60 / twine.timeline.bpm;
+ var beatLength;
+ if (data.loop == 0 && data.warp == 0) {
+ if (data.warpMode == 0) {
+ beatLength = data.duration / data.pitch;
+ } else {
+ beatLength = data.duration;
+ }
+ } else {
+ beatLength = data.playLength;
+ }
+ var width = (beatLength / beattime) * twine.timeline.pixelsPerBeat;
+ element.css("width", width + "px");
+ setClipWaveform();
+ }
+
+ this.redraw = function() {
+ self.setSize();
+ };
+
+ this.loadFromPath = function(path, userImported) {
+ var cbid = app.createCallback(async function(ndata) {
+ //await app.unlinkFile(path);
+ if (ndata.status == -1) {
+ return self.errorHandler("File not valid");
+ } else if (ndata.status == -2) {
+ return self.errorHandler("File too large");
+ }
+ datatable = ndata.data.datatable;
+ await getDataFromTable();
+ data.clipindex = ndata.data.clipindex;
+ data.channel = ndata.data.channel;
+ data.name = ndata.data.name;
+ elWaveText.text(data.name);
+ data.soundPath = path;
+
+ if (userImported) {
+ twine.seq.userImportedFiles.push(path);
+ }
+ loaded = true;
+ twirl.loading.hide();
+ self.setSize();
+ });
+ app.insertScore("ecpweb_loadsound", [0, 1, cbid, path, data.channel, data.position]);
+ };
+
+ this.clone = function() {
+ var newdata = Object.assign({}, data);
+ newdata.id = getID();
+ return new Clip(data.channel, newdata, self);
+ };
+
+ this.randomiseWarpPoints = function(mode) { // mode is -1, 0 or 1 I think..
+ if (!mode) mode = 0;
+ var cbid = app.createCallback(function(ndata) {
+ notify("OK");
+ });
+ app.insertScore("ecpweb_randomisewarppoints", [0, 1, cbid, mode]);
+ };
+
+ var dragHandleClip;
+ function handle_mousedown(e){
+ var originalPosition = data.position;
+ dragHandleClip = {};
+ dragHandleClip.pageX0 = e.pageX;
+ dragHandleClip.pageY0 = e.pageY;
+ dragHandleClip.elem = this;
+ dragHandleClip.offset0 = $(this).offset();
+ var isCopying = e.ctrlKey;
+
+ if (isCopying) { // && loaded
+ self.clone();
+ }
+
+ function handle_dragging(e){
+ var left = dragHandleClip.offset0.left + (e.pageX - dragHandleClip.pageX0);
+ var minLeft = (window.screen.width / 100) * 10;
+
+ //round
+ // left = Math.ceil(left / pixelsPerBeat) * pixelsPerBeat;
+
+ if (twine.timeline.snapToGrid) {
+ left = (Math.ceil((left - minLeft) / twine.timeline.pixelsPerBeat) * twine.timeline.pixelsPerBeat) + minLeft;
+ }
+
+
+ if (left < minLeft) {
+ left = minLeft
+ }
+ data.position = twine.timeline.startBeat + ((left - minLeft) / twine.timeline.pixelsPerBeat);
+
+ var header = 50;
+ var top = dragHandleClip.offset0.top + (e.pageY - dragHandleClip.pageY0);
+ top = (Math.ceil(top / chanHeight) * chanHeight) + header;
+ var maxTop = (chanHeight * channels.length) + header;
+
+ if (top > maxTop) {
+ top = maxTop;
+ } else if (top < 30) {
+ top = 30;
+ }
+
+
+ $(dragHandleClip.elem).offset({top: top, left: left});
+ }
+
+ function handle_mouseup(e){
+ $("body")
+ .off("mousemove", handle_dragging)
+ .off("mouseup", handle_mouseup);
+ if (data.position != originalPosition) {
+ self.setData("position", data.position);
+ }
+ }
+
+ $("body").on("mouseup", handle_mouseup).on("mousemove", handle_dragging);
+ }
+
+ if (parent) {
+ self.redraw();
+ }
+};
+
+function runTest() {
+ new Channel();
+ new Channel();
+ new Channel();
+ new Channel();
+ new Channel();
+ new Channel();
+}
+
+var topMenuData = [
+ {name: "File", contents: [
+ {name: "New", disableOnPlay: true, shortcut: {name: "Ctrl N", ctrlKey: true, key: "n"}, click: function(twine) {
+ twine.createNewInstance();
+ }},
+ {name: "Save", disableOnPlay: true, shortcut: {name: "Ctrl S", ctrlKey: true, key: "s"}, click: function(twine) {
+ twine.saveFile();
+ }},
+ {name: "Close", disableOnPlay: true, shortcut: {name: "Ctrl W", ctrlKey: true, key: "w"}, click: function(twine) {
+ twine.closeInstance();
+ }},
+ ]},
+ {name: "Help", contents: [
+ {name: "Help", click: function(twine){
+ $("#twist_documentation")[0].click();
+ }},
+ {name: "About", click: function(twine) {
+ twine.ui.showAbout();
+ }},
+ ]}
+];
+
+
+var Twine = function() {
+ twirl.init();
+ var twine = this;
+ var playing = false;
+ this.onPlays = [];
+ this.selectedClip = null;
+ this.clipUpdates = true;
+ this.timeline = new TimelineGrid(twine);
+ this.seq = new Sequencer(twine);
+ this.topMenu = new twirl.TopMenu(twine, topMenuData, $("#twine_menubar"));
+ this.ui = setupUI(twine);
+
+ twine.ui.head.grid.setValue(1, true);
+ twine.ui.head.snap.setValue(1, true);
+
+ this.setPlaying = function(state) {
+ playing = state;
+ };
+
+ this.play = function() {
+ if (playing) return;
+ twine.setPlaying(true);
+ var time;
+ var reltime;
+ var maxtime = 0;
+ var beatTime = 60 / twine.timeline.bpm;
+ for (var c in clips) {
+ time = clips[c].position;
+ if (time >= twine.timeline.startBeat && time <= twine.timeline.endBeat) {
+ reltime = time - twine.timeline.startBeat;
+ if (reltime + clips[c].duration > maxtime) {
+ maxtime = reltime + clips[c].duration;
+ }
+ app.insertScore("ecp_playback", clips[c].getPlaybackArgs(-1, reltime * beatTime));
+ }
+ }
+ var cbid = app.createCallback(function() {
+ twine.setPlaying(false);
+ });
+ app.insertScore("ecpweb_playbackwatchdog", [0, maxtime, cbid]);
+ };
+
+ this.stop = function() {
+ if (!playing) return;
+ app.insertScore("ecpweb_stopplayback");
+ };
+
+ async function handleFileDrop(e) {
+ e.preventDefault();
+ twirl.loading.show();
+ for (const item of e.originalEvent.dataTransfer.files) {
+ if (!twirl.audioTypes.includes(item.type)) {
+ return self.errorHandler("Unsupported file type", self.ui.showLoadNewPrompt);
+ }
+ if (item.size > twirl.maxFileSize) {
+ return self.errorHandler("File too large", self.ui.showLoadNewPrompt);
+ }
+
+ errorState = "File loading error";
+ var content = await item.arrayBuffer();
+ const buffer = new Uint8Array(content);
+ await app.getCsound().fs.writeFile(item.name, buffer);
+ var x = new Clip(1); // determine channel
+ x.loadFromPath(item.name, true);
+ twirl.loading.hide();
+ }
+ }
+
+ var tempclip = null;
+ $("body").on("dragover", function(e) {
+ e.preventDefault();
+ e.originalEvent.dataTransfer.effectAllowed = "all";
+ e.originalEvent.dataTransfer.dropEffect = "copy";
+
+ if (!tempclip) {
+ tempclip = $("<div />").addClass("clip").text("New Clip");
+ $("#twine_timelineoverlay").show().append(tempclip);
+ }
+
+ tempclip.css("top", e.pageY + "px").css("left", e.pageX + "px");
+
+ return false;
+ }).on("dragleave", function(e) {
+ e.preventDefault();
+ $("#twine_timelineoverlay").hide();
+ if (tempclip) tempclip.remove();
+ }).on("drop", function(e) {
+ $("#twine_timelineoverlay").hide();
+ if (tempclip) tempclip.remove();
+ handleFileDrop(e);
+ });
+};
+
+
+$(function() {
+ window.twine = new Twine();
+
+ window.app = new CSApplication({
+ csdUrl: "twine.csd",
+ files: ["test.mp3"],
+ csOptions: ["--omacro:ECP_NORECORDING=1"],
+ onPlay: function () {
+ runTest();
+ twirl.loading.hide();
+ },
+ errorHandler: twirl.errorHandler,
+ ioReceivers: {percent: twirl.loading.setPercent}
+ });
+
+ $("#start_invoke").click(function() {
+ $("#start").hide();
+ twirl.loading.show();
+ app.play(function(text){
+ twirl.loading.show(text);
+ });
+ });
+
+
+
+
+
+});
+/*
+divisionsPerBeat: 2,
+ duration: 3,
+ beatsLength: 4,
+ utilisedLength: 5,
+ warpMode: 6,
+ pitch: 7,
+ amp: 8,
+ fftSize: 9,
+ txtWinSize: 10,
+ txtRandom: 11,
+ txtOverlap: 12,
+ loop: 13,
+ warp: 14,
+ txtWinType: 15,
+*/
+</script>
+</head>
+<body>
+<div id="start">
+ <div id="start_centre">
+ <p id="start_invoke">Press to begin</p>
+ </div>
+</div>
+
+<div id="twine_header">
+ <table id="twine_headertable"><tbody><tr>
+ <td id="twine_head_play"></td>
+ <td id="twine_head_snap"></td>
+ <td id="twine_head_showgrid"></td>
+ </tr></tbody></table>
+</div>
+<div id="twine_menubar"></div>
+<div id="twine_main">
+ <div id="twine_timeline"></div>
+ <div id="twine_timelineoverlay"></div>
+ <div id="twine_details">
+ <div id="twine_channeldetailslow"></div>
+ <div id="twine_clipdetails">
+ <div id="twine_clipdetailsleft">
+ <table><tbody>
+ <tr>
+ <td id="twine_clip_audition"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td id="twine_clip_colour"></td>
+ <td id="twine_clip_name"></td>
+ <td></td>
+ <td></td>
+ </tr>
+ </tbody></table>
+ <table><tbody>
+ <tr>
+ <td>Read type</td>
+ <td id="twine_clip_readtype"></td>
+ <td id="twine_clip_warp"></td>
+ <td id="twine_clip_loop"></td>
+ </tr>
+ </tbody></table>
+ <table><tbody id="twine_clipparamsbottom">
+ </tbody></table>
+ </div>
+ <div id="twine_clipdetailsright"></div>
+ </div>
+ </div>
+</div>
+</body>
+</html>
\ No newline at end of file |