From 3f64c2f52797390c6561b76a46579485002e3181 Mon Sep 17 00:00:00 2001 From: Josef Schauer Date: Sun, 6 Apr 2014 22:05:46 +0000 Subject: player_relativ weit diff --git a/RHMixxx1280x800/MixxController.js b/RHMixxx1280x800/MixxController.js new file mode 100644 index 0000000..0a26df2 --- /dev/null +++ b/RHMixxx1280x800/MixxController.js @@ -0,0 +1,363 @@ +function MixxxController(id) { + this.midiMappings = new Object(); + this.namedMappings = new Object(); + this.controls = new Object(); + this.id = id; + + /* + * Convenience method that returns a Mixxx value for the given control + */ + this.getMixxxValue = function(control) { + return engine.getValue(control["group"]["name"], control["name"]); + } + + /* + * Sets a Mixxx value for the given control. If a coversion has been + * registered, it is taken into account. This method also takes care + * of softTakeover, if enabled. + */ + this.setMixxxValue = function(control, value) { + var conversion = control["conversion"]; + if (conversion) { + if (conversion["name"] != "none") { + value = script[conversion["name"]](value, conversion["min"], conversion["max"], conversion["mid"]); + } + } + else { + value = script["absoluteNonLin"](value, 0, 1, 4); + } + if (control["softTakeover"] && (Math.abs(this.getMixxxValue(control) - value) < 0.1)) + { + control["softTakeover"] = false; + } + else if (!control["softTakeover"]) { + engine.setValue(control["group"]["name"], control["name"], value); + control["value"] = value; + } + } + + /* + * Convenience method that returns a control based on its midi number. + */ + this.getByMidiNo = function (midiNo) + { + return this.midiMappings[midiNo]; + } + + /* + * Convenience method that returns a control based on its group and control. + */ + this.getByNames = function(group, control) + { + return this.namedMappings[group+control]; + } + + /* + * Creates a multi button that supports klicking and turning. + * Parameters are: + * # Mixxx value that is set if button is klicked (may be empty if button cannot be pressed) + * # Midi number + * # Mixxx value that is set if button is turned left + * # Mixxx value that is set if button is turned right + */ + this.createMultiButton = function(name, id, left, right) + { + var button = this.createControl(name, id); + button.setConversion("none"); + button["isMultiButton"] = true; + button["left"] = left; + button["right"] = right; + return button; + } + + /* + * Creates a button that executed a Mixxx function without having a concrete + * state (e.g. the beatsync button). + * Parameters are: + * # Mixxx value that is set if button is klicked + * # Midi number + */ + this.createButton = function(name, id) + { + var button = this.createControl(name, id); + button.setConversion("none"); + button["isButton"] = true; + return button; + } + + /* + * Creates a switch that can be switches on and off (e.g. the play button). + * Parameters are: + * # Mixxx value that is toggled if switch is pressed + * # Midi number + */ + this.createSwitch = function(name, id) + { + var button = this.createControl(name, id); + button.setConversion("none"); + button["activated"] = false; + button["isSwitch"] = true; + return button; + } + + /* + * Creates a control that can be used for volume sliders, filter knobs, etc. + * Parameters are: + * # Mixxx value that is changed if the control is used + * # Midi number + * Various behaviours can be enabled on a control: + * # enableFireOnKeyUp() (control is fired if released, not if pressed. Useful for buttons/switches) + * # enableSoftTakeover() (custom softTakeover function that is some smarter than Mixxx's default implementation) + * # addCallback() (add a MixxxController callback. Currently available is only "kill" to emulate a kill switch for equalizers) + * # addExternalCallback() (add a callback to a custom function specific for a certain controller) + * # setConversion(name, min, max, mid) (supported: absoluteLin, absoluteNonLin) + * headVolume, Master volume, crossfader, headMix and volume are automatically enhanced with a fitting conversion. + */ + this.createControl = function(name, id) + { + var control = new Object(); + control["name"] = name; + control["midiNo"] = id; + control["ledMidiNo"] = id; + control["callbacks"] = new Object(); + control["fireOnKeyUp"] = false; + this.midiMappings[id] = control; + control.enableFireOnKeyUp = function() { + control["fireOnKeyUp"] = true; + return control; + } + control.enableSoftTakeover = function() { + control["softTakeover"] = true; + return control; + } + control.addCallback = function(name) { + control["callbacks"][name] = name; + return control; + } + control.addCallback = function(name) { + control["callbacks"][name] = name; + return control; + } + control.addExternalCallback = function(name) { + control["externalCallbacks"][name] = name; + return control; + } + control.setConversion = function(name, min, max, mid) { + control["conversion"] = new Object(); + control["conversion"]["name"] = name; + control["conversion"]["min"] = min; + control["conversion"]["max"] = max; + control["conversion"]["mid"] = mid; + return control; + } + control.setLEDMidiNo = function(id) { + control["ledMidiNo"] = id; + return control; + } + return control; + } + + /* + * Create a new control group to which multiple controls can be added. A control must have a name that matches + * the Mixxx group ([Master], [Channel1], ...) + */ + this.createGroup = function(name, id) + { + var group = new Object(); + group["name"] = name; + if (name.indexOf("[Channel") == 0) { + group["id"] = name.substring(8, 9); + } + group["controller"] = this; + group["scratching"] = false; + group["scratchingEnabled"] = false; + group.addControl = function(control) { + group[control["name"]] = control; + control["group"] = this; + group["controller"].namedMappings[group["name"]+control["name"]] = control; + + if (control["softTakeover"]) { + control["value"] = group["controller"].getMixxxValue(control); + engine.connectControl(group["name"], control["name"], this["controller"].id+".softTakeover"); + } + if (control["name"] == "play") { + engine.connectControl(group["name"], control["name"], this["controller"].id+".playListener"); + } + for (var callback in control["callbacks"]) { + engine.connectControl(group["name"], control["name"], this["controller"].id+"."+callback); + } + for (var callback in control["externalCallbacks"]) { + engine.connectControl(group["name"], control["name"], callback); + } + + var name = control["name"]; + if (name == "headVolume") { + control.setConversion("absoluteNonLin", 0, 5, 1); + } else if ((group["name"] == "[Master]") && (name == "volume")) { + control.setConversion("absoluteNonLin", 0, 5, 1); + } else if (name == "crossfader") { + control.setConversion("absoluteLin", -1, 1); + } else if (name == "headMix") { + control.setConversion("absoluteLin", -1, 1); + } else if (name == "volume") { + control.setConversion("absoluteLin", 0, 1); + } + + return group; + } + this[name] = group; + return group; + } + + /* + * Enabled softTakeover on a control if the controllers value differs to much from Mixxx's state. + * This can be the case on startup of mix or if a control has been modified inside of Mixxx, + * if beatsync has been used, ... + */ + this.softTakeover = function(value, group, control) { + var controller = this["controller"]; + var control = controller.getByNames(group, control); + if (Math.abs(control["value"] - value) > 0.1) { + control["softTakeover"] = true; + } + } + + /* + * If a controller has no eq kill switch, this method can be used to kill frequencies + * if a knob has been moved to zero. To enable this feature, use .addCallback("kill") + * on the created control before adding it to its group. + */ + this.kill = function(value, group, control) { + var controller = this["controller"]; + var control = controller.getByNames(group, control); + if (controller.getMixxxValue(control) == 0) { + engine.setValue(control["group"]["name"], control["name"]+"Kill", 1); + } else if (engine.getValue(control["group"]["name"], control["name"]+"Kill") == 1) { + engine.setValue(control["group"]["name"], control["name"]+"Kill", 0); + } + } + + /* + * This callback is added to the play state and toggles of the play buttons led if needed. + */ + this.playListener = function (value, group, control) { + var controller = this["controller"]; + var control = controller.getByNames(group, control); + controller.led(controller.getMixxxValue(control), control["group"]["name"], control["name"]); + control["activated"] = (controller.getMixxxValue(control) == 1); + } + + /* + * Switch a led for a control on or off. + */ + this.led = function (value, group, control) { + var led = this.getByNames(group, control)["ledMidiNo"]; + if (value == 1) { + midi.sendShortMsg(0x90, led, 0x7F); + } else if (value == 0) { + midi.sendShortMsg(0x90, led, 0x0); + } + } + + /* + * This method must be called from a concrete controller script to get the cow flying. + */ + this.dispatch = function (c, midi, value, status) { + var control = this.getByMidiNo(midi); + if (control["isButton"]) { + this.handleButton(control, value); + } else if (control["isSwitch"]) { + this.handleSwitch(control, value); + } else if (control["isMultiButton"]) { + this.handleMultiButton(control, value); + } else if (control["name"] == "jogWheel") { + this.wheelTurn(c, midi, value, status); + } else { + this.setMixxxValue(control, value); + } + } + + /* + * This method handles multiButtons. + */ + this.handleMultiButton = function (control, value) { + if (value == 127) { + engine.setValue(control["group"]["name"], control["name"], 1); + } else if (value == 0x3f) { + engine.setValue(control["group"]["name"], control["left"], 1); + } else { + engine.setValue(control["group"]["name"], control["right"], 1); + } + } + + /* + * This method handles buttons. + */ + this.handleButton = function (control, value) { + if (value == 0) { + this.led(0, control["group"]["name"], control["name"]); + } else { + this.led(1, control["group"]["name"], control["name"]); + } + if ((control["fireOnKeyUp"] && (value == 0)) || (!control["fireOnKeyUp"] && (value == 127))) { + this.setMixxxValue(control, 1); + } else { + this.setMixxxValue(control, 0); + } + } + + /* + * This method handles switches. + */ + this.handleSwitch = function (control, value) { + if ((control["fireOnKeyUp"] && (value == 0)) || (!control["fireOnKeyUp"] && (value == 127))) { + if (control["name"] == "scratch") { + var group = control["group"]; + group["scratchingEnabled"] = !group["scratchingEnabled"]; + if (group["scratchingEnabled"]) { + this.led(1, control["group"]["name"], control["name"]); + } else { + this.led(0, control["group"]["name"], control["name"]); + } + } else if (control["activated"]) { + this.setMixxxValue(control, 0); + this.led(0, control["group"]["name"], control["name"]); + } else { + this.setMixxxValue(control, 1); + this.led(1, control["group"]["name"], control["name"]); + } + control["activated"] = !control["activated"]; + } + } + + /* + * This method handles a jog wheel for scratching. + */ + this.wheelTurn = function (channel, control, value, status) { + var control = Mixage.controls.getByMidiNo(control); + var group = control["group"]; + // See if we're scratching. If not, just return. + if (!group["scratchingEnabled"]) return; + + if (!group["scratching"]) { + var alpha = 1.0/8; + var beta = alpha/32; + engine.scratchEnable(group["id"], 128, 100, alpha, beta); + } + + // Register the movement + var ramp = (value - 64); + engine.scratchTick(group["id"], ramp); + group["scratching"] = true; + // This two timers check if you are still scratching and disable + // the function if not. + engine.beginTimer(20, function() { + group["scratching"] = false; + engine.beginTimer(20, function() { + if (!group["scratching"]) { + engine.scratchDisable(group["id"]); + } + }, true); + }, true); + } +} diff --git a/RHMixxx1280x800/skin.xml b/RHMixxx1280x800/skin.xml index 2678747..eb50400 100755 --- a/RHMixxx1280x800/skin.xml +++ b/RHMixxx1280x800/skin.xml @@ -150,7 +150,7 @@ WSearchLineEdit { background: #cfdee7; color: #000000; } title 1 0,1 - 315f,30 + 275,30 - + + 455,56 + + Channel volume meter Shows the left channel of player 1 volume Volume_long_over_player.png Volume_long_player.png - 455,68 + 0,30 false 5 500 @@ -716,7 +722,7 @@ WSearchLineEdit { background: #cfdee7; color: #000000; } clipping_long_over_player.png clipping_long_player.png - 455,38 + 0,0 [Channel1],PeakIndicator @@ -727,7 +733,7 @@ WSearchLineEdit { background: #cfdee7; color: #000000; } clipping_long_over_player.png clipping_long_player.png - 475,38 + 20,0 [Channel1],PeakIndicator @@ -739,7 +745,7 @@ WSearchLineEdit { background: #cfdee7; color: #000000; } Volume_long_over_player.png Volume_long_player.png - 475,68 + 20,30 false 5 500 @@ -749,7 +755,8 @@ WSearchLineEdit { background: #cfdee7; color: #000000; } [Channel1],VuMeterR - + + - - + ********************************************** -- cgit v0.10.2