Button works in development but not in app

If you find an issue in LiveCode but are having difficulty pinning down a reliable recipe or want to sanity-check your findings with others, this is the place.

Please have one thread per issue, and try to summarize the issue concisely in the thread title so others can find related issues here.

Moderator: Klaus

Post Reply
nickvoll
Posts: 3
Joined: Tue Sep 20, 2022 4:14 am

Button works in development but not in app

Post by nickvoll » Tue Sep 20, 2022 4:38 am

Hi,
I've built an application that connects CasparCG (a video and graphics playback engine for broadcasting) with LiveXML, which outputs data from scoreboards at sporting events. For several years, I have had the same code, which has worked perfectly within LiveCode during broadcasts (and still does). Recently, I exported my app for Windows and Mac so that others can use it. However, the button that automates the scoreboard graphics on screen does not work in the exported versions for either OS. When I reopen LC and run it there, everything is fine. I am at a loss as to what I should do, or what might be causing this.

Here's the basic workflow:
- LiveXML collects scoreboard data from the game site and deposits it in an XML file on my desktop.
- My application reads the XML file every 100 milliseconds. It puts all existing data into variables, and then checks to see if the new information from the game is different. If not, it ignores the new data. If so, it triggers buttons in the application to update the graphics on screen with the new data, as if a person had done it with a mouseclick. That way I can trigger animations as the data is updated.
- Besides seeing the clock moving, I can tell when it's working because there's a large amount of activity on my CasparCG server, which I can see.

Instead of running every 100 milliseconds, the button on the finished app appears to only run once, and then never again. Here's the code:

Code: Select all

global tVscoreholder
global tHscoreholder
global tHtimeoutsholder
global tVtimeoutsholder
global tHTOGraphicholder
global tVTOGraphicholder
global tQuarterholder
global tDownholder
global tDownonlyholder
global tDistanceholder

on mouseUp
   if backgroundcolor of button "Automate Countdown" is red then
      send mouseUp to button "Automate Countdown"
      end if
   
   if label of me is "Automate Scorebug" then
      set label of me to "Stop Automation"
      set the backgroundcolor of me to red
      put field T1Score into tVscoreholder
      put field T2Score into tHscoreholder
   loadXML

else
   set the label of me to "Automate Scorebug"
   set the backgroundcolor of me to green
end if

end mouseUp

command loadXML
   if label of me is "Stop Automation" then
      local tTree
      put readToXMLTree() into tTree
      if tTree is empty then
         
         
         wait 1 second with messages
         put readToXMLTree() into tTree
         
      end if
      
      processXMLTree tTree
      
      revXMLDeleteTree Tree

         send "loadXML" to me in .1 seconds 
     
      
   else if label of me is "Automate Scorebug" then
      exit to top
   end if
end loadXML

private function readToXMLTree
   set the itemdelimiter to slash
   
   set the itemdelimiter to comma
   
   local tXMLData, tResult
   put field "xmlfile" into xmlFileName
   put url("file:" & specialFolderPath("desktop") & slash & xmlFileName & ".xml") into tXMLData
   put the result into tResult
   if tResult is not empty then
      put cr & the date && "-" && the time & ":" & cr & "Error: " && tXMLFile  before field "errorfield"
      wait 1 second with messages
      return empty
      send "loadXML" to me
   end if
   
   local tTree
   put revXMLCreateTree(tXMLData, false,true,false) into tTree
   if tTree is not an integer then
      
      put cr & the date && "-" && the time & ":" & cr & "Error: " && tTree  before field "errorfield"
      wait 1 second with messages
      return empty
      send "loadXML" to me
      
   end if
   
   return tTree
end readToXMLTree

