question: adding control elements using another language

Discuss Lemur and share techniques.
marinus
Newbie
Posts:13
Joined:21 Feb 2012 13:28
Location:Rotterdam
Contact:
question: adding control elements using another language

Post by marinus » 04 Oct 2012 08:51

Hola!

A while ago I started working on a method of using SuperCollider to build automatically an control interface according to the content of the EnvirGui class or basicaly a dictonary. For each instance of the EnvirGui class I am able to build an interface on a page.

The problem is I encountered some strange behaviour when building realtime a control surface on the lemur using SuperCollider. It seems that sometimes I can build interefaces with no problems, but sometimes the program gets stuck. I tried various solution like to slow down the loop that is used to build the interface. But then still I get dropouts of the lemur app. I also use exactly the same code the lemur-editor sends over a tcp connection while adding a control element (for instance a slider) to the lemur-app.

Is there a way to view on the ipad why the lemur-app keeps crashing? Are there any thing I have to keep in mind with?

Ik can send the SuperCollider pseudo class of list if it's needed.

Many thnx,
Grt,Marinus

Macciza
Regular
Posts:1325
Joined:07 Dec 2011 04:57
Location:Sydney, Australia.

Re: question: adding control elements using another language

Post by Macciza » 04 Oct 2012 09:54

Hi
Yes you would need dto send us the SC project to have a look at
Cheers
MM
iMac 2.8G i7 12G 10.6.8/10.7.2, Legacy Dexter/Lemur, Liine Lemur/iPad2, KMI SoftStep, 12Step & QuNeo , B-Controls, Mackie C4 etc
MaxMSP, Live Suite, Native Instrument stuff, etc Modified Virtual Guitar System etc All Projects/Modules © CC-BY-NC-SA[*][/b]

marinus
Newbie
Posts:13
Joined:21 Feb 2012 13:28
Location:Rotterdam
Contact:

Re: question: adding control elements using another language

Post by marinus » 05 Oct 2012 08:03

I just sended the code to you off-list. many thnx in advance! grt,marinus

marinus
Newbie
Posts:13
Joined:21 Feb 2012 13:28
Location:Rotterdam
Contact:

Re: question: adding control elements using another language

Post by marinus » 13 Oct 2012 15:33

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");
)

nitefish
Regular
Posts:56
Joined:24 Aug 2012 07:43

Re: question: adding control elements using another language

Post by nitefish » 14 Oct 2012 07:45

It works!!
I have to adapt sizes since i just own an IPod touch :oops:

I also get an error message in the post window:

ERROR:OSCmessages must have type tags.


But it works,I have four pages with three sliders on the Lemur.
Thank you for sharing,Marinus!

marinus
Newbie
Posts:13
Joined:21 Feb 2012 13:28
Location:Rotterdam
Contact:

Re: question: adding control elements using another language

Post by marinus » 24 Oct 2012 08:23

Thnx!

I going make a slider size option for building on iphone or iPad. Anyway you can also build seperate sliders yourself want.

Unfortunately I still have the problem that I don't know what source of the problem is why the building get's stuck. Especially when I build multiple pages with 10 sliders. Once lemur gets stuck even restarting the program and cleaning up supercollider,
the problem stays.

Is there a way to get a crash report on the Ipad or Iphone? What do you guys advice what I should check while debugging?

Grt,marinus

nitefish
Regular
Posts:56
Joined:24 Aug 2012 07:43

Re: question: adding control elements using another language

Post by nitefish » 24 Oct 2012 17:15

a lot of links on Gogole about crash reports.The first:
http://stackoverflow.com/questions/4325 ... sh-reports

I'm always looking for a basic example of "classic" communication between Liine Lemur and SuperCollider with the new sc/osc system (I'm still using the old Lemur class found on the Jazzmutant site,I'm french and unable to find a method)...

Anton
Regular
Posts:75
Joined:08 Dec 2011 12:36

Re: question: adding control elements using another language

Post by Anton » 25 Oct 2012 07:32

this is super interesting work you guys are doing! keep us up to date.

marinus
Newbie
Posts:13
Joined:21 Feb 2012 13:28
Location:Rotterdam
Contact:

Re: question: adding control elements using another language

Post by marinus » 25 Oct 2012 08:54

This is could maybe be an basic example:

// It's the most basic usage to get osc in SuperCollider.
// important is that to send messages from lemur to your computer ip and to sc-lang port. set this up in lemur.

// when you set the adress to nil it will listen to all devices it receives. this can be filter out with the netaddr object.
// anyway in the help file of the OSCFunc class more elaborate examples are given of this.

// from multi devices but only receives when the packets have the same /cmdname.
~responder = OSCFunc({|msg|
msg.postln; // osc message and do whatever
}, '/cmdname');

// update a lemur parameter
~tolemur = NetAddr("ip addr", port);
~tolemur.sendMsg('cmdname', value);


It would be cool to here some idea's from the people from Liine about this. Also on debugging on creating templates on lemur using SuperCollider code I have written.

When I have some time left I will look into the crash reports thing with itunes and iPad and keep you people updated with that.

grt, marinus

nitefish
Regular
Posts:56
Joined:24 Aug 2012 07:43

Re: question: adding control elements using another language

Post by nitefish » 25 Oct 2012 10:26

Yeeah!
Thank you,I've got a good starting point,even for re-reading the SC help files.

Post Reply