**Q-SYS Training  |  Plugin Development Training - Get Components, Get Pins, & Get Wiring — Transcript & Summary | SozAI**
Source: https://sozai.app/transcript/qsys-plugin-development-training-components-pins-wiring/

Learn how to develop Q-SYS plugins by embedding components, pins, and wiring to create functional audio playback on IP change events.

## Key Takeaways

- Q-SYS plugins can embed components, pins, and wiring programmatically for flexible design.
- The SDK is essential for understanding available components and their properties.
- Runtime scripting enables dynamic actions like playing audio on specific events.
- Textual plugin development can replicate Designer workflows but may be harder to troubleshoot.
- Incremental plugin versions allow adding requested features without revising existing ones.

## What the video covers

- The video covers building version 1.1 of a Q-SYS plugin with new features including get components, get pins, and get wiring functions.
- It explains embedding components inside a plugin for private use, similar to dragging components in the Q-SYS Designer.
- Demonstrates adding an audio bin loop player component with one output channel to the plugin.
- Shows how to add output pins to the plugin and wire them to the embedded components programmatically.
- Details how to write runtime Lua code to trigger audio playback when an IP address change event occurs.
- Highlights the use of the Q-SYS SDK to find component types and properties for plugin development.
- Explains the textual wiring process inside the plugin as an alternative to graphical wiring in Designer.
- Mentions best practices like saving files and using VS Code shortcuts for efficient coding.
- Discusses the possibility of building entire Q-SYS designs textually through plugins, though it may be complex for troubleshooting.
- Concludes with testing the plugin and confirming the successful implementation of the new version 1.1 features.

## Chapters

1. 00:00 Introduction to Plugin Version 1.1 Feature Request
2. 01:05 Setting Up Audio Playback on IP Address Change
3. 02:05 Embedding Components in Plugins Explained
4. 03:09 Overview of Q-SYS SDK Components
5. 03:53 Configuring Audio Components and Pins
6. 05:02 Using VS Code Shortcuts and Coding Best Practices
7. 05:58 Adding Bin Loop Player Component and Properties
8. 07:22 Wiring Components and Pins Textually
9. 09:05 Editing Runtime Script to Play Audio File
10. 09:45 Testing and Finalizing Plugin Version 1.1

Answers

## Questions about this video

What are the main functions introduced in Q-SYS plugin version 1.1?

Version 1.1 introduces the functions get components, get pins, and get wiring, which allow embedding components, defining pins, and wiring them programmatically inside the plugin.

How can I play an audio file when an IP address changes in a Q-SYS plugin?

You can write runtime Lua code that listens for IP address change events and triggers a bin loop player component to play a specified audio file when the event occurs.

Where can I find information about available components and their properties for Q-SYS plugins?

The Q-SYS SDK provides detailed documentation on all available components, their types, and properties that can be instantiated and used within plugins.

## Full Transcript — Download SRT & Markdown

00:06

Speaker A

Okay, I know that we just built version 1.0, but we have just had a feature request come in.

00:14

Speaker A

Why? Version 1.1 is what we are about to build. This is called do you want to build a plugin, not do you want to revise a plugin. That's someone else's job.

00:25

Speaker A

But Nate, they're going to give us more money. Okay, I'm in. So, you may have noticed that as we were running through plugin.lua that we skipped three of the functions. They all go together. Get components, get pins, and get wiring. We skipped them because

00:41

Speaker A

well, they're not actually really necessary for version 1.0 of our plugin. But because someone somewhere said that they would give us more money for version 1.1, we're going to give them what they asked for, which is something completely silly and ridiculous. But

01:00

Speaker A

it's going to provide us the opportunity to actually use these functions, Nate. All right, that sounds legitimate.

01:05

Speaker A

What we're going to do is we're going to make our plugin actually play a file whenever there's a change. And for simplicity's sake, we're going to make it be able to play a file when the IP address has changed because that's the

01:22

Speaker A

first event handler. So, that's the one we chose. Got it. But the point is instructional purposes only.

01:28

Speaker A

It's for instructional purposes only. This is 100% silly. You wouldn't actually do this with this in the real world. Let's get into VS Code. And let's actually open all three of these, plugin.lua, and it says get components, get pins,

01:47

Speaker A

