Hola!
Here is the code I written to build the gui elements on lemur realtime. Basically while building the pages templates lemur will drop out. I don't no if miss a particular xml command or something. The dropouts are also quite random. I can build onto 5 pages full of sliders and sometimes not even three slider on a page. I have no clean-up functions implemented but with cmd . the oscrespondernodes stops working when using 3.6 alpha-3.
It been a while since I started to code it. But due the program gets stuck from time to time I haven't looked at it for a while.
http://new-supercollider-mailing-lists- ... 04665.html
How can I debug this on the iPad when lemur gets stuck due to building using sc-language code? I am missing xml messages here or I am building to fast?
First evaluate the code between brackets to load the pseudo class. The code below is for building several pages with sliders from the content of envirgui).
Thnx! Marinus
// three main functions to build automatically are: buildEnvir -> auto_add -> add_object
// the reset message clears lemur-app.
// there are no clean functions implemented to remove object.gui_objects oscrespondernodes
// object.gui_objects = [[ Fader, stream3_Fader_2, freq, an OSCresponderNode ], etc]
(
// lemur communication pseudo object.
~lemur_gui = ~lemur_gui ? ();
~lemur_gui.makePage = { |object, name|
var message = [ '<COPY>',
'<WINDOW class="JAZZINTERFACE" text="%"/>'
.asString.format(name),
'</COPY>'];
object.pagename = name.asString;
object.send_packet(message);
};
~lemur_gui.tcp_connect = { |object, ip="192.10.1.2", port1=8002, port2=8000|
object.tcp_addr = NetAddr(ip,port1);
object.tcp_addr.connect;
object.osc_addr = NetAddr(ip, port2);
};
~lemur_gui.tcp_disconnect = { |object|
if (object.tcp_addr != nil,
{
object.tcp_addr.disconnect;
object.tcp_addr = nil;
},
{ "first make connection by using the message .tcp_connect!".postln;}
);
};
~lemur_gui.osc_disconnect = { |object|
if (object.tcp_addr2 != nil, {
object.osc_addr.disconnect;
object.osc_addr = nil; },
{ "first make connection with .tcp_connect!".postln; });
};
// counts and puts elements in the right order
~lemur_gui.auto_add = { |object,class,name,envirgui,index|
var x,y,width,height,cmdname,message;
x = object.object_width * index.asInt + 10;
y = 10;
width = object.object_width;
height = object.object_height;
cmdname = "%_%_%".format(object.pagename,class,index).asSymbol;
if ( index.asInt >= 10, { "not more than 10 objects are possible now".postln; ["now:", index].postln; },
{ object.add_object(class,name,cmdname,index,x,y,width,height);
object.gui_objects.add([class,cmdname,name,
object.responder(cmdname,class,name,envirgui),
]);
"New object is added:\n%\n\n".postf(object.gui_objects.last); });
};
// basic function to add a
~lemur_gui.add_object = { |object,class,name,cmdname,id,x,y,width,height |
// lines of xml code are concatinated before sending to device via tcp with send_packet
var message;
r {
message = [
'<WINDOW class="JAZZINTERFACE" text="%">'
.asString.format(object.pagename),
'<COPY>',
'<WINDOW class="%" text="%" x="%" y="%" width="%" height="%" group="0" id="%"/>'
.asString.format(class,cmdname,x,y,width,height,id),
'</COPY>',
'</WINDOW>'];
object.send_packet(message);
0.05.wait; // 50 ms wait time between message.
message = [
'<WINDOW class="JAZZINTERFACE" text="%">'
.asString.format(object.pagename),
'<COPY>',
'<WINDOW class="Text" text="%" x="%" y="%" width="%" height="50" group="0" state="245" content="%"/>'
.asString.format(cmdname ++ \text,x,y+20,width,name),
'</COPY>',
'</WINDOW>'];
object.send_packet(message);
nil }.play;
};
~lemur_gui.reset_interface = { |object|
// reset lemur and set lemur app scheme name, remove responder and empty list
object.send_packet([
'<RESET/><OSC request="1"/><SYNCHRO mode="0"/><PROJECT title="pattern autogui"',
' version="3030" width="1024" height="724" osc_target="-2" midi_target="-2" kbmouse_target="-2"/>'
]);
if (object.gui_objects.size > 0, {
object.gui_objects do: { |i| i[3].remove };
object.gui_objects = List.new;
});
};
~lemur_gui.set_osctarget = { |object,target_number=0,ip_host="192.10.1.16",port=57120|
object.send_packet(['<OSC target=\"%\" ip=\"%\" port=\"%\"/>'
.asString.format(target_number,ip_host,port)]);
};
~lemur_gui.send_packet = { |object,message| var packet = "";
message do: { |statement|
packet = packet ++ statement;
};
object.tcp_addr.sendMsg("/jzml",packet.ascii.add(0).as(Int8Array));
};
~lemur_gui.responder = { |object,cmdname,type,key,envirgui|
var return,map,val;
return = OSCresponderNode(nil,asSymbol(cmdname ++ "/x").postln , { |t,r,msg|
case
{ type == \Fader; }
{ val = msg[1]; }
{ type == \Range; }
{ val = [msg[1],msg[2]]};
if ( envirgui.getSpec(key) == nil, {
val = ControlSpec.specs[key].map(val); }, {
val = envirgui.getSpec(key).map(val); });
{ envirgui.envir[key] = val; }.defer;
}).add;
return; // connect and return responder.
};
// when this function is cakled the interface on the lemur-app will be automatically filled.
~lemur_gui.buildEnvir = { | object, event, envirgui, pagename, width = 100 |
object.object_width = width;
object.object_height = 700;
object.gui_objects = List.new;
r {
object.makePage(pagename);
0.2.wait; // wait time.
r {
event.order do: { |key, index|
var type, class = event[key].class;
case
{ (class == Float) || (class == Integer) }
{ type = \Fader; }
{ class == Array }
{ type = \Range; };
object.auto_add(type,key,envirgui,index); // add object sends 2 packets with 0.05 ms interval
0.11.wait; // wait 2 * 50 ms plus a bit extra time.
};
}.play(AppClock);
nil;
// object.update_LemurFromEnvir // should be added later to set sliders
}.play(AppClock);
};
// updates slider values.
~lemur_gui.update_LemurFromEnvir = { |object, event, envirgui|
event.order do: { |key, index|
var val = envirgui.envir[key];
if ( envirgui.getSpec(key) == nil, {
val = ControlSpec.specs[key].unmap(val); "top level spec".postln; }, {
val = envirgui.getSpec(key).unmap(val); });
case
{ (class(val) == Float) || (class(val) == Integer) }
{ object.osc_addr.sendMsg("/%_Fader_%/x".format(object.pagename,index).postln,val); }
{ class(val) == Array; }
{ object.osc_addr.sendMsg("/%_Range_%/x".format(object.pagename, index).postln,val[0],val[1]); };
};
};
);
// set instructions to connect and clear the lemur-app.
// set ipad ip and ports
~lemur_gui.tcp_connect("192.10.1.2",8002,8000);
// set ip of the device lemur should send osc to (this computer)
~lemur_gui.set_osctarget(0,"192.10.1.16",57120);
// clear app to start building.
~lemur_gui.reset_interface;
(
// template 1
~envgui1 = EnvirGui.new(nil, 4, parent: nil, bounds: Rect(100,100, 500, 200));
~envgui1.putSpec(\freq, \freq.asSpec);
~envgui1.putSpec(\amp, [0,1.0]);
~envgui1.putSpec(\dur, [0.02,1,\exp]);
~envgui1.object_((freq: 100, amp: 0.1, \dur: 0.1));
~lemur1 = ~lemur_gui.copy; // copies psuedo object to new environemnt
~lemur1.buildEnvir(~envgui1.envir, ~envgui1, "stream1");
)
(
// template 2
~envgui2 = EnvirGui.new(nil, 4, parent: nil, bounds: Rect(100,100, 500, 200));
~envgui2.putSpec(\freq, \freq.asSpec);
~envgui2.putSpec(\amp, [0,1.0]);
~envgui2.putSpec(\dur, [0.02,1,\exp]);
~envgui2.object_((freq: 100, amp: 0.1, \dur: 0.1));
~lemur2 = ~lemur_gui.copy; // copies psuedo object to new environemnt
~lemur2.buildEnvir(~envgui2.envir, ~envgui2, "stream2");
)
(
// template 3
~envgui3 = EnvirGui.new(nil, 4, parent: nil, bounds: Rect(100,100, 500, 200));
~envgui3.putSpec(\freq, \freq.asSpec);
~envgui3.putSpec(\amp, [0,1.0]);
~envgui3.putSpec(\dur, [0.02,1,\exp]);
~envgui3.object_((freq: 100, amp: 0.1, \dur: 0.1));
~lemur3 = ~lemur_gui.copy; // copies psuedo object to new environemnt
~lemur3.buildEnvir(~envgui3.envir,~envgui3,"stream3");
)
(
// template 4
~envgui4 = EnvirGui.new(nil, 4, parent: nil, bounds: Rect(100,100, 500, 200));
~envgui4.putSpec(\freq, \freq.asSpec);
~envgui4.putSpec(\amp, [0,1.0]);
~envgui4.putSpec(\dur, [0.02,1,\exp]);
~envgui4.object_((freq: 100, amp: 0.1, \dur: 0.1));
~lemur4 = ~lemur_gui.copy; // copies psuedo object to new environemnt
~lemur4.buildEnvir(~envgui4.envir, ~envgui4, "stream4");
)