![]() |
|
SageTV Studio Discussion related to the SageTV Studio application produced by SageTV. Questions, issues, problems, suggestions, etc. relating to the Studio software application should be posted here. |
![]() |
|
Thread Tools | Search this Thread | Display Modes |
#1
|
||||
|
||||
Plugin: STVI Configurator
Per this discussion, I have created an STVI (with some Java support code) that allows STVI plugins to use the V7 plugin configuration UI instead of rolling their own config UI. Detailed instructions are in the Javadocs for Tools Library V1.2, but the gist of it is that you implement a few lines of widget code in your STVI for each of the get/setConfig* methods, insert them into a standard place in the STVI Configurator code skeleton, and declare STVI Configurator as an STVI dependency in your manifest. Once this is done, a Configure button will appear on the options dialog for your plugin, and your widget-code methods will be called by the plugin manager in lieu of Java-based config methods.
To make things even easier, Tools Library V1.2 also includes an XmlConfig class that lets you define your config settings in an XML file, so that your config methods can be one-line calls into XmlConfig. You're not obliged to use XmlConfig with the STVI Configurator, but it does simplify things.
__________________
-- Greg Last edited by GKusnick; 07-17-2010 at 07:24 PM. |
#2
|
|||
|
|||
Very nice work Greg and much needed for per STVi developers who don't want to code their own stvi options.
|
#3
|
||||
|
||||
Greg, I just want to clarify... Will the PluginAPI calls, such as, GetPluginConfigSettings, work on these plugins as well? (I think it will, but I just want to make sure)
__________________
Batch Metadata Tools (User Guides) - SageTV App (Android) - SageTV Plex Channel - My Other Android Apps - sagex-api wrappers - Google+ - Phoenix Renamer Downloads SageTV V9 | Android MiniClient |
#4
|
||||
|
||||
You mean if you call them yourself from Java or from another STVI? Unfortunately no, they won't. To get this to work I had to replace PluginAPI calls in the stock STV with calls to my STVI-aware wrapper methods. I would rather not have done this, so if you know of a way for me to intercept calls to the native PluginAPI methods, that would be a cleaner and more robust approach.
__________________
-- Greg |
#5
|
||||
|
||||
Quote:
I was asking, because at some point, I wanted to make the plugin configuration available via the Phoenix configuration metadata (which would also make it available via the web ui) . I won't be doing this for some time, but when I do it, I'll simply create phoenix configuration nodes by iterating the plugin list and calling GetPluginConfigSettings for each plugin (as well as the other plugin apis to fully populate the metadata)
__________________
Batch Metadata Tools (User Guides) - SageTV App (Android) - SageTV Plex Channel - My Other Android Apps - sagex-api wrappers - Google+ - Phoenix Renamer Downloads SageTV V9 | Android MiniClient |
#6
|
||||
|
||||
well, the plugin configurations are still just stored in the .properties files, so you shouldn't NEED to go through the plugin config system to use them from Phoenix/BMT Web.
__________________
Buy Fuzzy a beer! (Fuzzy likes beer) unRAID Server: i7-6700, 32GB RAM, Dual 128GB SSD cache and 13TB pool, with SageTVv9, openDCT, Logitech Media Server and Plex Media Server each in Dockers. Sources: HRHR Prime with Charter CableCard. HDHR-US for OTA. Primary Client: HD-300 through XBoxOne in Living Room, Samsung HLT-6189S Other Clients: Mi Box in Master Bedroom, HD-200 in kids room |
#7
|
||||
|
||||
Quote:
I could read properties, but properties don't actually contain any metadata, such as label, description, help, data type, etc. They only contain a key and value.
__________________
Batch Metadata Tools (User Guides) - SageTV App (Android) - SageTV Plex Channel - My Other Android Apps - sagex-api wrappers - Google+ - Phoenix Renamer Downloads SageTV V9 | Android MiniClient |
#8
|
||||
|
||||
Quote:
As you mentioned, though, this would not work through the sage plugin system... in the end, the only way to do this cleanly is for sage to add STVI's to the basic plugin config system. I would think this would be trivial, and should really be taken care of next version.... Jeff?
__________________
Buy Fuzzy a beer! (Fuzzy likes beer) unRAID Server: i7-6700, 32GB RAM, Dual 128GB SSD cache and 13TB pool, with SageTVv9, openDCT, Logitech Media Server and Plex Media Server each in Dockers. Sources: HRHR Prime with Charter CableCard. HDHR-US for OTA. Primary Client: HD-300 through XBoxOne in Living Room, Samsung HLT-6189S Other Clients: Mi Box in Master Bedroom, HD-200 in kids room |
#9
|
||||
|
||||
Quote:
Quote:
My solution was to code an STVI's config methods in widget code as an inseparable part of the STVI, so they're always enabled/loaded together. But this requires a somewhat klugey callback mechanism from Java into widget code via ExecuteWidgetChain, with parameters passed via AddStaticContext. It works for my purposes, but I'm not sure it's something they'd want to formalize as a standard part of the PluginAPI.
__________________
-- Greg |
#10
|
|||
|
|||
I am in the process of updating one of my STVi plugins to use this. It is excellent. Thanks for all of your work on this!
|
#11
|
|||
|
|||
STVi Configurator questions
I have a few questions as I work through the STVi Configurator process. I plan on storing the config values in an XML.
What folder do you store the config.xml (example.config.xml in the example)? Where do you put the SettingMethod conditional in Studio? Does that go in the Application Started hook as well; right after the action that instantiates the XMLConfig via AddGlobalContext? How do you test this? How do you test the Application Started hook? I tried F5 on the hook and a black screen showed up. Do you have to shut down SageTV and open it back up or is there a trick? * merged * |
#12
|
||||
|
||||
You can of course store config values anywhere you want, but the expected place for them is in the .properties file, and that's where my XmlConfig class will put them.
Or are you just saying you want to use XmlConfig to get the config definitions from an XML file? Quote:
What I prefer to do is to package the config.xml as a resource in the JAR file, and use XmlConfig.FromResource() to load it at startup time. That way it's one less file cluttering up the user's disk. Quote:
(However there seems to be a new bug in 7.0.15 that prevents menus created by STVIs from showing up in Studio. I'll file a bug report on that.) Quote:
You can also test any arbitrary widget chain using the Execute Widget Chain command on the right-click context menu. But if the chain depends on variables that aren't globally defined, it may not do what you expect when invoked this way. (F5 is strictly for launching Menu widgets.) As a final note, if you post questions like this to the existing STVI Configurator thread, I'll probably see them sooner because I'm subscribed to that thread. That goes for pretty much any plugin question: the plugin authors subscribe to their own support threads in order to get notifications about questions from users. Starting a new thread bypasses that notification system and may delay the response. (Plus it tends to clutter the forum unnecessarily and push useful threads off the front page.)
__________________
-- Greg |
#13
|
|||
|
|||
More noob questions....
Yes, I will be using the gkusnick.sagetv.XmlConfig class to get my config definitions from an XML document.
I'm still confused what the job of the SettingMethod condition is? Is it to get any of the elements defined in the config definitions XML doc and to save values to the sageTV.properties file? Say I have this XML config definitions file: Code:
<config> <setting name="CallName" type="Text"> <label>Call name:</label> <helptext>This will be the call name used.</helptext> <property>mypluginsCallName</property> </setting> <setting name="AgeOfUser" type="Integer"> <label>Age:</label> <helptext>Enter your age.</helptext> <property>mypluginsAgeOfUser</property> </setting> <setting name="BkColor" type="Choice"> <label>Background Color</label> <helptext>This will be the color of the table.</helptext> <option>red</option> <option>blue</option> <property>mypluginsBkColor</property> <default>red</default> </setting> </config> Say my jar has: package HelloTable class HelloTableClass1 class HelloTableClass2 Resource folder called: Resources XML in the folder called: ConfigDefinitions.XML Code:
In ApplicationStarted hook: AddGlobalContext("ExampleConfig", new_gkusnick_sagetv_XmlConfig(XmlConfig.FromResource(cls, szResource))) Code:
"example.getConfigSettings" gkusnick_sagetv_XmlConfig_getConfigSettings(ExampleConfig) "example.getConfigType" gkusnick_sagetv_XmlConfig_getConfigType(ExampleConfig, SettingName) "example.getConfigLabel" gkusnick_sagetv_XmlConfig_getConfigLabel(ExampleConfig, SettingName) "example.getConfigHelpText" gkusnick_sagetv_XmlConfig_getConfigHelpText(ExampleConfig, SettingName) "example.getConfigValue" gkusnick_sagetv_XmlConfig_getConfigValue(ExampleConfig, SettingName) "example.setConfigValue" gkusnick_sagetv_XmlConfig_setConfigValue(ExampleConfig, SettingName, SettingStrValue) "example.getConfigValueAsInt" gkusnick_sagetv_XmlConfig_getConfigValueAsInt(ExampleConfig, SettingName) "example.????" gkusnick_sagetv_XmlConfig_setConfigValue(ExampleConfig, SettingName, SettingIntValue) Last edited by chrishallowell; 08-14-2010 at 09:16 PM. |
#14
|
||||
|
||||
The SettingMethod conditional is how STVIConfig finds the right method to execute. When the UI wants to call method M of plugin P, the STVIConfig runtime sets the global variable SettingMethod to "P.M" and calls ExecuteWidgetChain on the conditional. The result is that the branch labeled "P.M" gets executed. But that's all internal to the STVIConfig implementation. Your responsibility is just to make sure that the appropriate branches exist for the methods you want to implement.
Also, as indicated in the STVIConfig docs, you're not obliged to use XmlConfig with STVIConfig. You can put any widget code you like in those method branches. Using XmlConfig is a convenient way to keep that code concise, but XmlConfig itself has no knowledge of that conditional widget structure, and STVIConfig has no special knowledge about XmlConfig, so it's not really accurate to say that the job of the conditional is to interact with XmlConfig. Its job is simply to invoke whatever code you choose to put in those branches, which can be calls to XmlConfig if that suits your needs. The branch names you use should be specific to your plugin, e.g. "hellotable.getConfigSettings" rather than "example.getConfigSettings" (assuming "hellotable" is the unique plugin ID specified in your manifest). Your job is not to replace the contents of the existing "example" branches, but to add new, uniquely named branches below the "else" branch. Similarly, you ought not to call your XmlConfig instantiation ExampleConfig; you should call it HelloTableConfig or something else specific to your plugin. Don't step on the example code if you want your plugin to coexist peacefully with other plugins using the same machinery. You don't need a branch for getConfigValueAsInt; that's not one of the standard methods defined by the SageTVPlugin interface (which is what you're trying to satisfy here). It's just a convenience method I thought might be useful to Java coders using XmlConfig and is not really relevant to STVI code. I'm not following your question about setConfigValue; if you already have a branch for that, you don't need another one. Again, don't get confused by the overloads in XmlConfig.java; your guide on what to implement should be the methods defined by SageTVPlugin. The class you pass in to XmlConfig.FromResource in some sense doesn't really matter; its only use is to determine which ClassLoader to use for loading the resource. If that doesn't mean anything to you, don't worry about it. The simplest rule of thumb is to pass in any class defined by the same JAR as the resource you're trying to load. In your case either of your HelloTable classes will work. To get a class object from STVI code, call java_lang_Object_getClass on an instance of the class. The szResource you pass in is the string name of the resource file in the JAR. That's the filename that the resource loader will search for. As such it should be unique within the set of JARs on the search path (i.e. in the SageTV\JARs folder), to avoid collisions with other plugins and their resources. So "ConfigDefinitions.XML" is not a good choice from that perspective; something along the lines of "HelloTable.config.xml" would be better. Your XML looks reasonable, but as a matter of convention I'd suggest putting your plugin's properties under some common key, e.g. Hallowell/HelloTable/CallName, Hallowell/HelloTable/AgeOfUser, etc. This makes it clear they belong together and lets you manipulate them as a group if you need to. Prefixing it with your name is a good idea so that if you write more than one plugin, their properties all group together in the .properties file. The same goes for Java package names, by the way: call it Hallowell.HelloTable or something along those lines both to make it clear who it belongs to and to minimize the chance of collision with other package names. (The Java convention is to use some domain name that you own as the prefix, with the components reversed, e.g. org.apache.whatever.)
__________________
-- Greg |
#15
|
|||
|
|||
Quote:
What does the getting/setting of the property values in the sage.properties file? STVi config, XmlConfig, SageTV internal, or something I need to do? Do I have this right (not using the STVi config)? 1. User installs a plugin 2. SageTV internal process uses the manifest xml to ensure all dependencies are in place and then it installs the files. 3. User selects the config button of the plugin 4. SageTV internal process calls the get sage.api.PluginAPI methods to get the config options in the HelloTableConfigDefinitions.XML file and property values from the sage.properties file and then displays them in SageTV. 5. User changes a property value. 6. SageTV internal process calls a set sage.api.PluginAPI method to save the changed property to the sage.properties file. But now since we are using the STVi config, SettingMethod conditional methods process the calls instead of the sage.api.PluginAPI. Am I right? Assuming the above statements are true, how do I know what methods are called by the SageTV internal process? (I know, it's like your trying to teach a baby to walk here... ![]() Last edited by chrishallowell; 08-16-2010 at 02:39 PM. |
#16
|
||||
|
||||
Quote:
In your case you've chosen to delegate that task to XmlConfig. That's the point of specifying property names in your config.xml: so that XmlConfig knows how to store and retrieve the property values. STVIConfig has nothing directly to do with that. Again, the sole purpose of STVIConfig is to allow the plugin manager UI to call config methods written in widget code rather than Java code. You have chosen to write widget code methods that use XmlConfig to do the bulk of the work. That's fine; that's a smart choice. But it doesn't directly relate to STVIConfig, which doesn't care about how your widget code methods do their job; all it cares about is how to invoke them when needed. By the way, you have the Java source code for both XmlConfig and STVIConfig if you want to find out exactly what they do. Quote:
It's not a a "SageTV internal process" that calls the PluginAPI methods. It's the plugin manager in the stock UI, which is a separate (and replaceable) component from the SageTV core. The core manages plugin installation and dependency resolution (step 2). The UI handles plugin configuration (steps 3-6). Also, it's misleading to say that the plugin manager calls PluginAPI methods to get config settings from the XML file and config values from the .properties file. In fact the plugin manager doesn't care where that information comes from or how it's stored; that's completely up to the plugin. It is true that if the plugin delegates those tasks to XmlConfig, then the effect of those calls will be to retrieve said information from the XML and .properties files. But that's not the purpose of those calls; the purpose is to allow the plugin to do whatever it does to provide that information. So the division of labor is thus: the plugin manager UI handles the display and editing of config settings; the plugin (perhaps delegating to XmlConfig) handles the definition and storage of config settings. Quote:
Quote:
You must implement getConfigSettings, since that's where everything starts. You must implement getConfigType, getConfigLabel, and getConfigHelpText, since those are common to all setting types. If you have any Choice or Multichoice settings, you must implement getConfigOptions. If you have any Multichoice settings, you must implement get/setConfigValues. If you have settings of any type other than Multichoice, you must implement get/setConfigValue. (However it also appears that getConfigValue can be called even on Multichoice settings, but it's not clear if that's a bug or by design.) And of course you have access to the plugin manager's widget code in the stock UI if you want to study that to see exactly what it does.
__________________
-- Greg |
#17
|
|||
|
|||
Ok, thanks Greg. Your explanations have really cleared things up for me and I really do appreciate you spending the time to explain these basic principles. I think I have enough understanding to give it a go.
|
#18
|
|||
|
|||
Is there a way to test the STVI Configurator plugin config before installing it as a plugin?
I tried: Execute widget chain on this: AddGlobalContext("HelloTableConfig", new_gkusnick_sagetv_XmlConfig("plugins/Hallowell/HelloTable/ConfigDefinitions.xml")) and then I tried F5 on Menu: Plugin Configure but that produced a blank Config screen. So then I noticed that the Plugin needs to be set before running that menu. So I searched for "Plugin Configure" but there wasn't a reference to that menu. |
#19
|
||||
|
||||
Quote:
Quote:
Yes, there is a reference; that's why the menu name appears in bold. But you won't find it with a string search, because there's only one widget with that name (the menu itself). Widget references aren't textual; they're pointers to the actual widget. You find them with the Highlight References command (or if you have my Studio Tools installed, the List Widget References command).
__________________
-- Greg |
#20
|
|||
|
|||
My STVI Configurator menu is not in bold or in italics.
And the action items all have a yellow square. (Screen shot attached) I tried uninstalling and reinstalling STVI Configurator and the same thing happens. I'm on SageTV 7.0.15 Windows XP SP3 Using a server and starting SageTV on the server. |
![]() |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
|
|
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
STVi Plugin: Phoenix Fanart for Malore Menus | tmiranda | SageTV v7 Customizations | 29 | 11-28-2015 01:28 PM |
MediaPlayer Plugin/STV Import: Winamp Media Player Plugin | deria | SageTV Customizations | 447 | 12-11-2010 07:38 PM |
STVi plugin request: Send TV show detailed info to an email recipient | mkanet | SageTV Customizations | 1 | 01-22-2006 03:59 PM |