New Tool (3.0,3.1): xStream

Btw: you also mentioned you had encountered some bugs?

I’m a big fan of using the github issue tracker.

If you click the following link, you will see that they are also organized in milestones (xStream 1.6 and 2.0, at time of writing):

https://github.com/renoise/xrnx/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20xstream

Yep. xStream is currently hard-coded to the selected track. Again, this is something that would change in the planned version

(I would like to add as a sidenote: it’s nice how your questions align so nicely with those plans ^_^)

How much longer until this plan comes to action? I need a multitrack xStream man!!! :frowning: But seriously, I had a ton of fun with it this weekend, but was annoyed at how my bass line AND my drum sequence couldn’t be auto-composed simultaneously. My crappy suggestion for a temporary solution: allow a model to ‘go in the background’. Like, it maintains control over (and continues editing the pattern data of) a certain track, but it is inaccessible to the user while they have another model open. So they can’t edit the first model, or mess with the arguments GUI of that model.

Then, perhaps all running models would be on a track-by-track basis. One model per track. And when I select another track, it opens up the model assigned to that one. Not a big request at all, i know. :smiley:

In other problems-i’ve-been-running-into: How does one edit a model in the Renoise scripting console?

However, I have been toying with an idea which would enable you to edit xstream files outside Renoise. I think this is actually a much more convenient thing, because no matter how much how we tweak the text editor in Renoise, most people who are dabbling with this tool probably have a text editor that they prefer anyway. So I see no reason why xStream shouldn’t benefit from that. Hell, you could even use the Renoise scripting console then, if you wanted to (I know some people do ^_^)

If I open up my model in the console, it’s in that sandbox section, which is a big block comment. Thus, there’s no syntax highlighting. Not much of an improvement over the tiny black and white text in the xStream console.

But this isn’t even the worse issue. When I do save changes that I made in the Renoise scripting console, the current instance of xStream suddenly closes. I have to open it and my model back up to try and execute the new code. But instead of my new code being there, my model is instead a blank canvas. It’s still inside the Renoise editor, but not in the xStream one. So I have to copy and paste it from the Renoise editor to the xStream one.

I’ve noticed this sometimes only happens if my new code has a syntax error. If it doesn’t, sometimes the model won’t be blank when I open it back up. I’d be more than happy to go back and figure out/report on the exact behavior of all this if you’d like.

But not a big issue. Just making you aware. I’m perfectly fine with the xStream editor in the meantime. Also weird: if I make a change in the xStream editor (and save), it does not update those changes in the Renoise editor. Haven’t tried with other editors yet. I think this also had that syntax error peculiarity.

Second issue I’ve been having is that I get this error:

*** Error: please review the callback function - .\source/xLib/classes/xEffectColumn.lua:216: Unexpected effect number. Expected two bytes between 0-35 respectively

It prints this constantly (in the renoise console) when I run this one model I’ve been using. But it’s updating the effect columns just fine. I can send you the model and the song. Should I zip it?

Final issue, another weird error:
*** Expected an instance of xline for output - sequence: 4 line: 46

I also get this persistently when running my models. Sometimes, I get it and no track data is written to. Not until I click and change some args (eg, click a ‘choose’ button, move a minislider, etc.) will it then start putting out track data. And sometimes the error then goes away. Sometimes it doesn’t.

One question: Is this worth pursuing?

I want to use Ruby array methods in xStream. I was thinking I would get these methods to work in a C program by calling the Ruby method as an external function to the C program. Then, I would try to get a Lua program to call a C function, which then just calls the Ruby method. Would this be recommended in xStream? Any problems as far as performance issues?

If not, I’d like to get that working. Array manipulation is easy peesy in Sonic Pi because of all the different methods there were. I’d like that in xStream. Otherwise, I’ll probably just write them myself. Would there be any performance issues if I wrote them in C and called the C functions in xStream?

Also, thanks again for this amazing tool. It’s inspired me to start making music consistently. Before, I’d make something like, 3 times max a year. Now I’m pumping out another thing every other week. And they’re all miles better than what I had made before.

How much longer until this plan comes to action?

My roadmap includes a new “stable” release shortly, without the multi-track/model feature, but featuring all the improvements that I and joule have discussed above.
And then, development will switch to github for a while, which means that you could try out early versions and provide a bit of feedback.

How does one edit a model in the Renoise scripting console?

