sabato 13 ottobre 2018

Immagini scalate prospettivamente

Oggi vediamo un programma per modificare prospetticamente le immagini:
Lo potete scaricare da qui: http://livecodeshare.runrev.com/stack/893
Vi basterà copiare il gruppo hhPoly nella vostra card ed usare il codice:


send ("setTarget " & the short name of image miaImmagine) to group "hhPoly"

Semplice no?

martedì 11 settembre 2018

Libreria per Poker

Ecco la mia libreria per il gioco del Poker:



on MouseUp
   #hand notation like:
   #1c,2d,3h,4s,13s
   put field "hand" into tHand
   put analPoint(thand) into field 2
end MouseUp

function analPoint tHand
   sort items of thand numeric by the char 1 to -2 of each
   repeat with i=1 to 5
      put item i of tHand into th[i]
   end repeat
   #we must go in order
   #https://www.pagat.com/poker/rules/ranking.html
   ######################
   #Straight Flush
   put true into testsuit
   repeat with i=2 to 5
      if the last char of th[i - 1] is not the last char of th[i] then put false into testsuit
   end repeat
   if testsuit then #they have the same suit
      if checkscale(th) then
         return "Straight Flush: " & maxcard(th,"Straight Flush")
      end if
   end if
   ##############################
   #Four of a kind   
   put countDup(th) into duplist
   repeat for each key tKey in duplist
      if dupList[tKey] = 4 then return "Four of a kind: " & tKey
   end repeat
   ###############################
   #Full House
   repeat for each key tKey in duplist
      if dupList[tKey] = 3 then
         put tkey into FH3
         repeat for each key tKey2 in duplist
            if dupList[tKey2] = 2 then
               put tkey2 into FH2
               return "Full House: " & FH3 & "." & FH2
            end if
         end repeat
      end if
   end repeat
   ##############################################
   #Flush
   if testsuit then
      sort items of thand descending numeric by the char 1 to -2 of each
      repeat with i=1 to 5
         delete the last char of item i of thand
      end repeat
      return "Flush: " & thand
   end if
   #####################################################
   #Straight
   if checkscale(th) then
      return "Straight: " & maxcard(th,"Straight")
   end if
   #############################
   #Three of a Kind
   repeat for each key tKey in duplist
      if dupList[tKey] = 3 then
         put tkey into FH3         
         return "Three of a Kind: " & FH3
      end if
   end repeat
   #############################
   #Two Pairs
   repeat for each key tKey in duplist
      if dupList[tKey] = 2 then
         put tkey into P1
         put 0 into dupList[tKey]
         repeat for each key tKey2 in duplist
            if dupList[tKey2] = 2 then
               put tkey2 into P2
               put P1 & comma & P2 into PT
               sort items of PT descending numeric
               return "Two Pairs: " & PT
            end if
         end repeat
      end if
   end repeat
   ###########################
   #Pair
   repeat for each key tKey in duplist
      if dupList[tKey] = 2 then         
         return "Two Pairs: " & tKey
      end if
   end repeat
   #############################
   #Nothing
   return "Nothing: " & maxcard(th,"Nothing")
end analPoint

function countDup th
   repeat for each element tele in th
      add 1 to temp[char 1 to -2 of tele]
   end repeat
   return temp
end countDup
   
function checkScale th #check if it is a scale   
   if checkace(th) and checkKing(th) then
      put th into th2 #backup
      put swapace(th) into th #now aces are 14 in value
   end if
   #we need to sort again
   put sortedArray(th) into th
   put true into test1
   repeat with i=2 to 5
      if ((char 1 to -2 of th[i-1]) + 1) is not (char 1 to -2 of th[i]) then put false into test1
   end repeat
   return test1
end checkscale

function checkAce th
   put false into test1
   repeat for each element tele in th
      delete the last char of tele
      if tele = 1 then put true into test1
   end repeat
   return test1
end checkace

function checkKing th
   put false into test1
   repeat for each element tele in th
      delete the last char of tele
      if tele = 13 then put true into test1
   end repeat
   return test1
end checkKing

