Author Topic: Voice Attack GUID Processing/Treatment Questions  (Read 3998 times)

Starblue7

  • Full Member
  • ***
  • Posts: 131
Voice Attack GUID Processing/Treatment Questions
« on: May 13, 2023, 05:51:42 AM »
Hi,

I'm trying to make sure I understand how GUID works within VA and Plugins.

Regarding Profiles:

1.  Are Internal GUIDs in Voice Attack (if they exist) remaining STATIC for each .VAP (profile imported)?
Providing the author creates and indicates the GUID in their .vap prior to import?

2.  If a Profile is created within Voice Attack itself, does/can Voice Attack automatically assign an Internal GUID?
If not, does it require first an export of the .vap profile, then user creates a GUID (updates .vap and re-imports)?

Regarding Plugins:

1.  Does the Assembly Guid have any bearing and is it held anywhere within Voice Attack Proxy for retrieval?

2.  Is it a requirement to create an 'Assembly GUID' for plugin .dll creation?


General:

1.  If all Internal, Author, Product and Assembly GUIDs are missing, how is this treated within Voice Attack?



Thanks so much!

SemlerPDX

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 291
  • Upstanding Lunatic
    • My AVCS Homepage
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #1 on: May 13, 2023, 01:00:28 PM »
Hi,

I'm trying to make sure I understand how GUID works within VA and Plugins.

...

Thanks so much!


Start by reading the section of the VA Manual under Plugins (for the truly mad) called "VoiceAttack Plugin Requirements and Interface" - around page 191. This will get you up to speed on the requirements of plugins, and the "VoiceAttack Author Flags" section around page 250 regarding the use of these profile and command level flags.


Regarding Profiles:
1.  Are Internal GUIDs in Voice Attack (if they exist) remaining STATIC for each .VAP (profile imported)?
Providing the author creates and indicates the GUID in their .vap prior to import?

If you are referring to InternalID, AuthorID, and ProductID, these are static. These values as set are fixed or constant and do not change during profile imports. These values are not set by VoiceAttack, but by profile developers through exporting the profile as XML expanded .vap, and manually edited into it.



2.  If a Profile is created within Voice Attack itself, does/can Voice Attack automatically assign an Internal GUID?
If not, does it require first an export of the .vap profile, then user creates a GUID (updates .vap and re-imports)?

VoiceAttack never assigns the InternalID flag, or the ProductID or AuthorID flags, each exist for profile developers internal use only, and each require a GUID created by the user and manually edited into the (xml expanded) .vap file. When first created, you will see these flags as blank in the profile like this:
Code: [Select]
<AuthorID xsi:nil="true" />
<ProductID xsi:nil="true" />
<InternalID xsi:nil="true" />
All profiles do have an ID field which is a GUID set by VoiceAttack, yet this will be changed anytime a profile is exported.


Regarding Plugins:
1.  Does the Assembly Guid have any bearing and is it held anywhere within Voice Attack Proxy for retrieval?

By Assembly GUID, if you are referring to the GUID as circled in the picture below, as your IDE may see it for your plugin, this is not used by VoiceAttack and so while you may be able to programmatically access this GUID for a plugin (if needed), it is not presented by any vaProxy attributes afaik.


...but if you are referring to the required GUID for the plugin to be identified by VoiceAttack, this is required and has bearing in that it is how VoiceAttack identifies a plugin - any other plugins with this same GUID would be ignored as "already loaded".
Code: (csharp) [Select]
/// <summary>
/// Method to return a unique ID generated by the author so VoiceAttack can identify and use the plugin.
/// </summary>
/// <returns>The GUID of this plugin.</returns>
public static Guid VA_Id()
{
return new Guid("{1A2B3C4D-5E6F7A8B-901C2D3E-4F5A6B7C}");
}
I am personally unaware of any vaProxy attribute or method to retrieve the `Guid VA_Id()` of plugins.


