Lua for GrandMA3 Episode 3 - Command Line Interaction
Hey lighting folks! The following is the transcript from my YouTube video, Lua for MA3 Ep 3 - Command Line Interaction
This video is part of my Lua for GrandMA3 Tutorial series. Please check out my channel, From Dark To Light, on YouTube, and you can find the code to go along with my tutorials here on GitHub.
Hello lighting people! Welcome back to my Lua for GrandMA3 tutorial series! While I do need to continue explaining how Lua works, I decided for today to take a break from that and show you an important, simple MA3 function and just explain some things about the MA3 system and how it uses code. I may or may not use this information a ton in examples in the next few videos, but I do know that having this knowledge will help you start putting things together to build your own plugins as soon as I give you the concepts in the next few videos.
So what are we actually talking about today? We're actually talking about how to do major normal functions of MA3 using Lua. Now of course there's a lot more in-depth stuff that you can do with Lua that you cannot do without it, but a lot of times when you're using Lua, maybe in place of a macro or something, some parts of what you need to do either must be done in the command line or would be best done through the command line, but you're in the middle of a Lua script rather than a macro, so how are you going to do that? Well, don't worry, because MA3 has several built-in Lua functions that can be used to interact with the regular command line. I'm going to introduce two of these and then show you the difference.
Now I'm going to write out the names of both of these basic functions that I mentioned. One of them is called Cmd and the other one is CmdIndirect. So both of these are going to take one argument: the string you want to put in the command. For example I'll just do one now, ‘Label Sequence 1 “Test.”’
If you're familiar with how the regular command line interaction works and writing commands then basically it just needs to be a valid command for MA3. I'm actually going to name this one “Test 2” and put the same thing in here without the 2.
Alright, now I have these two functions; they're very similar, I'm just going to run this plugin in MA3 and as you can see it executed both commands just as it would if you used the regular command without any Lua involved.
Now at first glance you would think that both of these functions are doing the exact same thing, but look over here at the system monitor. One says “Lua” before the command and the other one says “MainTask.” What exactly does this mean? Well, I'll explain. So the system has a couple of different tasks that can be used simultaneously and are not accessed the same way. The main task is for all of your normal user interaction and the normal command line of macros and all that. The Lua task is for, well, running Lua functions, but the system task designated for Lua can totally interact with the regular command line as well, it's just only capable of doing tasks given through Lua. Now you might be wondering why it matters whether you're running a command in the main task or in the Lua task, and actually it took me a while to really understand this, but it's simple, so I'm just going to tell you.
If you run a command in the Lua task and it fails, let's say, because of a syntax error or an addressed object not existing, the command will actually cause the Lua script to halt and not be able to proceed. You'll get an error and the entire remainder of your code will simply not be executed.
So if you run the command in the main task everything will be great, right? The command is sent to the main task, your Lua script keeps running, errors won't hurt you…
So actually there's a problem with using the main task as well and that is that Lua runs a lot faster than regular console operation, so let's say you have a command for the console in line 2 of your code and something else that is supposed to happen in line 4 that doesn't go through the command line but cannot be done properly unless line 2 has already been executed. Maybe line 2 stores a sequence and then in line 4 you're labeling that sequence using the system rather than than the command line (yeah, I'll show you how that works at some point, but you can actually change the name of an object without going through the command line to label it). Let's say you're doing that and you haven't yet stored the sequence, then trying to change the name of it isn't going to work and then your plugin will fail because it can't find the object. And of course you're probably thinking, “Well, yeah, line 2 and line 4 are pretty close to each other; of course it's possible that it might not quite be finished,” but that's actually not how it works. Basically even if you have 300 lines of code in between, Lua is that much faster. The regular command line system is way slower. Of course if you did execute the command in the Lua task it still takes just as long, the difference is that the rest of the code can't run until the command is finished again, though if the command is bad it will break the plugin.
So what's the solution? Do we just have to pick which problem to deal with? Nope! Remember I said there were three functions for executing commands? Well the third one is called CmdIndirectWait and this one is actually kind of like a combination of the other two. It executes in the main task, but Lua just waits for it to finish before moving on, so it's executed separately, meaning even if the command is bad it will not break the rest of the plugin, but if it is not finished with running then the rest of the code will not go through until it's done.
The only downside to this would be if you're running a bunch of commands and none of your code actually relies on them being completed to continue because it will significantly slow down your code while you're just waiting for the commands to finish. In that case I would definitely use CmdIndirect. I personally haven't found a great use case for Cmd but it's there if you need it.
Now before I end the video I just want to show you one of my favorite real-life, simple use cases for the command functions. This is also going to incorporate several of the concepts talked about in the last two videos, so let's do it together.
Jjust to set this up, I work for a church and we have services at the same time every week. On Sunday mornings I wanted haze to run automatically for rehearsal so my volunteers and I didn't have to remember to turn it on ourselves. The problem is, the worship and tech teams always circle up on stage together right before rehearsal to talk and pray beforehand. These circle ups don't always start or end exactly on time, meaning there's no exact time when the rehearsal will start on any given day. But I really wanted haze going by the time rehearsal starts.
I tried an agenda cue for several different times but they kept getting started while we were still on stage and it was loud enough to be quite a nuisance.
Finally I came up with a really easy solution. I was like, “why on earth didn't I think of this before?”
So I ended up using a function called MessageBox because it's more customizable, but for this video I'm just going to show you the Confirm function since I showed it to you in the last video and it's simple.
To set this up I'm going to create a function called ConfirmHaze. I'm going to set a local variable called UserOK equal to the result of the confirm function and the confirm function is going to have a title that says “Hey” and a message that says, “It's time to run haze for rehearsal! OK to proceed?”
Alright, and then I'm going to create an if statement, so “if UserOK then,” we'll do, “CmdIndirectWait(‘Go+...’)” I'm going to do “Page 1.115” cuz that's where I actually have it on the console and “end,” end the function and now I'm going to call that function.
There's no arguments
in it. I don't need any. Time to run it.
“Hey, it's time to
run haze for rehearsal. OK to proceed?” Now if I hit cancel nothing
happens. If I hit OK then in this case it actually doesn't run
because I don't have an object on page 1.115.
Now if you were thinking that it doesn't actually matter if I use CmdIndirect or CmdIndirectWait or Cmd you would actually be right because although I used CmdIndirectWait from habit, it actually doesn't matter. If I were to use Cmd in this case, as you could see it gave me an illegal object because the object didn't exist; that qualifies as a bad command and it would stop the rest of the code from running. However in this case there's no more code following it so it literally would not matter.
Since there's only one command it does not noticeably slow it down to use CmdIndirectWait and there's nothing else happening that I'm waiting for anyway. Obviously with a longer script it is going to matter and there will be reasons to choose different ones but in this case it did not matter at all.
So the way this actually works in our context is that I have an agenda cue, instead of triggering haze, trigger this plugin. And then when the plugin runs if the user is on stage already and not present at the console then they won't be there to hit Confirm, so it just sits on the screen with the confirm box up there and waits and it does not continue until someone presses OK or Cancel, and so whenever the person gets back to the console after the circle-up they can hit OK and then the haze runs. So we don't have to remember and it's super easy, never have to think about it again.
I hope you enjoyed learning about command line interaction with me! I love using real world examples to illustrate things because I think it makes it more fun and easier to understand and remember. In the next video I'm going to get back to Lua itself and talk about tables. Tables are something I did not understand for a really long time and it made it so that I often did things in the hardest way possible, until recently, and the reason is because you really can't do much without using tables. So I'm going to help you skip that part of the journey and start off strong with a clear understanding of tables before we start using them. I will see you soon! Until then, happy programming!
Comments
Post a Comment