function SwapAce th
   repeat with i=1 to 5         
      if char 1 to -2 of th[i] = 1 then put 14 into char 1 to -2 of th[i]
   end repeat
   return th
end SwapAce

function sortedArray @pArray   
   
   # fetch the keys and sort them using the array entry values
   get the keys of pArray
   sort lines of it numeric by char 1 to -2 of pArray[each]
   
   split it by return
   
   # create a new sorted array using the mapped keys
   put 1 into tNextIndex
   repeat for each element tIndex in it
      put pArray[tIndex] into tSortedArray[tNextIndex]
      add 1 to tNextIndex
   end repeat
   
   return tSortedArray
end sortedArray

function maxcard th, hType
   switch htype
      case "Straight"
      case "Straight Flush"
         if checkace(th) and checkKing(th) then
            return "ACE (14)"
         else
            return maxcard2(th)
         end if
         break
      case "Nothing"
         return maxcard2(th)
         break
   end switch
end maxcard

function maxcard2 th
   put 0 into temp
   repeat for each element tele in th      
      if char 1 to -2 of tele > temp then put char 1 to -2 of tele into temp
   end repeat
   return temp
end maxcard2

lunedì 10 settembre 2018

Nuova versione

Il 4 Settembre è stata rilasciata la versione 9.0.1 RC 3. La potete scaricare da qui: https://downloads.livecode.com/livecode/
Tra le novità abbiamo:
  • androidRequestPermission:  permette di chiedere all'utente su Android dei permessi temporaneamente.
  • nuove funzione per il volume stereo su Mac
  • mobileSetFullScreenRectForOrientations
  • correzioni di vari bug

mercoledì 29 agosto 2018

Video come creare un gioco i pochi minuti

Ho appena realizzato un video dove mostro come ealizzare un gioco stile Breakout / Arkanoid in pochi minuti.
Lo potete vedere qui:

mercoledì 22 agosto 2018

Lavorare in gruppo

Come fanno le grandi aziende con grossi team ad usare Livecode?
Questa domanda nasce spontanea quando ci si rende conto che il sorgente livecode è un file binario che contiene tutto, immagini, suoni, codice, ecc.
I sistemi di controllo della versione usuali non gestiscono le differenze di questo tipo di file.
Esistono diverse soluzioni, ma tra le più collaudate c'è Levure, che potete scaricare qui:
https://github.com/trevordevore/levure/wiki
In pratica i programmi creati con Levure/Livecode hanno il codice messo a parte, in file di testo separati, ed è possibile quindi utilizzare qualunque sistema di controllo della versione, come GIT.
Chiaramente ha senso solo se state lavorando in tanti su un enorme progetto.

giovedì 9 agosto 2018

Calendar Plugin

E' disponibili un plugin per avere un selettore della data semplice da usare:
Qui trovate la pagina ufficiale: http://www.maxvessi.net/pmwiki/pmwiki.php?n=Site.CalendarPlugin
E' configurabile, supporta tutte le lingue che volete, quando appare si riposiziona sempre in modo che sia visibile e ha altre funzionalità descritte nella pagina; ma soprattutto è gratuito!


lunedì 6 agosto 2018

Il ritorno dell'application browser

Il caro e vecchio application browser non è sparito da Livecode, ma adesso si trova dentro la linguetta Plugins, sotto il nome di revApplicationOverview:
Io lo proferisco rispetto al Project browser, perchè è molto più veloce.

giovedì 2 agosto 2018

Supporto CPU Android armv7, arm64, x86, x86_64

E' stato appena pubblicato su GitHub l'ultima modifica per permettere a Livecode di creare app Android per tutti i processori (armv7, arm64, x86, x86_64).
Come forse sapete Android era nato su armv7 e solo ultimamente qualche sistema lo sta utilizzando su altri processori, per questo le app livecode giravano solo su processori Arm (quelle di cellulari e tablet).
La prossima versione di livecode utilizzerà questa modifica e le app Android funzioneranno su tutto.

martedì 22 maggio 2018

Verificare email

Se volete verificare che un indirizzo email sia valido, vi basta utilizzare un'espressione regolare, ecco il codice con livecode:

put "((?i)(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|" & quote & "(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*" & quote & ")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\]))" into regemail
put matchtext(tEmail,regemail,controllo) into temp
if controllo is not tEmail then
   answer tEmail " non è un indirizzo email valido"
else
   answer tEmail " è un indirizzo email valido"
end if


Chiaramente la variabile tEmail contiene l'indirizzo da verificare.

venerdì 18 maggio 2018

Animazioni: indipendenti o ciclo padre?

Livecode permette di fare animazioni e videogiochi in diverse modalità.
Una delle caratteristiche più apprezzate è che ad ogni oggetto si può dire di muoversi in una certa maniera, usare un percorso, in maniera relativa e assoluta. Tutto utilizzando il comando move.
Questo permette di creare animazioni molto complesse con sprite e disegni che si muovono tutti per conto loro, prendono anche decisione autonome.
D'altro canto utilizzare move implica che non dovete bloccare lo schermo con  lock screen per calcolare e costruire nuove immagini.
Lock screen si usa quando non volete far vedere tutti gli spostamenti sullo schermo, ma passare da una configurazione ad un'altra. Se dovete piazzare all'improvviso un'immagine, ma non avete idea delle dimensioni e volete bloccare lo schermo per fare i calcoli, non potete utilizzare anche move; il risultato complessivo verrebbe come un'animazione a singhiozzo.
In tal caso vi conviene utilizzare un unico ciclo che blocca lo schermo, fa tutti gli spostamenti e calcoli, e poi sblocca lo schermo per dare l'effetto di animazione.
Per utilizzare un unico ciclo vi consiglio il comando send "ciclo" to me in 33 millisec; 33 millisecondi è il tempo di aggiornamento ideale per l'occhio umano, un tempo più corto non ha senso, mentre un tempo più lungo vi potrebbe servire se i calcoli sono talmente complessi che per ogni aggiornamento dello schermo vi servono più di 33 millisecondi.
Sta a voi decidere ogni volta quale strada intraprendere a seconda dell'applicazione che state programmando.

sabato 12 maggio 2018

Spesso Livecode è l'unica soluzione

Immaginate di avere un sistema VoIP particolare, un sistema android da interfacciare e siete voi l'incaricato di trovare una soluzione, beh quando si tratta di sistemi variegati livecode diventa l'unica soluzione, ecco un video di esempio:
https://www.facebook.com/rich.blackmore3/videos/1912590665426648/


https://www.facebook.com/rich.blackmore3/videos/1912590665426648/

venerdì 11 maggio 2018

Offerta speciale: livecode hosting a vita

Liveocde ha appena lanciato l'offerta Livecode hosting sul loro cloud a vita a per €499.
Qui trovate tutti i  dettagli, che ne pensate?
https://livecode.com/hosting/pricing/#!/~/

lunedì 23 aprile 2018

Nuova versione di Piccolo installer

E' uscito un mio nuovo aggiornamento di Piccolo Installer, uno stack di Livecode per creare OSX e Windows installers.
Tutte le informazioni qui: https://www.software.trevix.it/piccolo_installer/
Potete inoltre scaricarlo all'interno di LC, su Sample Stacks.

Ringraziamo Marco Trevisan per la segnalazione.

mercoledì 11 aprile 2018

Risolvere il bug del dizionario di livecode 9 su Linux

Su alcune distribuzioni Linux il dizionario appare bianco, c'è un bug misterioso che affligge la libreria di sqlite dbsqlite.so e al momento per risolverla c'è da aggiornare sqlite3 all'ultima versione e copiare il vecchio dbsqlite.so da livecode 8.
Quindi dopo aver aggiornato sqlite vi conviene eseguire come root, oppure con sudo i seguenti comandi:


cd /opt/livecode/livecodecommunity-9.0.0.x86_64/Externals/Database\ Drivers

mv dbsqlite.so dbsqlite.so.bak

cp /opt/livecode/livecodecommunity-8.2.0-dp-2.x86_64/Externals/Database\ Drivers/dbsqlite.so ./

cd ../../Runtime/Linux/x86-64/Externals/Database\ Drivers/

rm dbsqlite.so