2.  Is it a requirement to create an 'Assembly GUID' for plugin .dll creation?

If you are referring to the image above, the GUID in the Assembly Properties of this plugin (class library) in your IDE, this is not required but is recommended - VoiceAttack doesn't care about this, though.

If you are referring to the `Guid VA_Id()` that must be set in the plugin code as a public static method, this is required and must be unique to your plugin, and VoiceAttack uses it as the primary means to differentiate your plugin from other plugins.


General:
1.  If all Internal, Author, Product and Assembly GUIDs are missing, how is this treated within Voice Attack?

If the profile flags for InternalID, AuthorID, or ProductID are not set, these will simply be unavailable in the corresponding tokens or vaProxy attributes. The InternalID has special function, in that it can be used in an undocumented method for certain plugins to overwrite an existing profile with the same InternalID rather than importing a second profile of the same name ending in a number (such as "-1").

The Assembly GUID is not a profile flag, and again not sure if you mean in the IDE for the plugin or the required `Guid VA_Id()`, the former is ignored by VA and the latter is required for every plugin.

Starblue7

  • Full Member
  • ***
  • Posts: 131
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #2 on: May 13, 2023, 11:49:35 PM »
Thanks.

I think I pretty much got it.

I created GUIDs for my Profile and (future) Plugin.
I exported my .vap as xml, added those GUIDs and reimported.

I didn't add (I presume add, as nothing existed at the time) Any AuthorTags, which I presume would follow the format of <AuthorTag1></AuthorTag1>.

I'm not quite sure what good use they could be if I already have the GUIDs set up.

If AuthorTags have a compelling use-case, I'd like to know your thoughts.

Thanks!

SemlerPDX

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 291
  • Upstanding Lunatic
    • My AVCS Homepage
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #3 on: May 14, 2023, 11:30:15 AM »
The Author Tags can be strings (text), so they can be anything you want, and you must manually add them yourself if desired. Their data type is their compelling use-case, as we can put whatever info we need in these fields. 


Personally, I use the first for the build type (alpha/beta/release), and the second for the path name to configs for that profile on my website, and the third for the name and minor version. The third is what I check when switching to or from my AVCS CORE (main hub) profile - using {PREVIOUSPROFILE_AT3} or {NEXTPROFILE_AT3} to see if it starts with AVCS, and ignore if not... but if so, it grabs the three-letter name and the minor version number to identify and begin initialization for that profile (if not already initialized).

For a simplified example on how I use these, I add these three lines to my XML expanded .vap:
Code: (xml) [Select]
<AuthorTag1>release</AuthorTag1>
<AuthorTag2>falconbms</AuthorTag2>
<AuthorTag3>AVCSBMS42</AuthorTag3>

...as needed I could refer to these items in my profile as static readonly values that are always present in my profile(s) - even if all the commands were deleted from it, this data persists. They could be anything, for any use, I just happen to use them for profile identification and initialization in my AVCS CORE + AVCS4 (game) profiles.


Whatever you need to use these for, they are there as an option. Hope my example helps give ideas.  :D

Starblue7

  • Full Member
  • ***
  • Posts: 131
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #4 on: May 14, 2023, 05:15:04 PM »
Thanks.  That's a good idea.

I'm not really planning on going public at this point with any of what I'm doing.

My biggest challenge atm is to brush up on my coding and get some C# inline function working in VA..
I just hate defining and passing variables across functions etc.  I'd like to ADD args to already baked functions so I can return results from other operations I put in them, and not just what they're doing.

Example:

Code: [Select]
public void MyLogEntryAction(DateTime theDate, string theMessage, string theIconColor) <<< Add Bool actionPerformed arg to return back to main()
{
if (theMessage.Contains("BlahBlahBlah") & theIconColor.Contains("orange"));
{
VA.WriteToLog("<< INLINE >> Profile Loadup Confirmed", "black");
string MyCommandName = "POLLING ON";  <<< Would like to find a way to use the InternalID (GUID) as additional specification to focus on the command just for that Profile.
VA.Command.Execute(MyCommandName,true);
                        actionPerformed = true;
}
}