Yes, coding in that tiny tool window is a bit claustrophobic. But for now, it’s really what we got.
But you’ve just convinced me that I should try sneaking this feature into the next release, because I also feel that pain:
https://forum.renoise.com/t/new-tool-3-0-3-1-xstream/44430

Second issue I’ve been having is that I get this error:
*** Error: please review the callback function - .\source/xLib/classes/xEffectColumn.lua:216: Unexpected effect number. Expected two bytes between 0-35 respectively
It prints this constantly (in the renoise console) when I run this one model I’ve been using. But it’s updating the effect columns just fine. I can send you the model and the song. Should I zip it?
Final issue, another weird error:
*** Expected an instance of xline for output - sequence: 4 line: 46
I also get this persistently when running my models. Sometimes, I get it and no track data is written to. Not until I click and change some args (eg, click a ‘choose’ button, move a minislider, etc.) will it then start putting out track data. And sometimes the error then goes away. Sometimes it doesn’t.

(First one) yes please - zipped or non-zipped, you decide.
(Second one) hmmm… not sure, but so many things can go wrong.It happens only with your own models? Then, PM please :slight_smile:

One question: I want to use Ruby array methods in xStream.

That would essentially be an extension of the Renoise API, if you wanted the performance too. Otherwise it will be really clunky and (probably) have quite an overhead.
But curious as to what those handy methods are - lua is completely table based, so quite powerful for arrays too.
And perhaps some of these methods are readily available elsewhere, as vanilly lua libraries? That would make things quite simple then.

It’s inspired me to start making music consistently. Before, I’d make something like, 3 times max a year. Now I’m pumping out another thing every other week. And they’re all miles better than what I had made before.

Hey - this is 10x better than a “thankyou” note. Really means a lot to me :wub:

Trying to get my own functions/libraries working right now.Correct me if I’m wrong about anything. Also, feel free to tell me to get out and ask my questions in the beginner’s scripting forum if my questions are too easy/annoying. :rolleyes:

.

