Last active
August 29, 2015 14:06
-
-
Save Lokua/09b6f56442864ff5f2c3 to your computer and use it in GitHub Desktop.
max for live audio input routing helper script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2014 Joshua Kleckner, http://lokua.net | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
var Logger = new Global('Logger'), | |
log = Logger.log, | |
err = Logger.err; | |
Logger.on = true; // set to `true` to enable debugging | |
log('\t\tHello from audio-input-router.js version 1.0.2 | contact: [email protected]'); | |
autowatch = 1; | |
inlets = 2; | |
outlets = 2; | |
var api, | |
routes = [], | |
currentRouteIndex = 0, | |
subRoutes = [], | |
OBJ_COUNT = 32, | |
routesMenu = patcher.getnamed('routesMenu'), | |
subRoutesMenu = patcher.getnamed('subRoutesMenu'), | |
subRoutesGate = patcher.getnamed('subRoutesGate'); | |
/** | |
* Data structure to hold sub_routes and last stored index | |
* | |
* @param {String} sub_routes api path input_sub_routings | |
* @param {Number} index the last selected sub_route from live.menu | |
*/ | |
function SubRoute(sub_routes, index) { | |
this.sub_routes = sub_routes; | |
this.index = index || 0; | |
} | |
/** | |
* @return {String} the last stored sub_route | |
*/ | |
SubRoute.prototype.last = function() { | |
return this.sub_routes[this.index]; | |
} | |
SubRoute.prototype.toString = function() { | |
return 'sub_routes: ' + this.sub_routes + ', index: ' + this.index; | |
} | |
/** | |
* (re)initialize and populate everything | |
*/ | |
function bang() { | |
// set-up LiveAPI | |
api = new LiveAPI(_highlightCurrent, 'this_device canonical_parent'); | |
this_name = api.get('name'); | |
api.property = 'current_input_routing'; | |
if (inlet === 0) { | |
_clear(); | |
_configureRoutesAndSubRoutes(); | |
_populateRoutesMenu(); | |
_populateSubRoutesMenu(); | |
} | |
// update the proxy routesMenu current item | |
routesMenu.message('set', api.get('current_input_routing')); | |
log('initialized'); | |
} | |
function _clear() { | |
routes = []; | |
subRoutes = []; | |
for (var i = 0; i < OBJ_COUNT; i++) { | |
var mess = 'message_'+i, | |
mobj = patcher.getnamed(mess); | |
mobj.message('set'); | |
mobj.message('hidden', 1); | |
patcher.getnamed('button_'+i).message('hidden', 1); | |
} | |
} | |
/** | |
* populate the routes and corresponding subRoutes arrays. | |
* This excludes the track this device is on and tracks that have their | |
* output set to 'None'. | |
*/ | |
function _configureRoutesAndSubRoutes() { | |
routes.push('Ext. In'); | |
subRoutes.push(new SubRoute(['1/2', '1', '2'], 0)); | |
routes.push('Resampling'); | |
subRoutes.push(new SubRoute(['none'])); | |
_pushType('tracks'); | |
_pushType('return_tracks'); | |
routes.push('Master'); | |
subRoutes.push(new SubRoute(['Pre FX', 'Post FX', 'Post Mixer'], 2)); | |
routes.push('No Input'); | |
subRoutes.push(new SubRoute(['none'])); | |
api.path = 'this_device canonical_parent'; | |
} | |
/** | |
* Internal helper used in _configureRoutesAndSubRoutes | |
* | |
* @param {String} type 'return_tracks' or 'tracks' | |
*/ | |
function _pushType(type) { | |
api.path = 'this_device canonical_parent'; | |
var this_name = api.get('name'); | |
for (var i = 0, len = api.getcount(type); i < len; i++) { | |
api.path = 'live_set ' + type + ' ' + i; | |
name = api.get('name').toString(); | |
hasOut = api.get('current_output_routing') != 'None'; | |
if ((this_name != name) && hasOut) { | |
routes.push(name); | |
var sr = new SubRoute(['Pre FX', 'Post FX', 'Post Mixer'], 2); | |
subRoutes.push(sr); | |
} | |
} | |
} | |
/** | |
* fills the UI messages and corresponding proxy menu with input routes; | |
* adjusts device and panels widths to reflect visible button/message columns. | |
* Requires that routes have been configured. | |
*/ | |
function _populateRoutesMenu() { | |
var deviceWidth = 222, // min width including update+about column and first routes column | |
i = 0, len = routes.length; | |
for (; i < len; i++) { | |
var mess = 'message_'+i, | |
mobj = patcher.getnamed(mess); | |
mobj.message('set', routes[i]); | |
mobj.message('hidden', 0); | |
routesMenu.message('append', routes[i]); | |
patcher.getnamed('button_'+i).message('hidden', 0); | |
if (i && i % 8 === 0) deviceWidth += 130; | |
} | |
// adjust widths to reflect visible columns | |
patcher.getnamed('this_device').message('setwidth', deviceWidth); | |
patcher.getnamed('panel').message('presentation_rect', 8, 6, deviceWidth-18, 158); | |
} | |
/** | |
* populate the subRoutesMenu with the current inputs corresponding sub_routes. | |
* Requires the subRoutes index to correctly match currentRouteIndex | |
*/ | |
function _populateSubRoutesMenu() { | |
var r0 = subRoutes[_updateCurrentRouteIndex()].sub_routes[0]; | |
// this input route does not have sub_routes ("Resampling" or "No Input") | |
if (r0 == 'none') { | |
subRoutesMenu.message('activebgcolor', 0, 0, 0, 0); | |
subRoutesMenu.message('textcolor', 0, 0, 0, 0); | |
subRoutesMenu.message('ignoreclick', 1); | |
return; | |
} | |
subRoutesMenu.message('_parameter_range', sr); | |
subRoutesMenu.message('activebgcolor', 0.05, 0.91, 0.91, 1); | |
subRoutesMenu.message('textcolor', 0, 0, 0, 1); | |
subRoutesMenu.message('ignoreclick', 0); | |
} | |
/** | |
* highlights the currently active route message object; | |
* un-highlights the rest | |
*/ | |
function _highlightCurrent() { | |
if (api && api.type != 'Track') return; | |
var current = api.get('current_input_routing'), | |
i = 0, len = routes.length, m; | |
for (; i < len; i++) { | |
m = patcher.getnamed('message_'+i); | |
m.message('textcolor', 0, 0, 0, 1); | |
if (routes[i] == current) { | |
m.message('textcolor', 0.05, 0.91, 0.91, 1); | |
} | |
} | |
} | |
/** | |
* @return {Number} the current index of the route (as placed in proxy menu) | |
*/ | |
function _updateCurrentRouteIndex() { | |
if (routes === undefined) return currentRouteIndex; | |
var current_input_route = api.get('current_input_routing'), | |
i = 0, len = routes.length; | |
for (; i < len; i++) { | |
if (routes[i] == current_input_route) { | |
currentRouteIndex = i; | |
return currentRouteIndex; | |
} | |
} | |
return currentRouteIndex; | |
} | |
/** | |
* Set this tracks audio input route, configure corresponding | |
* sub_route. | |
* | |
* @param {String} route the current input_route selected | |
* @param {Number} index the current item index from routesMenu | |
*/ | |
function setroute(route, index) { | |
_closeGate(); | |
api.path = 'this_device canonical_parent'; | |
api.set('current_input_routing', route); | |
currentRouteIndex = index; | |
_populateSubRoutesMenu(); | |
_openGate(); | |
subRoutesMenu.message('symbol', subRoutes[index].last()); | |
} | |
/** | |
* close subRoutesGate to avoid calling setsubroutes when | |
* populating the menu | |
*/ | |
function _closeGate() { | |
subRoutesGate.message(0); | |
} | |
function _openGate() { | |
subRoutesGate.message(1); | |
} | |
/** | |
* This is an incoming message from the subRoutesMenu. Sets this track's sub_route. | |
* | |
* @param {String} sub the sub_route | |
* @param {Number} index the sub_route index (not to be confused with route index), | |
* which will be stored for later updating when the main route changes | |
* ( subRoutes[currentRouteIndex].index ) | |
*/ | |
function setsubroute(sub_route, index) { | |
api.set('current_input_sub_routing', sub_route + ''); | |
subRoutes[currentRouteIndex].index = index; | |
} | |
function _debug() { | |
log('_debug >>'); | |
log('\tapi > input_routings: {0}', api.get('input_routings')); | |
log('\tapi > input_sub_routings: {0}', api.get('input_sub_routings')); | |
log('\tapi > current_input_routing: {0}', api.get('current_input_routing')); | |
log('\tapi > current_input_sub_routing: {0}', api.get('current_input_sub_routing')); | |
log('\tcurrentRouteIndex: {0}', currentRouteIndex); | |
log('\troutes: {0}', routes); | |
subRoutes.forEach(function(r, i) { | |
log('\tsubRoutes[{0}].toString(): {1}', i, r.toString()); | |
}); | |
log('\troutes[currentRouteIndex]: {0}', routes[currentRouteIndex]); | |
log('\tsubRoutes[currentRouteIndex]: {0}', subRoutes[currentRouteIndex]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment