# t32_run_script.py
#
# Example Python script that shows how to connect to
# an instance of TRACE32 and run a script.
# The script is built as a simple GUI using Tkinter, allowing
# the user to initiate the connection and browse for the
# script to be executed.
#
# Requires:
#   - Python 3
#   - Tkinter


from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter import messagebox
import sys
import platform
import os
import pathlib

import ctypes        # module for C data types
import enum

# determine host OS
# This will load the correct DLL/shared object and set the
# system path, assuming a default TRACE32 installation:
# Windows   - C:/T32
# Mac/Linux - /opt/t32
#
# DLL, Python and OS must all be either 64bit or 32bit - you
# can't mix versions!!
if platform.system() == "Linux":
    SYSDIR='/opt/t32'
    if platform.machine().endswith('64'):
        #Linux64
        APIFILE='t32api64.so'
    else:
        #Linux32
        APIFILE='t32api.so'
elif platform.system() == "darwin":
    # Mac OX
    SYSDIR='/opt/t32'
    if platform.machine().endswith('64'):
        #Mac OS64
        APIFILE='t32api64.so'
    else:
        #Mac OS32
        APIFILE='t32api.so'
elif platform.system() == "Windows":
    SYSDIR='C:/T32'
    if platform.machine().endswith('64'):
        #win64
        APIFILE='t32api64.dll'
    else:
        #win32
        APIFILE='t32api.dll'
else:
    print("Unknown OS")
    quit

# If your TRACE32 installation is not installed in the default
# location, change the value of SYS here and uncomment the next
# line.
# SYS='/my/trace32/location'

APIDIR='demo/api/python'
LIBFILE=os.path.join(os.sep,SYSDIR,APIDIR,APIFILE)
t32api=ctypes.cdll.LoadLibrary(LIBFILE)
T32_DEV = 1

class simple_tk_gui:
    def __init__(self, parent):
        self.connstate = FALSE
        self.parent = parent
        self.parent.minsize(width=400, height = 200)
        parent.title("TRACE32 Script Launcher")

        self.topframe = Frame(root)
        self.topframe.pack(fill=BOTH, padx=5, pady=5)

        self.midframe = Frame(root)
        self.midframe.pack(fill=BOTH, padx = 5, pady = 1)

        self.bottomframe = Frame(root)
        self.bottomframe.pack(side=TOP, padx = 5, pady = 5 )

        self.quitbutton = Button(self.topframe, text="Quit", command=self.quit)
        self.quitbutton.pack(side=RIGHT, padx=5)

        self.attachbutton = Button(self.topframe, text="Connect to TRACE32", command=self.connect)
        self.attachbutton.pack(side=RIGHT, padx=5)

        self.statetext = Label(self.topframe, text="Disconnected", bg="RED")
        self.statetext.pack(side=LEFT, padx=15)

        self.label1 = Label(self.midframe, text="Select script to execute:")
        self.label1.pack(side=LEFT)

        self.scriptbutton = Button(self.bottomframe, text="Execute", command=self.runscript)
        self.scriptbutton.pack(side=RIGHT, padx=5, pady = 5)

        self.browsebutton=Button(self.bottomframe, text="Browse", command=self.browse)
        self.browsebutton.pack(side=RIGHT, padx = 5 , pady = 5)

        self.scriptname = Entry(self.bottomframe, width=40)
        self.scriptname.pack(side=LEFT, padx = 5, pady = 5)

    def quit(self):
        if self.connstate==TRUE:
            t32api.T32_Exit()
        self.parent.quit()

    def runscript(self):
        if self.connstate==FALSE:
            messagebox.showerror( "Error", "No connection established to TRACE32!")
            return
        cmd = 'DO '+self.scriptname.get()
        print (cmd)
        t32api.T32_Cmd(cmd.encode())

    # connect
    # manage and establish a connection to a running instance
    # of TRACE32. Config.t32 ()
    def connect(self):
        if self.connstate==TRUE:
            self.statetext.config(text="Disconnected", bg="RED")
            self.attachbutton.config(text="Connect to TRACE32")
            t32api.T32_Exit()
            self.connstate=FALSE
            pass
        else:
            self.statetext.config(text="Connecting, please wait.", bg="YELLOW")
            self.parent.update()

            # Configure communication channel to an instance
            # of TRACE32 running on the localhost, listening on UDP
            # port 20000
            t32api.T32_Config(b"NODE=",b"localhost")
            t32api.T32_Config(b"PORT=", b"20000")
            t32api.T32_Config(b"PACKLEN=",b"1024")

            # Establish a connection to TRACE32
            rc = t32api.T32_Init()
            if rc != 0:
                self.statetext.config(text="T32_Init Error. Is TRACE32 running?", bg="RED")
                self.connstate=FALSE
                return

            # Sometimes the first attempt to Attach fails but a second will
            # usually succeed. This often happens if the API has been left hanging
            # when the previous user didn't call T32_Exit() before quitting.
            for x in range(0,3):
                rc = t32api.T32_Attach(T32_DEV)
                if rc == 0:
                    break
            if rc != 0:
                self.statetext.config(text="T32_Attach Error", bg="RED")
                self.connstate=FALSE
                t32api.T32_Exit()
                return

            # Ping TRACE32 to check the connection really is up and running
            rc = t32api.T32_Ping()
            if rc != 0:
                self.statetext.config(text="T32_Ping Error", bg="RED")
                self.connstate=FALSE
                t32api.T32_Exit()
                return

            self.statetext.config(text="Connected", bg="GREEN")
            self.attachbutton.config(text="Disconnect from TRACE32")
            self.connstate=TRUE



    def browse(self):
        opts={}
        opts['filetypes'] = [('TRACE32 scripts', '.cmm','.CMM')]
        file_path=askopenfilename(**opts)
        if file_path=='': return
        self.scriptname.delete(0,END)
        self.scriptname.insert(0,file_path)
        print(file_path)

root = Tk()
my_gui = simple_tk_gui(root)
root.mainloop()
