Sorry to be blowing up the forums, but I have a free Saturday and I’m making some great progress!
I have about 99% of the functionality that I want for my remote. I’ve created the keyboard page and have all of the keys functioning, but I’m a bit stumped at enabling the “Shift” function for the Roku.
At first, I thought I just just make standard keys and shifted keys, and hide the appropriate buttons when my “shift” key was enabled. It looked like the small and cap letters were contained in arrays (“LetterA” : [ “Lit_a”, “Lit_A” ]) and I could just call the specific value. For instance, for small “a”, I could use LetterA(0), and for caps I could use LetterA(1). Obviously, that didn’t work.
I did notice that there’s a variable (shiftKeyState) to enable the shift function, but I’m not sure how to set it. Do I need to create this variable inside of a virtual device so I can then set the boolean value?
I assume you’re using the Roku plugin? If so, you can send the LetterShiftOn and LetterShiftOff media commands to control the state of the shift key (which controls the shiftKeyState variable you identified). I’m a little rusty on how it works for the Roku, but I believe you could, alternatively, just send LetterShift to toggle the state, so the shift key on your keyboard could just send that each time and you wouldn’t have to track state separately (unless you wanted to do fancier things on the UI based on the shift state).
I wrote the keyboard stuff for the MCE Controller plugin first and then adapted the Roku plugin to have the same interface so I could use a PageBrowser and the same keyboard control. However, I moved earlier this year and don’t have my theater any more (working on designing a new one), so I’m a little rusty on how all the Home Remote pieces fit together I believe the MCE Controller page has a sample keyboard control attached that you could take a look at for how the state is controlled, since that one changes the background color of the shift key, as I recall.
Thank you for your reply! Very helpful. I may have some time later today to give it a try, and I’ll post back with how it goes.
Good luck with your new home theater! I had so much fun designing mine when we built our house, and it was the first “real” home theater I have ever had. Of course, after having it now for 15 years there are several things I would do differently. It would be a lot of fun laying out a new one.
Not sure if double posting is okay here, but it seems fitting to reply instead of edit since some time (and attempts!) have passed.
Okay… the good news is that I have the shift function working. I simply added a button linked to the LetterShift capability, and it locks the shift function until pressed a second time. I can change the color with the key press, but I’m afraid of it getting out of sync with the actual value of the shift mode. As mentioned in the Roku Plugin (you were correct–I’m using the plugin), it stores the boolean value in the shiftKeyState variable. How do I actually poll the value of the shiftKeyState variable? I tried appending the variable to the end of the device (Roku.MediaCommand.shiftKeyState) to see if that would work in a data trigger setting, but it didn’t. I was going to see if I could link the variable to a variable I create in virtual devices, but it looks like the functionality of variables has changed (I watched Brian’s video on setting a variable, and after creating the variable the menu options don’t appear when I select the variable).
If anyone could explain to me how to pass/get the variable from the plugin into a data trigger, etc., I would appreciate it!
Here’s how my shift key behaves. The shift button type is “toggle.” I included screenshots so you could see how I did it, however, part of the function is done via a script, which is not a good idea in the current version of HR. Maybe @bill could shed some light on how best to convert the script.
Thanks! We got to enjoy the theater in our last house for about 5-6 years before we moved and we are missing it horribly The plans for the new one are slowly coming along, but, while the space has some great aspects (it’s very wide, so time for a much bigger screen than before ), it has some challenges also (who would have ever thought a room could be “too big”?). We’ll get there eventually…
Glad you got it working! You cannot poll the value of shiftKeyState as the plugin is currently written (no access to internal variables). It would need to be exposed as an Attribute. However, I don’t think there’s a lot of risk of it getting out of sync. Again, I can’t really test this at present, but here is what I have observed:
First, I never had it get out of sync in my setup (although admittedly I didn’t use the Roku keyboard that much), it was much more of a potential issue with the MCE Controller. The MCE Controller is different than the Roku because it actually tracks shift state on the device you’re controlling, so I had to put some more stuff into the plugin to help avoid getting out of sync.
Second, because the Roku itself knows nothing about the shift state, the only thing to get out of sync is the visual indication of shift state and the plugin’s internal understanding of the shift state. But that really shouldn’t happen so long as you stay on the page with the keyboard. It would require THR to “lose” one of (1) setting the background color for the button and (2) processing the MediaCommand for the LetterShift, but I don’t think that can happen. They are both triggered off of the same button press event, right? Almost positive that is how mine was set up, but for some reason THR won’t start right now so I can’t verify. Thus, so long as you’re on the page, nothing gets out of sync. And if you leave the page, then all of that state gets wiped anyway, so when you go back to it, everything is re-loaded cleanly and set to the default state (unshifted), which means they are still both in sync. You could, in theory, “lose” state if left the page with the shift “down” (shifted), but does that really matter? If you left, you were probably done with it, so not a big deal when you come back and it is “up” (unshifted) again.
I hope that makes sense and I apologize I can’t seem to pull up my setup at present. I’ll try to follow-up once I can get back into it and find anything different than what I said above, but in the meantime, I suspect you won’t have any out-of-sync problems with the Roku.
My turn to apologize for the double-post–I finally realized I installed the wrong version of the .NET library and got THR to load up this time. Looking at my project, my keyboard control page works as I had remembered. The ButtonType for the Shift button is Toggle and it has 2 EventTriggers on it, one for the Checked event and one for the Unchecked event:
Each EventTrigger has 3 Actions, a DataAction to send the MediaCommand, a PropertyAction to change the background color, and a ScriptAction that remaps the text on the keys, similar to @gregkinney’s post above:
I’m not sure why a script is no longer a desirable way to remap the text, but would be interested to learn more. I certainly never had issues with it, but I haven’t used it in 6 months, so maybe things in THR have changed that I missed.
Thanks for all of the input! I love the use of scripting to set the buttons values… that just seems so, so much easier. Can anyone weigh in on why it’s not a good method to use now?
HotelFoxTrot: You’re likely correct… getting out of sync is likely not an issue at all–especially since Roku doesn’t track the state of the shift key.
That brings up a question… I know just enough about programming to do the little things I need to do. I dabble in Python, VBA and a little Java, but I’ve never really delved deep into the languages and interactions with other programs. How does one go about finding the capabilities that a program/device has? For instance, you knew the Roku doesn’t track the state of the shift button. I also see some capabilities pointed to in the Home Remote that aren’t listed in devices and capabilities. How can one go about finding the different ways you can interact with devices, etc.?
Regarding why scripting might not be a good method for changing the button values, maybe @bill has some thoughts on that? It really seems to me like a clean way to do it. I suppose PropertyActions might be the “correct” way to do it, but the script seems a lot less cumbersome in this situation, at least.
As for finding out capabilities of a program/device, do you mean in terms of writing a plugin? If so, there is usually some kind of documentation of the control API for the device. Those docs will tell you what form the commands should be sent in and what all can be done through the control interface. For example, the Roku plugin page links to Roku’s API documentation. It has a section that explains how to send keypress values, and from the way they describe it, you send specific ASCII codes. Those codes have separate characters for upper and lower case, which allows for you to send the exact form of the letter without regard to any concept of shift state on the Roku.
In general, if you can use an API in a stateless way, that’s preferable because it can sometime be very difficult or even impossible to reliably know the state on the remote device. While it is really nice to be able to provide Attributes for a plugin that give feedback, the devices I have worked with so far have been cumbersome because they can be very slow to update and you’re left with uncertainty in the plugin as to whether you’ve got the correct state at any point in time. It’s one thing if you’re just displaying a label and showing some value on the device (you might just have to wait a beat or two for the UI to update), but if you want the plugin to send commands or behave differently based on the state, it can be tricky to be sure you’re up to date at any point in time, at least in a fast manner.
If you were asking more generally about what capabilities/attributes a plugin device has within THR, usually that’s documented. And you can also look in the source in the onSynchronizeDevices() method and see what Capabilities and Attributes are defined for it. There are probably some other ways to dig into it in THR’s interface, but I’m not very familiar with them–I don’t think I have used plugins other people have written in quite a while (just a coincidence that all the devices I had I needed to write my own plugins for if they weren’t natively supported).
Some of that makes perfect sense, and some of that kiiiiinda sorta makes sense. My experience with API’s is, well, extremely limited. My “programming” including APIs has typically involved shouting at my computer, kicking a concrete wall and finally begging for help in the appropriate forum I’m assuming the onSynchronizeDevices() would be a list in the API code? I really need to take some time and delve into that side of programming. Most things I’ve done have been completely stand-alone apps to perform some function that I need.
One good example is the subwoofer value/adjustment for my receiver (I set it up so I can turn down the subs when everyone is in bed). The range is -10 to 10, and I set it up as such. I’m assuming the variable is a float (or single or double…?) since it contains a decimal value. However, it usually starts out displaying an integer, switches to a decimal value, and sometimes just crashes (I have it tied to a slider). It works, but not reliably. It’s fun figuring it out, however!
I fully understand that kind of API interaction Now that I’ve written several plugins, I tend to use them as a starting point for new ones. In general, you encounter 2 types of devices, those controlled by HTTP and those controlled by TCP, so I just pick a plugin that already starts with the right kind of communication and then modify according to the new device’s API. Sending commands tends to be pretty straightforward. Receiving/parsing data you get back has been trickier for me, at least.
Regarding onSynchronizeDevices(), that is one of the required methods for a plugin in THR. It’s usually at the bottom of the plugin source code and is pretty short. A couple of the parameters that get set for the THR device object are Capabilities and Attributes and those give you an idea of the types of commands you can send and what values you can read.
Setting aside my lack of understanding why you’d ever turn down a subwoofer (people can learn to sleep through the gentle massage…) , I don’t have much experience with sliders, but I would think you could configure one to have only integer increments. Javascript is a weird and horrible language and everything is basically every data type all at once. But if you want/need to send an integer, I’m certain there is a toInt()-type function that would allow you to be sure that’s what you’re sending (I may have even used it in one of my plugins before, but I’m swamped with work this morning and don’t have time to go digging). Unless your receiver can take a floating point value? That seems unlikely to me, though. So that might help with the crashes you’re seeing.