private command processXMLTree pTree
   local  tClock
   put revXMLNodeContents(pTree, "info/clock") into tClock
   put revXMLNodeContents(pTree, "info/shotclock") into tShotclock
   put revXMLNodeContents(pTree, "info/Hscore") into tHscore 
   put revXMLNodeContents(pTree, "info/Vscore") into tVscore
   put revXMLNodeContents(pTree, "info/quarter") into tQuarter
   put revXMLNodeContents(pTree, "info/Htimeouts") into tHtimeouts
   put revXMLNodeContents(pTree, "info/Vtimeouts") into tVtimeouts
   put revXMLNodeContents(pTree, "info/HTOGraphic") into tHTOGraphic
   put revXMLNodeContents(pTree, "info/VTOGraphic") into tVTOGraphic
   put revXMLNodeContents(pTree, "info/down") into tDown
   put revXMLNodeContents(pTree, "info/togo") into tTogo
   
   
   put "cg" && field "CasparCGChannel" &&" update 1"  into s1xml
   put quote after s1xml
   put "<templateData>" after s1xml
   
   ###CLOCK###
   put "<componentData id=\" after s1xml
   put quote after s1xml
   put "gameclock\" after s1xml
   put quote after s1xml
   put "><data id=\" after s1xml
   put quote after s1xml
   put "text\" after s1xml
   put quote after s1xml
   put " value=\" after s1xml
   put quote after s1xml
   put tClock after s1xml
   put tClock into field "DataFeedClock"
   put "\" after s1xml
   put quote after s1xml
   put " /></componentData>" after s1xml
   
   
   
   ###SCORE###
   if tHscore <> tHscoreholder then
      
      put tHscore - tHscoreholder into scoreAmt
      
      put "Team2plus"& scoreAmt into buttonSend
      if exists(button buttonSend) then
         send mouseDown to button buttonSend
         send mouseUp to button buttonSend
      else
         put tHscore into field T2Score
         send textchanged to field T2Score
      end if
      put tHscore into tHscoreholder
      
   end if
   
   if tVscore <> tVscoreholder then
      
      put tVscore - tVscoreholder into scoreAmt
      
      put "Team1plus"& scoreAmt into buttonSend
      if exists(button buttonSend) then
         send mouseDown to button buttonSend
         send mouseUp to button buttonSend
      else
         put tVscore into field T1Score
         send textchanged to field T1Score
      end if
      put tVscore into tVscoreholder
      
   end if
   
   
   ####TIMEOUTS####
   if tHtimeouts <> tHtimeoutsholder then
      if tHtimeoutsholder is "Hide" then
      else
         
         send mousedown to button "t2to"
         set the label of button "t2to" to tHtimeouts
         send mouseup to button "t2to"
         put tHtimeouts into tHtimeoutsholder 
      end if
   end if
   
   if tVtimeouts <> tVtimeoutsholder then
      if tVtimeoutsholder is "Hide" then
      else
         
         send mousedown to button "t1to"
         set the label of button "t1to" to tVtimeouts
         send mouseup to button "t1to"
         put tVtimeouts into tVtimeoutsholder
      end if
   end if
   
   
   
   #### QUARTER ####
   
   if tQuarter <> tQuarterholder then
      
      put "<componentData id=\" after s1xml
      put quote after s1xml
      put "quarter\" after s1xml
      put quote after s1xml
      put "><data id=\" after s1xml
      put quote after s1xml
      put "text\" after s1xml
      put quote after s1xml
      put " value=\" after s1xml
      put quote after s1xml
      
      if tQuarter is "1" then
         put tQuarter & "st" into tQuarteredit
         put tQuarteredit after s1xml
      else if tQuarter is "2" then
         put tQuarter & "nd" into tQuarteredit
         put tQuarteredit after s1xml
      else if tQuarter is "3" then 
         put tQuarter & "rd" into tQuarteredit
         put tQuarteredit after s1xml
      else if tQuarter is "4" then
         put tQuarter & "th" into tQuarteredit
         put tQuarteredit after s1xml
      else if tQuarter is "5" then
         put "OT" into tQuarteredit
      else if tQuarter is "6" then
         put "2OT" into tQuarteredit
      else if tQuarter is "7" then
         put "3OT" into tQuarteredit
      else if tQuarter is "8" then
         put "4OT" into tQuarteredit
      end if
      set the label of button "quarter" to tQuarteredit
      
      if tQuarteredit is "1st" then
         set label of button "QuarterSelector" to "End of 1st Quarter"
      end if
      if tQuarteredit is "2nd" then
         set label of button "QuarterSelector" to "Halftime"
      end if
      if tQuarteredit is "3rd" then
         set label of button "QuarterSelector" to "End of 3rd Quarter"
      end if
      if tQuarteredit is "4th" then
         set label of button "QuarterSelector" to "Final"
      end if
      if tQuarteredit is "OT" then
         set label of button "QuarterSelector" to "OT"
      end if
      
      put "\" after s1xml
      put quote after s1xml
      put " /></componentData>" after s1xml
      put tQuarter into tQuarterholder
   end if
   
   
   ### DOWN AND DISTANCE ###
   
   
   write invokexml  & format("\r\n") to socket server
   if tDown && "&" && tTogo <> tDownholder then
      put field IP after server
      put "cg" && field "CasparCGChannel" && "invoke" && field "ScorebugFlashLayer" && quote & "removedowndistanceholder" &quote   into invokexml
      
      write invokexml  & format("\r\n") to socket server
      if tDown <> tDownonlyholder then
         
      end if
      if the hilite of button "autodowndistance" is true then
         put label of button "downdistanceinterval" into downdistanceinterval
         
         send mousedown to button "downdistance" in downdistanceinterval seconds 
      end if
      
      if tDown is "1" then
         put "1st" into tDownedit
      else if tDown is "2" then
         put "2nd" into tDownedit
      else if tDown is "3" then
         put "3rd" into tDownedit
      else if tDown is "4" then
         put "4th" into tDownedit
      end if
      set the label of button "down" to tDownedit
      put tTogo into field "distance"
      set the label of button "downdistance" to "Show Down and Distance"
      set the backgroundcolor of button downdistance to gray
      put tDown into tDownonlyholder
      put tDown && "&" && tTogo into tDownholder
      
      
      
      put "cg" && field "CasparCGChannel" && "update" && field "ScorebugFlashLayer"  into ddxml
      put quote after ddxml
      put "<templateData>"after ddxml
      
      put "<componentData id=\" after ddxml
      put quote after ddxml
      put "downdistanceholder\" after ddxml
      put quote after ddxml
      put "><data id=\" after ddxml
      put quote after ddxml
      put "text\" after ddxml
      put quote after ddxml
      put " value=\" after ddxml
      put quote after ddxml
      put label of button "down" && "and" && field "distance" after ddxml
      put "\" after ddxml
      put quote after ddxml
      put " /></componentData></templateData>" after ddxml
      put quote after ddxml
      
      write ddxml  & format("\r\n") to socket server
      
   end if
   put "</templateData>" after s1xml
   put quote after s1xml
   put field IP after server
   write s1xml  & format("\r\n") to socket server
   if tDown is empty then
      put field IP after server
      put "cg" && field "CasparCGChannel" && "invoke" && field "ScorebugFlashLayer" && quote & "removedowndistanceholder" &quote   into invokexml
   end if
   
   if tTogo is empty then
      put field IP after server
      put "cg" && field "CasparCGChannel" && "invoke" && field "ScorebugFlashLayer" && quote & "removedowndistanceholder" &quote   into invokexml
      
      write invokexml  & format("\r\n") to socket server
   end if
   