get wiring. So, we need to open components.lua. We need to open pins.lua, and we need to open wiring.lua.

01:58

Speaker A

And I'm going to close that so we can actually see all of these all at the same time.

02:05

Speaker A

So, from a high level, the way this works is we are able to embed components into our plugin so that they are accessible for our own quasi private use.

02:21

Speaker A

This would be equivalent to in normal designer dragging in a component and being able to use name component methodologies to access the thing. We're just going to do it inside the plugin.

02:34

Speaker A

And that means the plugin is able to call those different components into existence for themselves. It's really a rather neat trick.

02:45

Speaker A

Now, in our base example here, we already have the example of pulling into the components table a mixer that has a name, has a type. So, the name is main mixer, the type is mixer, and you set certain properties about it. Where

03:03

Speaker A

do we learn about what kinds of components we can bring in? Guess where? SDK.

03:09

Speaker A

SDK, and there is a bunch of them. I have not made a count of how many components Q-SYS has, but it's got to be at least four or five now.

03:18

Speaker A

At least four or five. I'm not wrong. You're not wrong. There's a bunch, and almost all of them can be pulled in.

03:26

Speaker A

Refer to the SDK for the specifics about what can be instantiated via a plugin.

03:33

Speaker A

But the idea is there. Now, if we build and pull in a plugin, for example, and what we're going to do is we're going to pull in a particular audio component in a moment, we need that audio to, well,

03:45

Speaker A

get out. And so, for it to get out, it needs a pin for it to escape. Make sense?

03:53

Speaker A

Yeah. In the same way, you think of it as the plugin is kind of like a container, and inside of it are these, in this case, an audio component. And in the same way that you would configure a container to

04:07

Speaker A

have pins, we're effectively doing the same thing here. So, what we are going to do and what our demo has done is shown us how to create an audio output. So, name, audio output, direction, output. Additionally, if your script is going to use a serial

04:26

Speaker A

port, this is how you would do it as well. Now, lastly, if you're thinking about traditional DSP workflows, well, if you've got a mixer and you've got an output pin, you got to wire those suckers together.

04:41

Speaker A

Same thing here, you just have to do it textually. So, instead of talking about the demo, let's just do it right now.

04:51

Speaker A

So, let's come to components.lua. And let me shimmy that over. And I'm going to turn that off, theoretically. There we are.

05:02

Speaker A

And whoa, whoa, whoa, whoa, what was that shortcut you just did that uncommented everything at once?

05:07

Speaker A

I highlighted everything and I hit control slash. Control slash. Look at that. Do it for you?

05:14

Speaker A

Yeah. Yep. All right. So, the name of our component is going to be my player.

05:23

Speaker A

This is effectively the same as saying my player equals components.new of my player. Okay?

05:34

Speaker A

Since you've been through advanced, you know how to use name component methodologies. This is effectively what we're doing.

05:41

Speaker A

It's a code name and a name component and a variable all at the same time.

05:45

Speaker A

Affirmative. Sweet. Yes. Okay? Now, what we're bringing in is going to be a bin loop player.

05:52

Speaker A

Okay, a bin loop player is a lot like an audio player. You can give it a playlist, tell it how many times you want to play, you hit go, it does the thing. It's going to work great for us.

06:02

Speaker A

We also only the way, I'm looking in the SDK to double-check this, and it tells you like what the proper names are for all of these components all here in the embedded components section. So, that's why there isn't a space between bin and

06:14

Speaker A

loop, 'cause it's telling me that SDK. Great. And I'm glad you pulled it up in the SDK.

06:18

Speaker A

Yeah. Okay. Now, under properties, which I'm assuming is also it describes in the SDK what properties the bin loop player takes.

06:27

Speaker A

It does. It's got an output count. Correct. So, in \_outputs is going to be, in our case, one, one channel. Because it's a wave file. It's a wave file that I made like 10 minutes ago. I just yelled into my computer and

06:43

Speaker A

made a wave file, and we're going to play it out of the core momentarily. All right? We're going to insert into the components table a bin loop player whose name is my player, and it has one channel of output. So far so good?

06:57

Speaker A

So far so good. Great. Now, when we come to pins.lua, here's where we're adding a pin to literally our plugin's component, right?

07:07

Speaker A