Everything that gets included with xStream is specified in themain.lua But - that doesn’t mean that you can just starting referencing functions and method from within the xStream “main method” (the processing method that transforms pattern data, not to be confused with the “main.lua” file, which is simply the entry point for any renoise tool.

Okay, just so we’re on the same page, this means that I can’t just do require statements like you did in main.lua?

Is there any way to include libraries? Do I just put a simple #include “lib.h” at the top of the code?

Everything that gets included with xStream is specified in the main.lua But - that doesn’t mean that you can just starting referencing functions and method from within the xStream “main method” (the processing method that transforms pattern data, not to be confused with the “main.lua” file, which is simply the entry point for any renoise tool.

This is so, because xStream wraps the main method in a lua sandbox - which makes certain variables (e.g. the all-important xinc) available to the model, while also hiding potentially ‘dangerous’ things like file system access.

In order to benefit from method in your own files, you need to explicitly define sandbox accessors to your own properties and methods. If it sounds complicated, it’s not - just a question of opening and modifying the file called xStreamModel.lua.

So I gotta figure out this sandbox stuff I guess.

I see the renoise scripting page for cSandbox.lua. In it, it says that to supply functions to the sandbox, you do what it says to do in those examples at the very top. There’s also a “to do” for how to include properties in a sandbox.

I’m mentioning this in the context of xStreamModel.lua. Seems like all the xStream user-end stuff that is ‘given’ to the sandbox is in that ‘props_table’ table. Then immediately following the definition of props_table (lines 127-309), you have the line self.sandbox.properties = props_table (line 311). I’m guessing that each of the member definitions in prop_table are supposed to make calls to the functions in “…/source/xLib/classes” (and elsewhere)?

Should I just copy what you did there and make my own folder in “/source/…” with all my own properties? Seems messy (and I’m probably wrong).

Could I just add a singular property to props_table that (when called in xStream) points to a .lua file that will act as the foundation for my user library?

  • Eg, have a property “myLib” in props_table. Implement it just like the others.
  • In myLib.lua, I have require statements to more libraries (eg, lib1, lib2).
  • Then, I (somehow) make it where if I want to use a function in lib1, i just do “myLib.lib1.member_func” in the xStream console.

Or even better, can I skip the whole “editing xStreamModel.lua” by instead adding require statements to some Renoise file? :smiley: probably not… This just seems daunting to me. Not sure where to start.

(First one) yes please - zipped or non-zipped, you decide.

(Second one) hmmm… not sure, but so many things can go wrong.It happens only with your own models? Then, PM please :slight_smile:

Will definitely get to this later. Gotta go to class rn. Thanks again!

Could I just add a singular property to props_table that (when called in xStream) points to a .lua file that will act as the foundation for my user library?

  • Eg, have a property “myLib” in props_table. Implement it just like the others.
  • In myLib.lua, I have require statements to more libraries (eg, lib1, lib2).
  • Then, I (somehow) make it where if I want to use a function in lib1, i just do “myLib.lib1.member_func” in the xStream console.

Or even better, can I skip the whole “editing xStreamModel.lua” by instead adding require statements to some Renoise file? :smiley:

Yep (eh, or nope, depending on how you read it). xStreamModel is based on cSandbox, and as such, acting as the “gatekeeper”. This is so, so some script kiddie can’t just share a model which tries to wipe peoples harddrive. Copy-paste is handy, but there’s the downside. You see, the tool itself has access to file system and such :slight_smile:

But adding your class should indeed expose it’s methods and properties to xStream - the recommended approach, anyway. Many roads lead to Rome.

And, just a quick tip: if you want/need your file to be a class instance, then you could specify it as “userdata” - because, creating a class instance within the main loop in xStream would cause it to be redefined, over and over again…

So I’m finally trying to start adding my own code to xStream.

And, just a quick tip: if you want/need your file to be a class instance, then you could specify it as “userdata” - because, creating a class instance within the main loop in xStream would cause it to be redefined, over and over again…

Just to make sure, does this mean there are only two ways to add user code to xStream?

(1) by adding a property (which is my module) to the sandbox in “xStreamModel.lua” like I described earlier (which means its required in main.lua as well)

(2) by “specifying it as userdata” as you mentioned

Also technically (3): adding a sandbox function (ie, with sandbox.str_prefix/suffix).

How do I do method (2)? Do you mean to just add my module like any model in the “./userdata” folder?

I was able to get method (1) to work just fine. But like you said, if I instantiate an object from my own class, it’ll be re-instatiated over and over as xStream traverses the pattern.

This got me thinking about how xStream compiles/executes its code.

In any xStream model, when does the user code get evaluated? I’m guessing that for every line traversed, xStream evaluates the entire code. More specifically, it does load(sandbox)(or whatever) at every pattern line.

But what about the classes in the xModel.lua sandbox? Let’s say I call ‘xLine’ in my code. Does xStream precompile the bytecode for xLine, and it just ‘calls’ the parts it needs to when xLine is called (in my code)? Or does the xLine module get recompiled every time it gets called (along with the sandboxed code)?

I’m assuming it’s the same if I add my own module using method (1).

What is different about adding my module as “userdata”? I’m guessing that xStream pre-compiles my module. And when I call a function from it, it’ll jump to the already compiled and loaded bytecode.

I really should get a better grasp on the compiler and enviroment before I start asking questions like this…

But I’m asking because it seems like I could use method (1) for single-use functions, and I’d stick with method (2) if I wanted to make a class system.

I plan on making a big class system that’ll stream-line writing xStream models (or just Renoise scripts in general). Before I start getting into it I wanna make sure I put the right code in the right place.

(2) by “specifying it as userdata” as you mentioned

Ehrm, sorry, let me clarify this:
→ data is referring to data that you want to reference in your loop. You can add an initial value using the “+”, or simply define them on-the-go.
→ userdata is referring to a custom path, so you specify a folder somewhere outside the tool folder. Avoids that your models get overwritten on tool updates and such.

They are not related in any way - no precompile step or anything clever like that. But originally, they were both named userdata.
You’re not the first one to get confused by this

In any xStream model, when does the user code get evaluated? I’m guessing that for every line traversed

Yep. The same line can even get evaluated multiple times, if an argument that has been set to “re-buffer” has changed it’s value.

But what about the classes in the xModel.lua sandbox?

It depends. Most of xStream/xLib are based on static methods, and reside in the global variable space(in the scripting console. try entering rprint(_G) and see a complete listing of what is available. Doing the same in xStream will reveal nothing, because it’s hidden/sandboxed).Static methods are usually preferred over instances, as they don’t need to be instantiated - they are already there. But obviously, you will sometimes need an object that specifies it’s own properties - a ClassName() will allow you create a new class instance. Luckily, garbage collection in lua is pretty efficient so it doesn’t matter _that_much.

Btw: I’m hoping to get the next version finished soon, sounds like you have some good ideas lined up :slight_smile:

Ehrm, sorry, let me clarify this:
→ data is referring to data that you want to reference in your loop. You can add an initial value using the “+”, or simply define them on-the-go.
→ userdata is referring to a custom path, so you specify a folder somewhere outside the tool folder. Avoids that your models get overwritten on tool updates and such.

They are not related in any way - no precompile step or anything clever like that. But originally, they were both named userdata.
You’re not the first one to get confused by this

More confused now actually, lol :rolleyes:

Okay, so userdata is just that userdata folder, where user models are kept. Nothing else, right?

What is data now? Is it self.data in xStreamModel.lua(line 85)?

I guess I didn’t clearly state what I’m wanting to do. I want to be able to instantiate an object from a class, to use in my xStream model. But I shouldn’t do that inside of the model because of the problems mentioned before. So where do I put my class, and where should I instantiate the object?

Come to think of it, it’s probably fine for me to put the class in the xStreamModel.lua sandbox. It’s just initializing the object is what I’m having trouble with.

In my fantasy world, I could do this to instantiate an object:

S,L = xpos

if (S==1 and L==-1) then

obj = MyClass:new()

obj.notes = {4,8,11}

end

So we would never hit line -1, but we’d still enter the if block somehow…

Also, do my classes absolutely have to be luabind classes? This is what’s recommended according to theclasses.luasnippet. Not to mention it’s what xStream classes are made with.

When I was putting classes in the xStreamModel.lua sandbox, they were working both as luabind and ‘ordinary’ lua classes. (‘ordinary’ class being where the class is the metatable for the object).

Instead of trying to explain the concept, I would suggest you take a look at some of the models that make use of “data”, such as the arpeggiator or LFO?

They both take advantage of the feature to add helper methods, are being initialized with specific values, etc.

Essentially, data is just there for convenience, a way to access and define numbers/tables/functions/etc, so you can keep the main loop clean and focused.

In theory, you could define your (non-luabind) classes there too.

As for adding your own objects to the sandbox, I simply regard this as yet another way to achieve the same result.

The difference would of course be, that whatever you add to the sandbox would be accessible across all models.

Also, do my classes absolutely have to be luabind classes? This is what’s recommended according to theclasses.luasnippet. Not to mention it’s what xStream classes are made with.

When I was putting classes in the xStreamModel.lua sandbox, they were working both as luabind and ‘ordinary’ lua classes. (‘ordinary’ class being where the class is the metatable for the object).

I’m using them throughout, but you don’t have to. There are tradeoffs and advantages to using either approach.

For example, you can’t use the __index meta method in luabind - which is required for some of the more advanced techniques (the sandbox is therefore also not a luabind object).

Luabind, on the other hand, offers a clean syntax and the ability to specify handy getter/setter methods.

In my fantasy world, I could do this to instantiate an object:

S,L = xpos

if (S==1 and L==-1) then

obj = MyClass:new()

obj.notes = {4,8,11}

end

So we would never hit line -1, but we’d still enter the if block somehow…

Praise be the lambda calculus…I’m onto something

I was thinking if I had some kind of latch - which would allow the if conditional to evaluate to true only once - then the if block would only execute once.

All thanks to closures, I can define a function that : returns a 0 the first time its called, butnil for any successive calls:

latch2nil = function()

latch = function (val)

if val then

val = nil

return 0

else

return nil

end

end

i = 0

return latch(i)

end

And then in my xStream model, I put something like this:

if (xinc==latch2nil()) then

print(“I’m only here once :(”)

end

Now, the if block executes only once! At least, until I hit the play button in xStream again.

Gotta love how lua functions have lexical scoping. I guess I could get the same result without using closures, but this is much nicer.

I’m gonna keep playing around with this to see what I can get away with…

— EDIT : —

That latch2nil function is really sloppy. Here’s a better version:

latch2nil = function()

local latch = function (val)

if val then

val = nil

return 0

end

end

local i = 0

return latch(i)

end

Instead of trying to explain the concept, I would suggest you take a look at some of the models that make use of “data”, such as the arpeggiator or LFO?

I’ll definitely look at that, thanks!

But because of what I just came up with (the latching function), I’m gonna start with this instead:

My class modules are all xStreamModel sandbox properties.

Any objects I instantiate will be done using that latching function.

The only problem is if I want my object’s notes/delays to maintain states between each xStream session. I’ll figure that out later though. Gotta do what’s easy first.

So now I’ll stop bothering you. At least for a little while… :stuck_out_tongue:

Alright, well I lied. I’m back.

So, I’m trying to add my own classes via sandbox properties in xStreamModel.lua. I’m having trouble adding more than one source file.

I want to add a single class, eg “HelloClass.lua”. Just to make sure this is a legitimate strategy, I put all the steps I used to accomplish this:

Click to view contents
  • I make a folder “myLibrary” in the xStream tool folder: “~/source/myLibrary/”.

  • (I’m gonna use ‘~’ as shorthand for “com.renoise.xStream.xrnx”)

  • I add the source file"HelloClass.lua" to the folder.

  • in main.lua, I add these two lines (at about line 23) :
    _ulibroot = ‘source/myLibrary/’
    require (_ulibroot…‘HelloClass’)
    –require (_ulibroot…‘HelloClass2’)

  • I add a corresponding key to the sandbox properties in xStreamModel.lua. The steps of how I do that are:

  • I figured that I’d imitate what you did for xLFO in the definition of props_table in xStreamModel.lua.

  • So for the class xLFO:

  • So xLFO is a class in “~/source/xLib/classes/”.

  • xLFO is a key in props_table (line 305). (props_table is declared at line 127).

  • For my class HelloClass:

  • I imitate what I see for “xLFO”, by adding a key “HelloClass” to props_table.

  • The final code in xStreamModel.lua looks something like this:

["xPhraseManager"] = {
      		access = function(env) return xAudioDevice end,
    	},
    	["xLFO"] = {
      		access = function(env) return xLFO end,
    	},
		
		
	["HelloClass"] = { 
		access = function(env) return HelloClass end 
	},
	-- ["HelloClass2"] = { 
	-- access = function(env) return HelloClass2 end 
	-- },
		
  }

The code for HelloClass.lua is this:

Click to view contents
local HelloClass = {}

function HelloClass:init() --call this before using this class 
	print("resetting object count")
	self.objcount = 0
end

function HelloClass:new(init)
	print("Calling HelloClass:new()")	--used to warn user of accidental multiple calls
	
	init = init or {}
	setmetatable(init, self)
	self.__index = self
	
	self.objcount = self.objcount + 1
	init.objnum = self.objcount
	
	return init
end

function HelloClass:give_intro()	
	print("Calling HelloClass:hello()")
	if self == HelloClass then
		print("I'm the class HelloClass! I have "..tostring(HelloClass.objcount).." child objects!" ..
						"\n\tI'm located at "..tostring(self) )
	else
		print("I'm object number "..tostring(self.objnum).." from HelloClass! \n\tI'm located at "..tostring(self) )
	end
end

function HelloClass:say_hi()
	print("hi! hello!")
end

Basically, it just counts the number of objects instantiated, and prints out table locations.
I used this to get an idea of how xStream would behave when creating objects from my user-defined classes.

So yes, this did work! I was able to use it in an xStream model, with some success. There were issues with it, such as number of objects created. But I wanna ignore that for now.

The issue I’m having is that I can’t add more source files like this.

I want to add another class, “HelloClass2”, which is exactly the same as “HelloClass” - except there’s a ‘2’ anywhere after ‘HelloClass’. I repeat all those steps above (and those related lines for HelloClass2 are un-commented). When I try to refresh the tools/open up xStream again, I get this error message:
*** main.lua:168: attempt to index field ‘preferences’ (a nil value)
*** stack traceback:
*** main.lua:168: in function main.lua:166

*** Could not attach to sample - none selected

I tried this again by making HelloClass a luabind class. Same results.

So yeah, is what I’m trying to do okay? I won’t break xStream by doing this for a bunch of source files?

Or am I being way too stubborn, and I should stop begging you for help every day? :smiley: But seriously, I won’t take offense, haha. I’ve actually been looking up ViewBuilder stuff. Just to see how hard it would be to make my own version of xStream… if I can’t make this work.

I think you’re experiencing some of the same issues as I’ve come across. Basically, that xStream is such a large tool that some internal limitations/restrictions in lua are starting to apply.

https://forum.renoise.com/t/new-tool-3-0-3-1-xstream/44430

Still not sure exactly what triggers the problem, but, hm, I do know of a workaround: removing key shortcut /midi mappings from the main.lua file.

At least, that has worked until now and hopefully, will be enough until we can solve this issue properly (as in: compile the built-in lua component with the ability to load more resources)

Basically, that xStream is such a large tool that some internal limitations/restrictions in lua are starting to apply.

Whoah, no way! That’s nuts.

Still not sure exactly what triggers the problem, but, hm, I do know of a workaround: removing key shortcut /midi mappings from the main.lua file.
At least, that has worked until now and hopefully, will be enough until we can solve this issue properly (as in: compile the built-in lua component with the ability to load more resources)

just to be absolutely sure, this is what you mean?

Click to view contents

I Found this other version of main.lua that you linked to in a post on page 5:

I’m not getting that error, but maybe I have an idea - try replacing main.lua with this version?

attachicon.gifmain.lua

I’ll assume that I can do the same in the current version of xStream. That is: comment out everything after line 160.

…Assuming that everything after line 160 inmain.luais exclusively just the keyboard/midi mapping functions.

…Which I just did, and it worked! This will be totally fine for me, since I’m not using midi or keyboard mappings right now.

But that is “scary” as others mentioned on page 5. Is this issue with the lua compiler just in Renoise? Or is this with lua in general? (doubt it). Hopefully this can be an easy fix. I’m just afraid that the multi-track update will ‘take up more resources’, leaving me with less to room to include my own stuff. :o

Wish I could pitch in somehow too, with the code.This is definitely becoming my ‘best girl’ for making music, lol. Is there a donate link for xStream??

Yeah, there’s some cool nerd-factor to hitting this ceiling (xStream == extreme), but that doesn’t really comfort me.

Problem is, the reason is still unknown. I’ve done a bit of research on the topic, but not much has come up.

Is this issue with the lua compiler just in Renoise? Or is this with lua in general? (doubt it).

Well, all these runtimes would be compiled to some setting or the other. I think our settings are even a bit less restrictive than most.

But it’s true that it makes it a little more daunting to “just add stuff on top” when you know that, somewhere, something might break.

I have a request/idea… maybe it could be called xLight :blink:

The idea is that xStream could be stripped of many things (including most of its gui and midi handling), for the purpose of only using the generative/sandbox part as easily accessible presets.

A simple user case example:

  1. Right click the pattern editor.
  2. Navigate to context menu “xLight presets:”
  3. Select stuff like “Pad every 4th line with C-4 and the currently selected insrument” (but with shorter names). Or “Transform chords to Axx arps” et c

These presets would be the same as xStream sandbox code, and could potentially operate on either patterntrack or track in song or selection.

The clever thing with the xStream framework in this case is that its presets can act as either purely generative models, or “filters” that you parse your already tracked data thru. Both scenarios very useful - and with presets accessible by only a few mouseclicks in the pattern editor context menu.

I don’t imagine that this would “compete” with xStream, but rather make more users intrigued by it.

(details: I imagine that it would also be good to have some requester callback accessible from the sandbox, to prompt the user for simple input values when needed)

I have a request/idea… maybe it could be called xLight :blink:

And it should work with pattern aliases too? :slight_smile:

Hehe.

But seriously, I’m open to that idea. Live streaming is a special focus of xStream, and granted, that’s not everybody’s cup of tea.

Pattern aliases aren’t a problem as it wouldn’t be realtime or streaming, but just one-shot like the render buttons in current xStream.

It shouldn’t be difficult to list the presets in a context menu - and then load+trigger xstream.process:fill_track() or fill_selection() ?

A small tick box in the model could state if it should be listed in the pattern editor menu. This would be for the more “simpler” models that don’t require a GUI - or perhaps just a single user value as input. Maybe the tick box would state if the full-blown xStream GUI will be brought up on menu selection or not. These models would then be listed with “…” appended in the menu.

This should be rather simple to do, I imagine? Maybe just a matter of avoiding ui:show() + building the proper menus.

Just a couple of quick things. Feature requests actually. :slight_smile:

table.unpack isn’t usable in an xStream model.

I’m wanting to use it in my library, but I’m having to resort to making my own version of it.

Could there be a button that toggles the console messages for syntax errors?

Or maybe press a button to get the most recent error message. I just hate how there’s a bunch of useless error messages every time I type out a new, valid statement.

In other news, my hacky way of adding my code to xStream is coming along smoothly-ish. I have the whole thing required in one file, which I only need a single require for in main.lua. Then I avoid the weird error from requiring more than one file. So now I can keep MIDI and key mappings! Haven’t tried them out yet though.

table.unpack isn’t usable in an xStream model.

AFAIK, unpack isn’t available as a method of the table. Have you tried using just unpack ?

And I know that the error logging is a bit excessive. It’s nice to have, but most of the time it’s just adding noise.

I’ll look closer at, with regard to the whole “external editing” workflow. Ideally, I would like to use the scripting console or something like Sublime to edit the source.