end processXMLTree


end readToXMLTree

SWEdeAndy
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 324
Joined: Sat Aug 16, 2008 9:48 am
Contact:

Re: Button works in development but not in app

Post by SWEdeAndy » Tue Sep 20, 2022 7:19 am

Hi nickvoll,

Since it works in LC but not as standalone, my first action would be to check the Standalone application settings and make sure the necessary inclusions have been ticked. It seems your app would need the XML and Internet inclusions, at least.

If this is not the problem, then maybe something to do with permissions to save the file to desktop when running the standalones?
Andreas Bergendal
Independent app and system developer
Free LC dev tools: https://github.com/wheninspace
(WIS_WebDeployHelper, WIS_ScriptDependencies, WIS_BrowserAnimation)
WhenInSpace: https://wheninspace.com

stam
Posts: 3069
Joined: Sun Jun 04, 2006 9:39 pm

Re: Button works in development but not in app

Post by stam » Tue Sep 20, 2022 9:13 am

Not related to the current question (which does sound like an inclusions issue), I had another suggestion.

If distributing the app, maybe the desktop is not a good place to put an intermediary file? I know I’d get annoyed as a user if an app did that.

Perhaps a better place would be documents, or even better Application Support/appdata? (Ie specialFolderPath (“support”)?)

S.

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10315
Joined: Wed May 06, 2009 2:28 pm

Re: Button works in development but not in app

Post by dunbarx » Tue Sep 20, 2022 2:27 pm

I agree about the inclusions. A stack that works in the IDE but not as a standalone almost always has this as the cause..

Do you let LC select your inclusions, or do you select them by hand? I never let LC do it, as it often misses things. And if you do it, make sure you select all those that you require. This is sometimes not obvious.