Yeah. Um okay, I don't need this serial port, so get rid of it. Uncomment that. And that's actually going to be just fine. It's going to be called audio outputs, and its direction is output. Now, let's see. Can I make

07:22

Speaker A

this okay, that'll be fine. If I were going to make multiple output pins, is the order in which you put them in here in this .lua document the order in which they appear on my component?

07:34

Speaker A

Indeed. Because every time you do table.insert, you're creating an ordered list. Interesting. So, there we are. And then lastly, we need to wire my player's output one. That's the name of the output pin on my player. My player space

07:52

Speaker A

output space one. That's the string name of it. That's a surprisingly kind way for us to type it in. There's no brackets, there ain't no dots. It's just straight up a name.

08:02

Speaker A

Nope. I like that. Yep. And we are wiring it to audio output. So, if you're visualizing this in your mind of what this would look like in designer, it's like it's a component and pin and you wire it. Just like you would

08:21

Speaker A

back in control what? Back in level one. It sounds like you could literally take an entire design and build it inside of the plugin with all the components.

08:30

Speaker A

You actually really could. That's wild. You could indeed actually write an entire Q-SYS design just textually describing it through the plugin process.

08:41

Speaker A

That one, the troubleshooting would be a bit tricky. It would be terrible. Yeah. But possible.

08:46

Speaker A

Yeah. Right. So, that creates the player, that creates the pin, that wires it together.

08:53

Speaker A

We now have to edit our runtime. We need to add a little bit of code to actually make it do the thing.

09:00

Speaker A

So, be sure to save. So, let's save and those without saving, you're in trouble?

09:05

Speaker A

Uh no, it'll probably yell at you. Okay. Okay, we need runtime. Let's come down to the end of runtime.

09:13

Speaker A

And we're just going to add a whole little extra function right here at line 142.

09:19

Speaker A

Here we go. Boom. We're going to write a function. It's going to be called funk play file and it's going to take an argument of file.

09:31

Speaker A

But Jeff, you've called everything else arg file. My guy, it's the end of the day.

09:35

Speaker A

Yep. Can we be okay? We're losing our prefix.

09:40

Speaker A

All right, but because I opened it, I'm going to close it. I called mine argfile.

09:44

Speaker A

Cuz I'm not a monster. arg file Got it. No problem. Okay. Here's what we're going to do.

09:54

Speaker A

First thing we're going to do is we're going to follow our rules. if debug function then print that funk play file was called. Great.

10:08

Speaker A

Love it. end end single line Yep. All right there. Now, here's one of the interesting things.

10:15

Speaker A

You may remember from your previous studies, probably in level two you can't actually play audio if you're emulating.

10:24

Speaker A

You should know that from level one, hopefully. Perhaps level one. When you realized that you didn't have a core and that couldn't hear anything.

10:32

Speaker A

I It's Pretty hard to play a file from the core when you don't own that core.

10:36

Speaker A

Yeah. Anyway. Again, from your previous studies you may remember that you can't play audio while you're emulating on your machine.

10:45

Speaker A

And you may also remember from advanced, depending on where you took it, that uh that we actually can ask Quesus hey, are you emulating or are you not? Because we can't ask this bin loop player to play if we're emulating.

11:02

Speaker A

Otherwise strange things happen. Mostly it yells at you. And it's fine, but we don't want that. if system.is\_emulating then else end So, what we're doing is we're building a decision tree based off of well, are we emulating or are we not? Because if

11:27

Speaker A

we're emulating, we ought to know that. Because we're going to throw basically an error. We're just going to make it say print funk play file did not play because I'm emulating, man.

11:44

Speaker A

I added a a common dummy to that. I added, dude. That's That's good. Sometimes those are synonymous.

11:50

Speaker A

Yeah, did not play because I'm emulating, dude. Did not pass go, did not collect $200. Else, though, uh we're going to print that funk play file is going to the core will attempt to play the file called arg file. Okay, I changed mine to say

12:12

Speaker A

arg file because Nate whined about it. And I whined about it because you made me tell you to whine about it.

12:21

Speaker A

Applied by your own best practices. It is my fault. It is my fault. Okay.

12:26

Speaker A

So, there we are. Um so, it's going to say that it's going to attempt to play the file. The next line is we are going to and just follow along with me. We're going to ask my player to stop.

12:39

Speaker A