And I guess I can't ADD and argument for return because it's an ACTION.

Admittedly I'm quite rusty on coding as it's been years and I've never done C# before.
Anyways.  Probably elementary for most people writing code.

SemlerPDX

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 291
  • Upstanding Lunatic
    • My AVCS Homepage
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #5 on: May 14, 2023, 10:57:11 PM »
...

And I guess I can't ADD and argument for return because it's an ACTION.

You can - C# methods can return all sorts of information, and in the example below, could be used directly in an if-statement:
Code: (csharp) [Select]
public static bool MyLogEntryAction(dynamic VA, DateTime theDate, string theMessage, string theIconColor)
{           
  if (theMessage.Contains("BlahBlahBlah") & theIconColor.Contains("orange"));
  {
    VA.WriteToLog("<< INLINE >> Profile Loadup Confirmed", "black");

     // Find the actual GUID of the "POLLING ON" in the profile you want then use it like this
    Guid MyCommandNameGUID = new Guid("1A2B3C4D-5E6F7A8B-901C2D3E-4F5A6B7C");

    // Use the 'Execute(Guid InternalID, optional Boolean WaitForReturn)' method -- see pg. ~207 of the VA Manual
    VA.Command.Execute(MyCommandNameGUID, true);

    return true;
  }
  // ...if it didn't already return true, it will now return false:
  return false;
}


...(for example) you could call this like, as it would return true if the inner condition was met, or false if not:
Code: (csharp) [Select]
public class VAInline
{
  public void main()
  {
    if (MyLogEntryAction(VA, theDate, theMessage, theIconColor))
    {
      // ...do stuff
    }
  }

  public static bool MyLogEntryAction(dynamic VA, DateTime theDate, string theMessage, string theIconColor)
  {           
    if (theMessage.Contains("BlahBlahBlah") & theIconColor.Contains("orange"));
    {
      VA.WriteToLog("<< INLINE >> Profile Loadup Confirmed", "black");

       // Find the actual GUID of the "POLLING ON" in the profile you want then use it like this
      Guid MyCommandNameGUID = new Guid("1A2B3C4D-5E6F7A8B-901C2D3E-4F5A6B7C");

      // Use the 'Execute(Guid InternalID, optional Boolean WaitForReturn)' method -- see pg. ~207 of the VA Manual
      VA.Command.Execute(MyCommandNameGUID, true);

      return true;
    }
    // ...if it didn't already return true, it will now return false:
    return false;
  }
}

If you need some good references, check out these sites - w3schools is great for learning the basics of C# (and many languages) and it has "Try It" editors you can use to toy around with the concepts:

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/

https://www.w3schools.com/cs/index.php


...if you make an account at w3schools, you can track your progress through lessons and such:

Starblue7

  • Full Member
  • ***
  • Posts: 131
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #6 on: May 14, 2023, 11:08:23 PM »
Thanks for this!

I'll look at it a little closer.  But don't you have to convert the GUID to a string?

I guess I bring that up cause I'm also using this:

public void ProfileChanged(Guid? FromInternalID, Guid? ToInternalID, String FromName, String ToName)

Starblue7

  • Full Member
  • ***
  • Posts: 131
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #7 on: May 14, 2023, 11:24:10 PM »
And well, this line is causing error on compile:

if (MyLogEntryAction(VA, theDate, theMessage, theIconColor))

21: The name 'theDate' does not exist in the current context
21: The name 'theMessage' does not exist in the current context
21: The name 'theIconColor' does not exist in the current context

Which is calling this:

public static bool MyLogEntryAction(dynamic VA, DateTime theDate, string theMessage, string theIconColor)