Craig

nickvoll
Posts: 3
Joined: Tue Sep 20, 2022 4:14 am

Re: Button works in development but not in app

Post by nickvoll » Tue Sep 20, 2022 11:16 pm

Hey all, thanks for the good suggestions. First, I checked the XML box in the inclusions section and reexported it, and am having the same issue.

I realized after I made my initial post that I also have a similar script in my app to control another graphic, and it works in both the development environment as well as in the published app. The other script is a bit simpler, as it is controlling fewer elements in the graphic, but the base code is the same, reading the XML and converting it to the graphics. I've been trying to compare the two scripts and I don't see anything too different in there.

As for putting the XML on the desktop, I could definitely move it elsewhere. I just need to tell the LiveXML program to put it documents or wherever.

Any other ideas?

SparkOut
Posts: 2944
Joined: Sun Sep 23, 2007 4:58 pm

Re: Button works in development but not in app

Post by SparkOut » Wed Sep 21, 2022 7:25 am

Do you have the issue immediately on using the standalone built on the same machine as the IDE?
Are there any invisible or transparent objects? Are there any resizing handlers?
Sometimes on different machines/different screen metrics/operating systems/display managers the objects are not rendered precisely in the same positions. Could there be anything that (now) overlays the button that you can't see, but that is intercepting the mouse events?

stam
Posts: 3069
Joined: Sun Jun 04, 2006 9:39 pm

Re: Button works in development but not in app

Post by stam » Wed Sep 21, 2022 9:02 am

I had this exact issue recently; a non-opaque field was covering half a button and it took me a little while to realise that was the case.
Try moving the button to the front?

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10315
Joined: Wed May 06, 2009 2:28 pm

Re: Button works in development but not in app

Post by dunbarx » Wed Sep 21, 2022 2:48 pm

I am not seeing something. Where is the issue of a missing button in play? I thought this was all about standalones not working as the stack in the IDE.

Craig

SparkOut
Posts: 2944
Joined: Sun Sep 23, 2007 4:58 pm

Re: Button works in development but not in app

Post by SparkOut » Wed Sep 21, 2022 6:33 pm

In the first post of the thread, nickvoll wrote:
Tue Sep 20, 2022 4:38 am
However, the button that automates the scoreboard graphics on screen does not work in the exported versions for either OS. When I reopen LC and run it there, everything is fine. I am at a loss as to what I should do, or what might be causing this.
The issue is all about a button 'not working' (as opposed to being 'missing') in a standalone, yet it does work in the IDE. We're just guessing at reasons why.

nickvoll
Posts: 3
Joined: Tue Sep 20, 2022 4:14 am

Re: Button works in development but not in app

Post by nickvoll » Wed Sep 21, 2022 8:01 pm

As far as I know, nothing is in front of the button, and I typically have developed and tested on the same machine. Also, I think I mentioned it earlier, but perhaps not... when I click the button it runs one time, and partially populates the graphic. It should, however, loop every 100 milliseconds. My first thought was that something was wrong with my loop structure, but it works in the IDE, sooooo?

I was trying to share the project and exe with you all, but I can't post a link to a Google Drive folder, and the app is too big for an attachment. I broke up the URL below, so you can visit the folder.

https://
drive google com/drive/folders/1x4Ff2Sn5-mDAhkO1E7rGUj-Kuaj-Xfy1?usp=sharing



Thanks all for the help.

mwieder
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3581
Joined: Mon Jan 22, 2007 7:36 am
Contact:

Re: Button works in development but not in app

Post by mwieder » Fri Sep 23, 2022 4:16 am

Since I'm not hooked up to your server, it's a bit hard to tell exactly what to expect, but...

Try moving the 'send "loadXML" to me in 0.2 seconds' line higher in the loadXML handler. That got the loop going for me.
Since I'm getting xml errors because of not getting a data stream from the server, execution of the handler is terminated at the error point, thus it never gets to the "send" command.

This may be at least similar to what you're seeing: the datastream is present when you're running in the IDE but you're not connecting properly from the standalone, and thus getting an xml error before ever reaching the line that would keep the automation running.

...and you might want to put an escape routine in loadXML... once I got the repetition every .2 seconds I had to force-quit both the standalone and the IDE. Maybe something like

Code: Select all

if the controlKey is up then
    send "loadXML" to me in 0.2 seconds
end if

Post Reply