ln -s ../../../../../Externals/Database\ Drivers/dbsqlite.so

venerdì 30 marzo 2018

Livecode 9.0.0-RC1

E' uscita la nuova versione di livecode: 9.0.0.rc1
ed è piena di novità!
Vediamole insieme:
  • un nuovo spinner come widget
  • OAuth2 per l'integrazione con Facebook, Google, GitHub e simili
  • funzioni per creare dei comandi stile Linux
  • quando si crea l'eseguibile, adesso tutte le finestre sono chiuse e riaperte. Così facendo ricevono i messaggi di chiusura e apertura. Tenetelo in considerazione.Per evitarlo potete usare questo codice:
    on closeStack
      if the mode of stack "revStandaloneProgress" > 0 then
       exit closesStack
      end if
    end closeStack
  • Supporto da Windows 7 in su
  • Supporto da Linux Ubuntu 14.04 in su
  • Supporto da Mac 10.9 in su
  • Supporto da iOS 6.2 in su
  • Supporto da Android 4.1 in su
  • gli stack script possono contenere un behavior
  • se esportate come HTML5, adesso potete usare più finestre
  • file e folder adesso hanno anche il parametro kind per scegliere il tipo di risultato
  • supporto ad Android AAR
  • possibilità di unire il manifesto Adnroid con altri manifesti
  • le estensioni possono appoggiarsi a librerie esterne
  • c'è il pulsante per testare i programmi in versione HTML5
  • supporto ai jar files per Android
  • supporto alla variabile CLASSPATH del sistema operativo
  • supporto migliorato per l'internet se esportato in HTML5
  • Add support for accepting socket connections on a port in the ephemeral port range
  • possibilità di parlare col javascript nei programmi esportati in HTML5
  • nuovo comando difference per gli array
  • nuovo comando symmetric difference per gli array
  • messageDigest() supporta ora anche SHA-2 e SHA-3 
  • grafica migliorata appoggiandosi a Skia (https://skia.org)
  • CTRL + . non blocca le finestre modali
  • corretto create in
  • recordformats() ritorna la lista dei formati in cui può registrare il sistema operativo
  • conversione di pacchetti Java in linguaggio livecode builder (https://github.com/livecode/livecode/blob/develop/toolchain/lc-compile-ffi-java.1.md)
  • il terminale message box è stato riscritto
  • revVideoGrabber rimane disponibile solo per Windows
  • Supporto NFC per Android
  • in livecode builder si possono indicare i permessi richiesti ad Android usando i metadata.
  • revFontLoad e revFontUnload sono stati sostituiti da start using font.
  • si possono specificare le porte per i socket
  • ora è possibile indicare il numero massimo di caratteri di un campo di testo iOS
  • una app HTML5 può chiamare il javascript
  • migliorato libURLMultipartFormAddPart.
  • tabalign è la nuova proprietà per allineare il testo in HTMLtext e StyledText
  • se scrivete in livecode builder, adesso potete utilizzare più file, uno chiamato main.lcb e gli altri nella stessa cartella con estensione lcb.
  • ora ci sono le proprietà cDeveloperExtensionsFolders e cDeveloperExtensionsActiveFolders
  • i datagrid di tipo FORM ora hanno in più l'edit mode (proprietà dgEditMode) e lo swipe più altre funzioni per modificarne le icone, l'ordinamento e far scomparire e apparire alcune parti.
  • le estensioni possono avere il proprio property inspector
  • aggiunta l'opzione che una app su iOS si chiude se il cellulare va in sospensione
  • aggiunto il build number per le app iOS, così potete inviare più volte la stessa app
Questa è solo una concisa lista di tutto quello che porta di nuovo la nuova versione.

martedì 6 marzo 2018

VFR Course Calculator

Oggi vediamo una app per iOS fatta in 3 giorni: VFR Course Calculator.
Questa app permette di calcolare la rotta degli aerei. Calcola la vera rotta, direzione e rotta magnetica, la direzione della bussola, angolo di correzione del vento, vento trasversale e vento contrario, direzione e velocità del vento, velocità dell'aria reale, variazione e deviazione. Inoltre è possibile calcolare il tempo di volo (TL) per una distanza in funzione della velocità al suolo. In base a questi valori, calcola il carburante necessario e il suo peso. Non importa quale unità usi, l'app convertirà automaticamente i dati inseriti in sistemi metrici, statunitensi e britannici.


Questa app è utile ai piloti e agli apprendisti di aerei per pianificare il tuo volo VFR in modo rapido e semplice.

Che dire, è incredibile che con livecode si possa fare così tanto in così poco tempo! 

Potete scaricarla da qui: https://itunes.apple.com/us/app/vfr-course-calculator/id954985075?mt=8

giovedì 15 febbraio 2018

Libreria per GPIO raspberryPi

Abbiamo già visto precedentemente come lavorare con i GPIO della raspberry, ma ecco il codice di una libreria che rende tutto più facile:


on Pi_gpio_init nbr dir
   /* Pi_gpio_init RaspberryPi
   Syntax:
   Pi_gpio_init nbr, dir   # Command #
   Examples:
   Pi_gpio_init 2, "in"
   Pi_gpio_init 2, "out"
   Description:
   Initialize the gpio and set the direction of the operation
   nbr is one of the gpio pins: "2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,32"
   dir is "in" or "out"
   
   Source:
   Michael Doub
   Pi_gpio_init */
   /* Include
   RaspberryPi_var
   Pi_gpio_output
   */
   local cmd, direction_path
   if nbr is not among the items of good_pins then return "error: invalid pin nbr"
   if lower(dir) is not among the items of good_directions then return "error: invalid direction"
   if the platform is "Linux" then
      put ("/sys/class/gpio/gpio" & nbr & "/direction") into direction_path
      if there is not a file direction_path then
         put "echo" && nbr && "> /sys/class/gpio/export" into cmd
         get shell (cmd)
         if it is not empty then return "error:" & it
      end if
      if there is not a file direction_path then return "error:" && direction_path && "does not exist"
      open file direction_path for write
      write dir to file direction_path
      close file direction_path
   end if
   put dir into gpio[nbr][direction]
   return empty
end Pi_gpio_init

on Pi_gpio_input nbr
   /* Pi_gpio_input RaspberryPi
   Syntax:
   Pi_gpio_input nbr   # Command #
   Examples:
   Pi_gpio_input 2
   
   Description:
   Input from the gpio nbr
   nbr is one of the gpio pins: "2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,32"
   
   Source:
   Michael Doub
   Pi_gpio_input */
   /* Include
   RaspberryPi_var
   Pi_gpio_init
   */
   
   local value_path
   if nbr is not among the items of good_pins then return "error: invalid pin nbr"
   if the platform is "Linux" then
      put ("/sys/class/gpio/gpio" & nbr & "/value") into value_path
      if there is not a file value_path then return "error:" && value_path && "does not exist"
       open file value_path
       read from file value_path until EOF
       close file value_path
   end if
   return it
end Pi_gpio_input


on Pi_gpio_output nbr val
   /* Pi_gpio_output RaspberryPi
   Syntax:
   Pi_gpio_output nbr, val   # Command #
   Examples:
   Pi_gpio_output 2, 1
   Pi_gpio_output 2, 0
   Description:
   Output to the gpio nbr, with value of val
   nbr is one of the gpio pins: "2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,32"
   val is 1 or 0
   
   Source:
   Michael Doub
   Pi_gpio_output */
   /* Include
   RaspberryPi_var
   Pi_gpio_init
   */
   
   local value_path
   if nbr is not among the items of good_pins then return "error: invalid pin nbr"
   if val is not among the items good_values then return "error: invalid value"
   if the platform is "Linux" then
      put ("/sys/class/gpio/gpio" & nbr & "/value") into value_path
      if there is not a file value_path then return "error:" && value_path && "does not exist"
      open file value_path for write
      write val to file value_path
      close file value_path
   end if
   put val into gpio[nbr]["value"]
   return empty
end Pi_gpio_output

on Pi_to_Gert_Close
   /* Pi_to_Gert_Close RaspberryPi
   Syntax:
   Pi_to_Gert_Close    # Command #
   Examples:
   Pi_to_Gert_Close
   Description:
   This reoutine actually closes the serial port to the GertDuino.
   Source:
   Michael Doub
   Pi_to_Gert_Close */
   /* Include
   Pi_to_Gert_Variables
   */
   put false into _pi_okToRead
   wait for _pi_readrate with messages
   close file _pi_thePort
end Pi_to_Gert_Close


on Pi_to_Gert_Open pPortName, pReadrate, pBaud, pParity, pDatabits, pStopbits
   /* Pi_to_Gert_Open RaspberryPi
   Syntax:
   Pi_to_Gert_Open pPortName, [pReadrate], [pBaud], [pParity], [pDatabits], [pStopbits]    # Command #
   Examples:
   Pi_to_Gert_Open
   Description:
   Set the serial port configuration paramenters and opens the serial port to the GertDuino.
   
   Defaults:
   .    pPortName: "/dev/ttyAMA0"
   .    readrate: 10
   .    pBaud: 9600
   .    pParity: N
   .    pDatabits: 8
   .    pStopbits: 1
   
   Source:
   Michael Doub
   Pi_to_Gert_Open */
   /* Include
   Pi_to_Gert_Variables
   */
   
   if pPortName is empty then
      put "/dev/ttyAMA0" into _pi_theport
   else
      put pPortName into _pi_thePort
   end if
   if pReadrate is empty then put 10 into _pi_readrate
   if pBaud is empty then put 9600 into pBaud
   if pParity is empty then put "N" into pParity
   if pDatabits is empty then put 8 into pDatabits
   if pStopbits is empty then put 1 into pStopbits
   Put "BAUD=" & pBaud &&\
   "PARITY="& pParity &&\
   "DATA=" & pDatabits &&\
   "STOP=" & pDatabits into serial
   if the platform = "Linux" then
      set the serialControlString to serial
      open file _pi_thePort for binary update
   end if
end Pi_to_Gert_Open

on Pi_to_Gert_Start_Reading pCallbackname, pObj
   /* Pi_to_Gert_Start_Reading RaspberryPi
   Syntax:
   Pi_to_Gert_Start_Reading pCallbackname, pObj    # Command #
   Examples:
   Pi_to_Gert_Start_Reading "WeGotData", me
   Description:
   This routine starts the reading process between the Gertduino and
   the raspBerryPi. Since you must read the serial port until empty, this
   means that you must constantly have a read active on the port.   
      
      When data is actually recieved it is passed
      to pCallbackname of pObj thru the message path with a single parameter
      of the data base64encoded.
      
      Source:
      Michael Doub
      Pi_to_Gert_Start_Reading */
      /* Include
      Pi_to_Gert_Variables
      readPort_Gert
      */
      put true into _pi_okToRead
      put pCallbackname into _pi_callbackname
      put pObj into _pi_owner
      readPort_Gert
end Pi_to_Gert_Start_Reading

on Pi_to_Gert_Stop_Reading
   /* Pi_to_Gert_Stop_Reading RaspberryPi
   Syntax:
   Pi_to_Gert_Stop_Readingj    # Command #
   Examples:
   Pi_to_Gert_Stop_Reading
   Description:
   This routine stops the continious read process that is expecting data
   from the Gertdino serial port.
   Source:
   Michael Doub
   Pi_to_Gert_Stop_Reading */
   /* Include
   Pi_to_Gert_Variables
   */
   put false into _pi_okToRead
end Pi_to_Gert_Stop_Reading

on Pi_to_Gert_Write theData pDecode
   /* Pi_to_Gert_Write RaspberryPi
   Syntax:
   Pi_to_Gert_Write theData, [pDecode]    # Command #
   Examples:
   Pi_to_Gert_Write thedata
   Pi_to_Gert_Write thedata, true
   Description:
   Writes theData to the Gertduino serial port.   If pDecode is true then the data
   will be base64decoded
   Source:
   Michael Doub
   Pi_to_Gert_Write */
   /* Include
   Pi_to_Gert_Variables
   */
   if pDecode then
      write base64decode(theData) to file _pi_thePort
   else
      write theData to file _pi_thePort
   end if
end Pi_to_Gert_Write