Cuz we just want to make sure that it's not playing. Right? It shouldn't be playing, but in the off case that it is, make it stop playing.

12:47

Speaker A

Sure. Okay? Then we also are going to tell my player to clear. Because we want it to clear its queue.

13:00

Speaker A

And then we are going to say that my player's file name So, I had to use the traditional way of indexing the table. I couldn't use the syntactic sugar.

13:15

Speaker A

Uh that's why it's bracket quote the string name. Okay? And then it's dot string is going to be And this is actually really important. audio/ and then dot dot arg file.

13:29

Speaker A

Mhm. Because we are going to load the file from the course hard drive. Now, that actually begs a question. You actually have to Well, you need a wave file and you have to load it to that directory. Now, I happen to

13:47

Speaker A

specify here that it's just going into the audio directory. No other subfolders, it's just going right there. You do you, boo.

13:55

Speaker A

In the real world, there's no way you would hardcode that in there. You'd make that audio a variable, too, and you'd have that as one of the arguments in your play function, play file. You variable crap out of this, Jeff. I know

14:06

Speaker A

you. But may maybe. Probably not. Uh it depends. Again, right? The idea, you write working code and then you make it better. So, we're making working code.

14:14

Speaker A

But one of the steps is you do have to load a wave file to that directory that you are trying to now pull from um in the code.

14:24

Speaker A

Right. So, we have stopped playing. We have cleared the queue. We are loading the file to the queue. We are going to tell my player to set its play count to be one, which means play it once.

14:43

Speaker A

If you want it to play a lot, you can set it to 99 and then you would be there for a long time and you'd get really mad. If you set it to one, it means play one time.

14:52

Speaker A

There you go. So then we need to tell it to Well, submit. Again, this is just how the bin player works. And it's it's really fine. So, this is how we load the queue.

15:07

Speaker A

And then, because we're going to give it a smidge of time to load the file before we tell it to play the file, what do you think we're about to pull out of our pocket?

15:19

Speaker A

a call after on me? We are. Wow. We're going to pull a call after out of our back pocket. timer.call\_after You remember how that thing works?

15:27

Speaker A

Uh you're going to It's got two arguments. It's probably got a function and it's probably got the amount of time you want to wait for.

15:31

Speaker A

Indeed. So, the way that I like to write this is I like to put in the function, right?

15:38

Speaker A

So, I'm literally declaring a function right here in it. We're not being any more fancy. function blah blah blah end comma and then like point two.

15:48

Speaker A

Point two will be fine. Point one might be fine. Again, this could be more configurable if you really wanted it to, but again, that's not the point of this particular video. We're just trying to make this work and it's

15:59

Speaker A

silly and it's fun and just be happy with me. Yeah, and all of this you got to know that if you if you were using a bin player normally, then you would know why you had to hit all these buttons. And if

16:08

Speaker A

you opened up the view component controls info, you'd know how we figured out the names of all these controls along the way. Jeff's just already done that work ahead of time because there's no reason for us to take you through

16:17

Speaker A

those steps. You probably know how to do it. Right. This is just writing control code. So, inside our call after, we are finally going to tell it to play.

16:28

Speaker A

So, if we uh we can tidy up this uh this commenting a little bit so that it's a little easier to read, all right? So, we're going to stop playing, we're going to clear the queue, we are going to load the file, we are

16:42

Speaker A

going to tell it to play once, we are going to load the queue, we are going to then finally, after a smidge of time, tell it to play the file. And that concludes our code. And Nate, notice how

16:59

Speaker A

I ended all of my ends with them so nice and you even you you lined up your comments.

17:06

Speaker A

Sure did. So, now we are ready to actually do this. Yeah. So, right here, we are going to say in the event handler, we're going to call funk play file and we're going to tell it the name of the file. Now, I already

17:26

Speaker A

know it's IP address changed .wave. And you know that because you recorded that. I know that because I made that.

17:37

Speaker A

And you put it on the core. Sure did. Now, that's not going to work for me cuz I don't have a core. You got a core over there.

17:41

Speaker A

I have a core over here. have my core. That's actually true. I have Nate's core.

17:46

Speaker A

Um and Nate doesn't have a core and you probably don't have a core home or you might have a core home, in which case you can totally try this out, too.

17:53

Speaker A