SemlerPDX

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 291
  • Upstanding Lunatic
    • My AVCS Homepage
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #8 on: May 14, 2023, 11:26:13 PM »
Data types must be respected, else things will catch fire (err.. won't work).

If a method expects a "Guid" data type, the example I show above is a way to cast a string as a Guid which can then be provided to a method which expects a Guid data type.  You may also use the string directly with the Guid.Parse() method:

Code: (csharp) [Select]
VA.Command.Execute(Guid.Parse("1A2B3C4D-5E6F7A8B-901C2D3E-4F5A6B7C"), true);


...re:
And well, this line is causing error on compile:

if (MyLogEntryAction(VA, theDate, theMessage, theIconColor))

21: The name 'theDate' does not exist in the current context
21: The name 'theMessage' does not exist in the current context
21: The name 'theIconColor' does not exist in the current context

Which is calling this:

public static bool MyLogEntryAction(dynamic VA, DateTime theDate, string theMessage, string theIconColor)

That was a super basic example to show you how a static bool method could be used directly in an "if" statement. Whatever those values are would need to actually exist and be provided however you do that. They're just placeholders

try: if (MyLogEntryAction(VA, DateTime.Now, "BlahBlahBlah", "orange"))

edit: curly brackets not required in GUID strings, removed from examples above - curly brackets are typically used to visually represent a GUID, but they are not mandatory
« Last Edit: May 15, 2023, 12:45:12 AM by SemlerPDX »

Starblue7

  • Full Member
  • ***
  • Posts: 131
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #9 on: May 14, 2023, 11:31:03 PM »
Ok.  Um..  Thanks for jumping down the rabbit hole with me here..

Just testing out the code you provided to see if I can make it work.

As far as the GUID Parse,  I need to take the GUID captured in, let's say, GUID? ToInternalID and put that into a string so that I can compare it with one held in the string.

It's all in the vain of trying to make sure only:
1. Only the profiled intended to load is loaded.
2. Only the command from another profile is kicked off.

Ultimately at some point I'll want to try to prevent VA's Auto Profile switching via some way within code, so as, to make sure that if the user has it set, that it'll only switch to said profile when my code (Inline) is read for it to do so.
But that's another matter.

SemlerPDX

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 291
  • Upstanding Lunatic
    • My AVCS Homepage
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #10 on: May 14, 2023, 11:43:15 PM »
Your comments in your code suggested that you wanted to call the command ONLY from one particular profile, rather than by name, and my suggestion was that you find the actual InteralID (GUID) of that command (which would/could be different for different profiles with that same command), then use that literal string in the Execute(Guid InternalID) method around page 207 of the VA Manual to accomplish that goal.

Only commands in the active profile, and any global profiles, or in any profiles which are included in the active profile(s) can be executed. Unless you have a slew of active profiles loaded all with the same command, you shouldn't need to concern yourself with WHAT profile contains this command as it would be the ACTIVE profile.

I can't wrap my head around how you intend to develop your profile(s), or how they work, or why they work the way they do, but I can help point you in the right direction or towards the right sections of the VA Manual to focus on.  That, and where you can find more info about C#, and inlines/plugins for VA.

Starblue7

  • Full Member
  • ***
  • Posts: 131
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #11 on: May 14, 2023, 11:49:54 PM »
Sorry.

You're right on that.  My Profile is included in the commands for the other profile, so I guess I don't need the GUID compare for that.
I think it was more a precautionary step just incase myself or a friend accidently included a profile the the same command name or something.

In anycase.  I'll see what I can do to make the above code work without compile errors.  Kinda scratching my head on this.  As, my initial thought is that because it's a pre-defined action, that it won't like the VA added in and set as a Bool.

I do appreciate your help.

SemlerPDX

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 291
  • Upstanding Lunatic
    • My AVCS Homepage
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #12 on: May 14, 2023, 11:59:16 PM »
In the example I provided, your code had suggested a method which could return true when the inner actions occurred. But it contained actions which use the vaProxy object (which is "VA" in inline functions), and this would have to be provided to this method in some way - adding it as a dynamic input parameter to the method is one way to bring it into the method for access to the Execute() and WriteToLog() methods.

We are not (and cannot be) setting the VA as a Bool.

If you are so new to inline functions, you should be starting with some more basic examples which you can find on this forum, and also checking out that w3schools link to learn the basics of Methods in general.

Exergist has assembled a handful of useful inline functions, some that may be good examples (in both C# and VB) here:
https://forum.voiceattack.com/smf/index.php?topic=1307.0

SemlerPDX

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 291
  • Upstanding Lunatic
    • My AVCS Homepage
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #13 on: May 15, 2023, 12:16:59 AM »
For whatever it is worth, here is a convoluted example of the examples above which "works", in that it runs and will print to the Event Log - but you will need to read up on these concepts so you can design and employ them for yourself in actual useful methods which do your bidding.

As the comments state, the GUID portions are commented out and will not actually function unless provided with the InternalID (Guid) of an actual existing command in an active profile:
Code: (csharp) [Select]
using System;

public class VAInline
{
  public void main()
  {
    DateTime someDate = DateTime.Now;
    string someMessage = "Hello World";
    string someColor = "orange";
   
    if (MyLogEntryAction(VA, someDate, someMessage, someColor))
    {
      // ...do stuff
      VA.WriteToLog("My Hello World Test is complete", "pink");
    }
  }

  public static bool MyLogEntryAction(dynamic VA, DateTime theDate, string theMessage, string theIconColor)
  {           
    if (theMessage.Contains("Hello World") & theIconColor.Contains("orange")); //(incorrect semicolon!!)
    {
      VA.WriteToLog("<< INLINE >> Profile Loadup Confirmed", "black");

      // Find the actual GUID of the "POLLING ON" command in the XML expanded .vap profile you want then use it like this
      //Guid MyCommandNameGUID = new Guid("1A2B3C4D-5E6F7A8B-901C2D3E-4F5A6B7C");

      // Use the 'Execute(Guid InternalID, optional Boolean WaitForReturn)' method -- see pg. ~207 of the VA Manual
      //VA.Command.Execute(MyCommandNameGUID, true);

      // THE GUID EXAMPLES ABOVE WILL NOT WORK UNTIL PROVIDED BY A TRUE GUID OF AN EXISTING COMMAND!!!

      return true;
    }
    // ...if it didn't already return true, it will now return false:
    return false;
  }
}
« Last Edit: May 16, 2023, 02:49:32 PM by SemlerPDX »

Starblue7

  • Full Member
  • ***
  • Posts: 131
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #14 on: May 15, 2023, 10:08:56 PM »
For whatever it is worth, here is a convoluted example of the examples above which "works", in that it runs and will print to the Event Log - but you will need to read up on these concepts so you can design and employ them for yourself in actual useful methods which do your bidding.

As the comments state, the GUID portions are commented out and will not actually function unless provided with the InternalID (Guid) of an actual existing command in an active profile:
Code: (csharp) [Select]
using System;

public class VAInline
{
  public void main()
  {
    DateTime someDate = DateTime.Now;
    string someMessage = "Hello World";
    string someColor = "orange";
   
    if (MyLogEntryAction(VA, someDate, someMessage, someColor))
    {
      // ...do stuff
      VA.WriteToLog("My Hello World Test is complete", "pink");
    }
  }

  public static bool MyLogEntryAction(dynamic VA, DateTime theDate, string theMessage, string theIconColor)
  {           
    if (theMessage.Contains("Hello World") & theIconColor.Contains("orange"));
    {
      VA.WriteToLog("<< INLINE >> Profile Loadup Confirmed", "black");

      // Find the actual GUID of the "POLLING ON" command in the XML expanded .vap profile you want then use it like this
      //Guid MyCommandNameGUID = new Guid("1A2B3C4D-5E6F7A8B-901C2D3E-4F5A6B7C");

      // Use the 'Execute(Guid InternalID, optional Boolean WaitForReturn)' method -- see pg. ~207 of the VA Manual
      //VA.Command.Execute(MyCommandNameGUID, true);

      // THE GUID EXAMPLES ABOVE WILL NOT WORK UNTIL PROVIDED BY A TRUE GUID OF AN EXISTING COMMAND!!!

      return true;
    }
    // ...if it didn't already return true, it will now return false:
    return false;
  }
}

Well, even just initially, the odd thing about the above code is, when the inline function is kicked off and the MyLogEntryAction is kicked off due to a change in the Event Log, the code STILL writes the below to the Event Log EVEN  if no item in the event log meets the criteria:

i.e.  Criteria =  theMessage.Contains("Hello World") & theIconColor.Contains("orange")

I presume BOTH the above must be true in order for the subsequent line to be written in the Event Log:
<< INLINE >> Profile Loadup Confirmed


However, even if there is NO Hello World coupled with the color orange , the line above within the IF statement still prints in the log anyways.

This is strange behavior.  Even if the color orange exists already within the eventlog, there's never been any value of Hello World written in the log to generate the outcome.

SemlerPDX

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 291
  • Upstanding Lunatic
    • My AVCS Homepage
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #15 on: May 16, 2023, 12:08:36 AM »
Well, even just initially, the odd thing about the above code is, when the inline function is kicked off and the MyLogEntryAction is kicked off due to a change in the Event Log, the code STILL writes the below to the Event Log EVEN  if no item in the event log meets the criteria:

i.e.  Criteria =  theMessage.Contains("Hello World") & theIconColor.Contains("orange")

I presume BOTH the above must be true in order for the subsequent line to be written in the Event Log:
<< INLINE >> Profile Loadup Confirmed


However, even if there is NO Hello World coupled with the color orange , the line above within the IF statement still prints in the log anyways.

This is strange behavior.  Even if the color orange exists already within the eventlog, there's never been any value of Hello World written in the log to generate the outcome.

You are correct that both of those conditions must be true to meet the stated criteria, however all the way back to your original code example, a ";" (semicolon) has persisted at the end of the "if" statement line, thus making it a self-contained expression that accomplishes nothing, and turning the section below it contained in curly brackets into merely a nested code block that runs regardless of any line above it which ends in a ";" (semicolon).

It followed into my examples when I copied your code to alter it and I didn't catch it myself as it was rather late at night.

Remove that semicolon, and it will function as you'd expect. It will evaluate BOTH the left and right condition each time it is encountered, and only if both meet that criteria will the lines of code within the "if" statement be executed.


Starblue7

  • Full Member
  • ***
  • Posts: 131
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #16 on: May 16, 2023, 05:54:26 AM »
Yeah thanks.  Couldn't believe I missed that...

Do you know if there is an example PLUGIN project (uncompiled) that I could feed into Visual Studio and go thru the exercise with compiling it and getting it in to VA?

Something simple, but a starting point for the exercise?

Thanks muchos.

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4790
  • RTFM
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #17 on: May 16, 2023, 05:56:59 AM »
VoiceAttack comes with such a project; extract PluginSampleC#.zip which can be found under "Plugin Samples\C#" within VoiceAttack's installation directory.

Starblue7

  • Full Member
  • ***
  • Posts: 131
Re: Voice Attack GUID Processing/Treatment Questions
« Reply #18 on: May 16, 2023, 06:29:48 AM »
VoiceAttack comes with such a project; extract PluginSampleC#.zip which can be found under "Plugin Samples\C#" within VoiceAttack's installation directory.

Sorry Pfeil, and thanks.  You're of course correct.  I totally forgot about it...  :(