Yeah, but then just make sure you name your file right and put it in the right place.

17:56

Speaker A

Yeah. And besides, if you want to take this idea and actually, like you know, scale it out and make it actually announce the lighting levels whenever you change the lighting level.

18:08

Speaker A

great way to get fired. While this is silly, there might be an a real application, but let's be real.

18:13

Speaker A

This this is mostly silly. demonstrate how this kind of thing actually works. Uh I think we're actually done. So, control shift B and we're going to do it as a dev. Boom.

18:25

Speaker A

Let it do its thing. All right. There we go. And let's pull in our plugin.

18:36

Speaker A

My favorite thing is that now that we've made a major um release, now I'm caught up with you again and I'm just 1.0.0.1.

18:42

Speaker A

Yeah, that's the I didn't have an extra 10 builds along the way. It's okay. Now, Nate, what do you notice about our new our new plugin?

18:51

Speaker A

Look at that pretty little audio pin and if you have your mouse over it, it tells you what it is.

18:55

Speaker A

Yeah, fantastic, okay? And I'm going to pull in a gain block just because uh we don't want to like blow the speakers out and I'm going to pull in line out and we're going to wire into the output

19:11

Speaker A

number one. Let's hit go. And before we change the IP address, I am going to set a gain just so that we don't blow the speakers out. All right, so let that catch up.

19:26

Speaker A

Okay. Let's set this uh Are we good? There it is. All right, let's set that to minus 10.

19:37

Speaker A

And let's give this a uh let's give this shot. You don't need to unpin that. It's going to come out of the loudspeaker.

19:45

Speaker A

I know, but this way we can see it. Let's set it up. 127.0.0.1 Hey, look at you. You changed the IP address.

19:56

Speaker A

Ha, how about that? You sure did. That's pretty silly, but here's the point. If you want to embed components, you totally can. If you want to embed a text component because you want to save some information or some data, you can

20:11

Speaker A

do that. If you want to build a super fun elaborate audio player like this that does things Hey, we kind of did that just now. The point being is there are tools in your tool belt and now you know about

20:25

Speaker A

them and you can do something with them. So, Nate, we built it. We tested it.

20:29

Speaker A

Did you commit it? It's time to commit it. One more time. One last time. And in fact, control shift B.

20:38

Speaker A

We're going to build it as a minor. Good for you, man. Cuz now it's going to be 1.1.0.

20:47

Speaker A

And now that it's happy, I'm going to come over here and commit it as 1.1 release.

20:56

Speaker A

I probably should say something else, but that's going to be fine for now. Hit yes.

21:02

Speaker A

And look at that. We just did it. We are at 1.1, Nate. We built the plug-in that you said you wanted to build by consenting to this course.

21:12

Speaker A

Exactly. Right. We said, "Do you want to build a plug-in?" You said, "Yes." And now we've spent like probably between 6 and 8 hours together building a plug-in.

21:21

Speaker A

In retrospect, you should have said no to that question. No, you shouldn't. You should have said yes because plug-ins are wonderful and you should know about them.

21:30

Speaker A

Here's what you're going to do next. Normally, you would send in a file. You're not going to do that.

21:36

Speaker A

All you have to do now for you to get your Vixa credit is go take the quiz.

21:43

Speaker A

It won't be that hard. You'll be okay. So, but with that you have now built a plug-in and we have shown you how to use VS Code, how to use Git, how to use the compiler, how to access the SDK, how to

22:01

Speaker A

read the SDK, and walks you through what it means to build a plug-in. I for one thank you very much for going [music] on this journey with me. Nate, thank you also for being here.

22:15

Speaker A

I am glad to have learned so many new things about you along the way.

22:20

Speaker A

I am I'm going downstairs to find HR. [laughter] But with that, I really hope to see you soon. Have a great day. Good night and Godspeed.

Topics: Q-SYS plugin development get components get pins get wiring Lua scripting audio playback bin loop player Q-SYS SDK VS Code


---
This is the markdown twin of https://sozai.app/transcript/qsys-plugin-development-training-components-pins-wiring/ — the same content, without the markup.
Published by SozAI (https://sozai.app). Reuse and quotation are allowed with attribution and a link back.
Machine-readable index: https://sozai.app/llms.txt · data API: https://sozai.app/api/
