#!/usr/bin/python
#---------------------------------------------------------
#                     textphone.py
#---------------------------------------------------------
#Original code written by Michael Wright, y2kLeader.com
#If you use all or part of this code in your project please 
#   include the line above in the header.
#To run: python3 textphone.py 

import sys
import os
import time
import io
import serial
import threading
exitflag=0
incall=0
calling=0
keybuffer=""

#----------------------------------------
def load_tones():
#----------------------------------------
   global ringtone
   global message_alert_tone
   global disconnect_tone
   global outgoing_ringtone
   ringtone="incomingcall.wav"
   message_alert_tone="messagealert.wav"
   disconnect_tone="hangup.wav"
   outgoing_ringtone="outgoingcall.wav"

#----------------------------------------
def open_USB_ports():
#----------------------------------------
   global ser
   global event_port
   errors=""
   try:
      ser=serial.Serial('/dev/ttyUSB3',115200,timeout=.5)
   except:
      errors=errors+"/dev/ttyUSB3 not available\n"
   try:
      event_port=serial.Serial('/dev/ttyUSB2',115200,timeout=.5)
   except:
      errors=errors+"/dev/ttyUSB2 not available\n"
   if(errors!=""):
      print(errors)
      os._exit(0)

#----------------------------------------
def initiate_audio_devices():
#----------------------------------------
   global modem
   global mic
   global speaker 

   modem_name="EC25"

   #Examples
   #mic_name="USB Audio Device"
   #speaker_name="Headphones"

   mic_name="XIBERIA"
   speaker_name="XIBERIA"

   #get the modem device number
   device=os.popen("arecord -l | grep '"+modem_name+"' | awk '{print $2+0}'")
   modem=device.read().replace("\r","").replace("\n","")
   
   #get the microphone device number
   device=os.popen("arecord -l | grep '"+mic_name+"' | awk '{print $2+0}'")
   mic=device.read().replace("\r","").replace("\n","")

   #get the speaker device number
   device=os.popen("aplay -l | grep '"+speaker_name+"' | awk '{print $2+0}'")
   speaker=device.read().replace("\r","").replace("\n","")


#----------------------------------------
def send(command,port,sleeptime):
#----------------------------------------
   command=command+"\r"
   port.write(command.encode())
   time.sleep(sleeptime)  
   data=ser.read(10000)
   data=data.decode("utf-8").strip()
   return data

#----------------------------------------
def play(soundfile):
#----------------------------------------
   os.system("aplay -q -D plughw:"+speaker+" "+soundfile+" > /dev/null")
#----------------------------------------
def listen():
#----------------------------------------
   global keybuffer
   global incall
   global calling
   threading.Timer(3.0, listen).start()
   eventbuf=event_port.read(1000) #check for unsolicited events
   eventbuffer=eventbuf.decode("utf-8").strip()
   eventbuffer=eventbuffer.replace('OK','')
   if(len(eventbuffer)>0):
      #---check to see if there was an incoming text 
      if (eventbuffer.find("+CMTI:") != -1):
         if(incall==0):
            play(message_alert_tone)

      #---check for an incoming voice call
      if (eventbuffer.find('+CRING: VOICE') != -1):
         #extract the number from the incoming call
         if(incall==0):
            play(ringtone)

      #---check for a disconnect
      if (eventbuffer.find('NO CARRIER') != -1):
         end_call()

#----------------------------------------
def kill_process(process_name):
#----------------------------------------
   response=os.popen("ps | grep "+process_name+" | awk {'print $1'}").read().strip()
   lines=response.split('\n')
   if(len(response)==0): #return if no processes found
      return
   for line in lines:
      os.system("kill -9 "+line)
      time.sleep(.5)
   

#----------------------------------------
def initiate_call_audio():
#----------------------------------------
   voice_out="arecord -q -c 1 -f S16_LE -D plughw:"+mic+" | aplay -q -D plughw:"+modem+" -c 1 -f S16_LE &"
   voice_in="arecord  -q -D plughw:"+modem+" -c 1 -f S16_LE | aplay -q -c 1 -f S16_LE -D plughw:"+speaker+" &"
   os.system(voice_out)
   time.sleep(1)
   os.system(voice_in)
   time.sleep(1)

#----------------------------------------
def make_call():
#----------------------------------------
   global incall
   kill_process("arecord") #Kill any call audio first
   num=input("Number to call: ")
   send('AT+QGPSCFG=\"outport\",\"none\"',ser,.1)
   send("AT+qcfg=\"USBCFG\",0x2c7c,0x0125,1,1,1,1,1,1,1",ser,.1)
   send("AT+qpcmv=1,2",ser,.1)
   response=send("ATD"+num+";",ser,.1)
   ringcounter=0
   while 1:
      tdata = ser.read()  
      play(outgoing_ringtone)    
      ringcounter=ringcounter+1
      if(ringcounter==8):  #call was not picked up after 8 rings
         break
      time.sleep(1)           
      data_left = ser.inWaiting()
      tdata += ser.read(data_left) 
      d=tdata.decode("utf-8")
      if (d.find('+') != -1):
         incall=1
         initiate_call_audio()
         break


#----------------------------------------
def answer_call():
#----------------------------------------
   send('AT+QGPSCFG=\"outport\",\"none\"',ser,.1)
   send("AT+qcfg=\"USBCFG\",0x2c7c,0x0125,1,1,1,1,1,1,1",ser,.1)
   send("AT+qpcmv=1,2",ser,.1)
   send("ATA",ser,.1)
   initiate_call_audio()

#----------------------------------------
def end_call():
#----------------------------------------
   global incall
   incall=0
   kill_process("arecord")   
   send("ATH",ser,.1)
   send("AT+qpcmv=0",ser,.1)
   play(disconnect_tone)

#----------------------------------------
def send_keytones_menu():
#----------------------------------------
   b="SEND KEYTONES@"
   b=b+"One&send_keytone('1');"
   b=b+"Two&send_keytone('2');"
   b=b+"Three&send_keytone('3');"
   b=b+"Four&send_keytone('4');"
   b=b+"Five&send_keytone('5');"
   b=b+"Six&send_keytone('6');"
   b=b+"Seven&send_keytone('7');"
   b=b+"Eight&send_keytone('8');"
   b=b+"Nine&send_keytone('9');"
   b=b+"Zero&send_keytone('0');"
   b=b+"*&send_keytone('*');"
   b=b+"#&send_keytone('#');"
   show_menu(b)
   
#----------------------------------------
def send_keytone(key):
#----------------------------------------
   send('AT+VTS="'+key+'"',ser,.1)
#----------------------------------------
def texting_menu():
#----------------------------------------
   b="TEXTING@"
   b=b+"Send A Text&send_text('');"
   b=b+"Read Unread Texts&show_texts('REC UNREAD');"
   b=b+"Read ALL Texts&show_texts('ALL');"
   b=b+"Delete All Texts&delete_message(-1);"
   show_menu(b)

#----------------------------------------
def send_text(num):
#----------------------------------------
   if(num==""):
      num=input('Number to text: ')   
   message=input('Message: ')   
   send("AT+CMGF=1",ser,.1)
   send('AT+CSCS="GSM"',ser,.1)
   send('AT+CMGS="'+num+'"',ser,.1)
   send(message+"\x1a",ser,.1)

#----------------------------------------
def show_texts(cmd):
#----------------------------------------
   #first read where the messages are stored and space remaining
   choice=""
   while(choice!="x"):
      os.system('clear')
      response=send("AT+CPMS?",ser,.1)
      response=response.replace('OK','').replace('\r\n','')
      line=response.split(",")
      used=line[1]
      capacity=line[2]
      available=int(capacity)-int(used)
      storage_area=line[3].replace('"','')
      if(storage_area=="ME"):
         sto="Modem Chip"
      if(storage_area=="SM"):
         sto="SIM Card"
      print("Standby...")
      stats=used+" saved, "+str(available)+" space(s) available\nUsing "+sto+" for storage"
      send("AT+CMGF=1",ser,.1)
      response=send('AT+CMGL="'+cmd+'"',ser,3)
      if (response.find("+CMGL:") == -1):
         if (cmd=="REC UNREAD"):
            print("No unread messages")
            time.sleep(3)
         if (cmd=="ALL"):
            print("No messages")
            time.sleep(3)
            return
      else:
         os.system('clear')
         if(cmd=="REC UNREAD"):
            print("UNREAD MESSAGES\n"+stats)
         if(cmd=="ALL"):
            print("ALL MESSAGES\n"+stats)
         print("")
         record=response.split("+CMGL:")
         for i in range(1,len(record)):
            line=record[i].split("\r\n") #separate the metadata from the text
            metadata=line[0].split(",")
            message=line[1]
            id=metadata[0].replace(' ','')
            number=metadata[2].replace('"','')
            dt=metadata[4].replace('"','')
            yr=dt[0:2]
            mo=dt[3:5]
            dy=dt[6:8]
            the_date=mo+"/"+dy
            tm=metadata[5].partition('-')[0]
            hr=tm[0:2]
            mn=tm[3:5]
            sc=tm[6:8]
            the_time=hr+":"+mn
            if(number=="2300"):
               message="<MULTIMEDIA MESSAGE>"
            print(id+" - "+the_date+" "+the_time+" "+number+" "+message)
            print("")
         choice=input("Message # to view, A=Delete All or X to exit: ")
         if (choice.isnumeric()):
            view_individual_text(choice)
            continue  #show list of texts again after returning from viewing indiv text
         if(choice=="a"):
            delete_message(-1)
            continue
         
#----------------------------------------
def view_individual_text(id):
#----------------------------------------
   response=send('AT+CMGR='+str(id),ser,.2)
   response=response.replace('OK','')
   os.system('clear')
   line=response.split("\r\n") #separate the metadata from the text
   metadata=line[0].split(",")
   number=metadata[1].replace('"','')
   print("Message from "+number)
   print("")
   print(line[1])
   print("")   
   choice=""
   while(choice!="x"):
      choice=input("R=Respond, D=Delete or X to exit: ")
      if(choice=="r"):
         send_text(number)
         continue
      if(choice=="d"):
         delete_message(id)
         return
#----------------------------------------
def delete_message(id):
#----------------------------------------
   if(id==-1): #delete all messages
      send('AT+CMGD=,4',ser,.1) 
      return
   send('AT+CMGD='+str(id),ser,.1) 

#----------------------------------------
def gps():
#----------------------------------------
   #This function simply prints your current GPS location 
   choice=""
   while(choice!="x"):
      os.system('clear')
      print (30 * '-')
      print ('{: ^30}'.format("GPS LOCATION"))
      print (30 * '-')
      send('AT+QGPSCFG="outport","usbnmea"',ser,.1)
      send("AT+QGPS=1",ser,.1)
      response=send("AT+QGPSLOC=2",ser,.1)
      response=response.replace('\r\n','').replace('OK','')
      if (response.find('+CME ERROR: 516') != -1):
         err=response.partition('+CME ERROR: ')[2]
         if(err=="516"):
            print("Position Not Fixed Yet")
            print("It seems to be getting a signal but it needs more time to fix the location.")
         if(err=="504" or err=="505"):
            print("No signal from antenna")
            print("Check the connections.")
            print("Often the pigtail antenna is not connected well or is bad.")
         time.sleep(5)
         return
      if (response.find('+QGPSLOC: ') != -1):  #signal received
         gps_sentence=response.partition('+QGPSLOC: ')[2].split(",")
         latitude=float(gps_sentence[1])
         if (latitude < 0):
            latitude_hemisphere="South"
         if (latitude > 0):
            latitude_hemisphere="North"
         longitude=float(gps_sentence[2])
         if(longitude < 0):
            longitude_hemisphere="West"
         if(longitude > 0):
            longitude_hemisphere="East"
         latitude=abs(latitude)
         longitude=abs(longitude)
         altitude=gps_sentence[4]
         course=gps_sentence[6]
         speed=gps_sentence[7]
         print("")     
         print(str(latitude)+" "+latitude_hemisphere+" Latitude")
         print(str(longitude)+" "+longitude_hemisphere+" Longitude")
         print ("Altitude="+altitude+" Meters")
         print ("Direction traveling="+course+" degrees")
         print("")
         print("Link for Google Maps:")
         print("")
         link="https://www.google.com/maps/place/"+gps_sentence[1]+","+gps_sentence[2]
         print(link)
         print("")
      choice = input('Type any key to refresh or x to exit : ') 
      if(choice!="x"):
         continue


#----------------------------------------
def contacts_menu():
#----------------------------------------
   b="CONTACTS MENU@"
   b=b+"Show All Contacts&show_all_contacts('ALL');"
   b=b+"Create Contact&create_contact();"
   b=b+"Search for Contact&search_for_contact();"
   b=b+"Delete All Contacts&delete_all_contacts();"
   show_menu(b)

#----------------------------------------
def delete_all_contacts():
#----------------------------------------
   #Cycle through all the contacts and delete them one-by-one
   #get the storage area and capacity
   response=send('AT+CPBS?',ser,1)
   response=response.replace('\r\n','').replace('OK','')
   response=response.partition('+CPBS: ')[2]
   line=response.split(",")
   contact_storage_area=line[0].replace('"','')
   capacity=line[2]
   response=send('AT+CPBR=1,'+str(capacity),ser,1)
   response=response.replace('OK','').replace('\r\n\r\n','')
   records=response.split("+CPBR: ")
   for i in range(1,len(records)):
      contact=records[i].split(",")
      cr=contact[0]
      contact_recordnum=(cr.partition('+CPBR ')[0])
      contact_name=contact[3].replace('"','').replace('\r\n','')
      print("Deleting "+contact_name)
      send("AT+CPBW="+contact_recordnum,ser,.1)
   time.sleep(4)

#----------------------------------------
def show_all_contacts(search):
#----------------------------------------
   choice=""
   while(choice!="x"):
      os.system('clear')
      #get the storage area and capacity
      response=send('AT+CPBS?',ser,1)
      response=response.replace('\r\n','').replace('OK','')
      response=response.partition('+CPBS: ')[2]
      line=response.split(",")
      contact_storage_area=line[0].replace('"','')
      used=line[1]
      capacity=line[2]
      available=int(capacity)-int(used)
      if(contact_storage_area=="ME"):
         sto="Modem Chip"
         altsto="SIM Card"
      if(contact_storage_area=="SM"):
         sto="SIM Card"
         altsto="Modem Chip"
      print("Contact storage area = "+sto)
      print(used+"/"+capacity+" used, "+str(available)+" spaces available.")
      print("")      
      if(search=="ALL"):
         response=send('AT+CPBR=1,'+str(capacity),ser,1)
         response=response.replace('OK','').replace('\r\n\r\n','')
         records=response.split("+CPBR: ")
      else:
         response=send('AT+CPBF="'+search+'"',ser,.5)
         response=response.replace('OK','').replace('\r\n\r\n','')
         records=response.split("+CPBF: ")
      for i in range(1,len(records)):
         contact=records[i].split(",")
         cr=contact[0]
         if(search=="ALL"):
            contact_recordnum=(cr.partition('+CPBR ')[0])
         else:
            contact_recordnum=(cr.partition('+CPBF ')[0])
         contact_number=contact[1].replace('"','')
         contact_type=contact[2]
         contact_name=contact[3].replace('"','').replace('\r\n','')
         print (contact_recordnum+" - "+contact_name+" "+contact_number)
      print("")
      choice=input("Choose #, T = transfer to "+altsto+" or X=Exit: ")
      if (choice.isnumeric()):
         view_contact(choice)
         continue  #show list of contacts again after returning from viewing indiv contact
      if (choice=="t"):
         transfer_contacts(altsto)

  
#----------------------------------------
def view_contact(num):
#----------------------------------------   
   choice=""
   while(choice!="x"):
      os.system('clear')
      response=send('AT+CPBR='+str(num),ser,.1)
      response=response.replace('OK','').replace('\r\n\r\n','')
      response=response.partition('+CPBR: ')[2]
      line=response.split(",")
      phone_number=line[1].replace('"','')
      contact_type=line[2]
      contact_name=line[3].replace('"','')
      print(contact_name+" "+phone_number)
      print("")
      print("1 - Change Contact Info")
      print("2 - Delete "+contact_name+" from contacts.")
      print("")
      choice=input("Choose function or X=exit : ") 
      if(choice=="1"):
         change_contact_info(num)
         continue
      if(choice=="2"):
         send("AT+CPBW="+num,ser,.1)
         return
   
#----------------------------------------
def change_contact_info(num):
#----------------------------------------
   response=send('AT+CPBR='+str(num),ser,.1)
   response=response.replace('OK','').replace('\r\n\r\n','')
   response=response.partition('+CPBR: ')[2]
   line=response.split(",")
   phone_number=line[1].replace('"','')
   contact_type=line[2]
   contact_name=line[3].replace('"','')
   print(contact_name+" "+phone_number)
   print("")
   new_name=input("New name for "+contact_name+"? ")   
   if(new_name!=""):
      contact_name=new_name
   new_number=input("New phone number for "+contact_name+"? ")   
   if(new_number!=""):
      phone_number=new_number
   s='AT+CPBW='+num+',"'+phone_number+'",'+contact_type+',"'+contact_name+'"'
   send(s,ser,.1)

#----------------------------------------
def create_contact():
#----------------------------------------
   os.system('clear')
   print("Create a Contact")
   print("")
   print("A blank name or number will exit the function.")
   print("")
   contact_name=input("Name of contact: ")
   if(contact_name==""):
      return
   phone_number=input("Phone number for "+contact_name+": ")
   if(phone_number==""):
      return
   s='AT+CPBW=,"'+phone_number+'",129,"'+contact_name+'"'
   send(s,ser,.1)
   response=response.replace('OK','').replace('\r\n\r\n','')
   response=response.partition('+CPBR: ')[2]
      
#----------------------------------------
def search_for_contact():
#----------------------------------------
   os.system('clear')
   print("Search for a Contact")
   print("")
   print("A blank will exit the function.")
   print("")
   search=input("Type first letter(s) of contact: ")
   if(search==""):
      return
   response=send('AT+CPBF="'+search+'"',ser,1)
   if (response.find("+CME ERROR:") != -1):
      print("No records found.")
      time.sleep(3)
      return
   if (response.find("+CPBF: ") != -1):
     #print(search)
     #os._exit(0)
     show_all_contacts(search)
   
#----------------------------------------
def transfer_contacts(altsto):
#----------------------------------------
   print("transferring storage")
   print("sto="+sto)
   print("altsto="+altsto)

   if(altsto=="SIM Card"):
      destination="SM"
   if(altsto=="Modem Chip"):
      destination="ME"
   #Cycle through each contact and save it to the alternate storage area
   #If a duplicate name and number is found in the new area, then it will be skipped
   #If either then name or the number is different in the new area, it will be added as a separate contact

   os._exit(0)

#----------------------------------------
def settings_menu():
#----------------------------------------
   b="SETTINGS@"
   b=b+"Network Settings&network_settings();"
   b=b+"Storage Settings&storage_settings_menu();"
   b=b+"Sound Settings&sound_settings();"
   show_menu(b)

#----------------------------------------
def network_settings():
#----------------------------------------
   os.system('clear')
   
   choice=""
   while choice!="x": 
      print("")
      os.system('clear')
      print (30 * '-')
      print ('{: ^30}'.format("NETWORK SETTINGS"))
      print (30 * '-')
      print("")

      #Get Phone number
      response=send("AT+CNUM",ser,.1)
      response=response.replace('OK','').replace('\r\n\r\n','')
      line=response.split(",")
      phone_number=line[1].replace('"','')
      print ("Your Number: "+phone_number)

      #Get signal strength
      response=send("AT+CSQ",ser,.1) 
      response=response.replace('OK','').replace('\r\n\r\n','')
      line=response.partition('+CSQ: ')[2].split(",")
      signal=int(line[0])
      signal=round((signal*100)/31)
      print("Signal Strength: "+str(signal)+"%")

      #Get Network Name
      response=send("AT+COPS?",ser,.1) 
      line=response.split(",")
      network=line[2].replace('"','')
      print("Network Provider: "+network)

      #Get time and date through network   
      response=send("AT+QLTS=2",ser,.1) 
      response=response.replace('OK','').replace('\r\n\r\n','')
      line=response.partition('+QLTS: ')[2].split(",")
      the_date=line[0].replace('"','')
      the_time=line[1].partition('-')[0]
      print("Local Date/Time: "+the_date+" "+the_time)

      #Get the IMEI of the phone
      response=send("AT+GSN",ser,.1)
      imei=response.replace('OK','').replace('\r\n\r\n','')
      print("IMEI: "+imei)

      #Get the IMSI of the SIM card (serial number)
      response=send("AT+CIMI",ser,.1)
      imsi=response.replace('OK','').replace('\r\n\r\n','')
      print("SIM Card Serial #: "+imsi)

      #Get the Firmware installed on the modem
      response=send("AT+GMR",ser,.1)
      firmware=response.replace('OK','').replace('\r\n\r\n','')
      print("Modem Firmware: "+firmware)

      print("")
      print("x - Exit")
      print("")
      choice = input('Enter X to return to previous menu: ')
   
#----------------------------------------
def storage_settings_menu():
#----------------------------------------
   os.system('clear')
   choice=""
   while choice!="x": 
      print("")
      os.system('clear')
      print (30 * '-')
      print ('{: ^30}'.format("STORAGE SETTINGS"))
      print (30 * '-')
      print("")

      #Get the text message storage area
      response=send("AT+CPMS?",ser,.1)
      response=response.replace('OK','').replace('\r\n','')
      line=response.split(",")
      used=line[1]
      capacity=line[2]
      available=int(capacity)-int(used)
      storage_area=line[3].replace('"','')
      if(storage_area=="ME"):
         sto="Modem Chip"
         altsto="SIM Card"
      if(storage_area=="SM"):
         sto="SIM Card"
         altsto="Modem Chip"
      #print("1 - Messages = "+sto+ " ("+used+"/"+capacity+" used)&change_storage_area('messages','"+altsto+"');"
      print("1 - Messages = "+sto+ " "+used+"/"+capacity+" used")
      #get the phonebook storage area and capacity
      response=send('AT+CPBS?',ser,1)
      response=response.replace('\r\n','').replace('OK','')
      response=response.partition('+CPBS: ')[2]
      line=response.split(",")
      contact_storage_area=line[0].replace('"','')
      used=line[1]
      capacity=line[2]
      available=int(capacity)-int(used)
      if(contact_storage_area=="ME"):
         sto="Modem Chip"
         altsto="SIM Card"
      if(contact_storage_area=="SM"):
         sto="SIM Card"
         altsto="Modem Chip"
      #print("2 - Contacts = "+sto+ " ("+used+"/"+capacity+" used)&change_storage_area('contacts','"+altsto+"');"
      print("2 - Contacts = "+sto+ " "+used+"/"+capacity+" used")
      print("")
      print("x - Exit")
      print("")
      choice = input('Enter X to return to previous menu: ')
      if(choice=="1"):
         change_storage_area('messages',altsto)         
      if(choice=="2"):
         change_storage_area('contacts',altsto)         
  
#----------------------------------------
def change_storage_area(area,altsto):
#----------------------------------------
   if(altsto=="SIM Card"):
      newsto="SM"
   if(altsto=="Modem Chip"):
      newsto="ME"
   if(area=="messages"):
      choice=input("Change message storage area to "+altsto+"? y/n ")
      if (choice=="" or choice=="n"):      
         return
      send('AT+CPMS="'+newsto+'","'+newsto+'","'+newsto+'"',ser,.1)  
   if(area=="contacts"):
      choice=input("Change message storage area to "+altsto+"? y/n ")
      if (choice=="" or choice=="n"):      
         return
      send('AT+CPBS="'+newsto+'"',ser,.1)  
   
#----------------------------------------
def sound_settings():
#----------------------------------------
   os.system('clear')
   choice=""
   while choice!="x": 
      print("")
      os.system('clear')
      print (30 * '-')
      print ('{: ^30}'.format("SOUND SETTINGS"))
      print (30 * '-')
      print("")
      print("Change the modem_name, mic_name and speaker_name in the ")
      print("initiate_audio_devices() function to match our choices.")
      print("")
      print ("--- Recording Devices ---")
      recording_devices=os.popen("arecord -l | grep card").read()
      recording_devices=recording_devices.replace("\r\n","").strip()
      data=recording_devices.split("\n")
      for line in data:
         d1=line.split(":")
         device_number=d1[0].partition(' ')[2]
         device_string=d1[1]
         start = device_string.find("[") + len("[")
         end = device_string.find("]")
         device_name = device_string[start:end]
         if (device_name!="EC25-AF"):
            print(device_number+" - "+device_name)

      # Get the playing devices
      print("")
      print ("--- Playing Devices ---")
      playing_devices=os.popen("aplay -l | grep card").read()
      playing_devices=playing_devices.replace("\r\n","").strip()
      data=playing_devices.split("\n")
      for line in data:
         d1=line.split(":")
         device_number=d1[0].partition(' ')[2]
         device_string=d1[1]
         start = device_string.find("[") + len("[")
         end = device_string.find("]")
         device_name = device_string[start:end]
         if (device_name!="EC25-AF"):
            print(device_number+" - "+device_name)


      # Get the Quectel modem device
      print("")
      print ("--- Quectel Modem ---")
      playing_devices=os.popen("aplay -l | grep card").read()
      playing_devices=playing_devices.replace("\r\n","").strip()
      data=playing_devices.split("\n")
      for line in data:
         d1=line.split(":")
         device_number=d1[0].partition(' ')[2]
         device_string=d1[1]
         start = device_string.find("[") + len("[")
         end = device_string.find("]")
         device_name = device_string[start:end]
         if (device_name=="EC25-AF"):
            print(device_number+" - "+device_name)

      print("")
      print("x - Exit")
      print("")
      choice = input('Enter X to return to previous menu: ')
  
#----------------------------------------
def show_menu(menustr):
#----------------------------------------
   menutitle=menustr.partition('@')[0]  #extract title
   print(menustr.partition("@")[2])
   choice=""
   while choice!="x": 
      print("")
      os.system('clear')
      print (30 * '-')
      print ('{: ^30}'.format(menutitle))
      print (30 * '-')
      print("")
      tmpstr=menustr.partition("@")[2].split(";")
      functions=""
      for i,item in enumerate(tmpstr,1):
         if(i==len(tmpstr)):
            break
         str=item.split("&")
         print(i,"-",str[0])
      print("")
      print("x - Exit")
      print("")
      choice = input('Enter your choice or x to exit: ')
      if(choice=="x" and menutitle=="MAIN MENU"): 
         os.system('clear')
         os._exit(0)
      if (choice.isnumeric()):
         #Iterate through again to compare the choice
         for i,item in enumerate(tmpstr,1):
            if(i==len(tmpstr)):
               break
            str=item.split("&")
            if(int(choice)==i):
               #try:
               eval(str[1])
               #except:
               #print("No "+str[1]+" function exists, or there is a problem with the code.")
               #os._exit(0)
   return choice  

#----------------------------------------
def main_menu():
#----------------------------------------
   b="MAIN MENU@"
   b=b+"Make a Call&make_call();"
   b=b+"Answer Call&answer_call();"
   b=b+"End Call&end_call();"
   b=b+"Send Key Tones&send_keytones_menu();"
   b=b+"<Texting>&texting_menu();"
   b=b+"Get GPS Location&gps();"
   b=b+"<Contacts>&contacts_menu();"
   b=b+"<Settings>&settings_menu();"
   show_menu(b)

#**************************************
# Start code here
#**************************************
kill_process("arecord")
open_USB_ports()
send("ATE0",ser,.1) #set no echo
send("AT+CRC=1",ser,.1) #set extented call reporting format
send("AT+CLIP=1",ser,.1) # enable caller ID
send("AT+COLP=1",ser,.1) # wait the call is answered to give an unsolicited response line: +COLP: "3174260810",129,,, instead of OK
send("AT+QTONEDET=1",ser,.1) #enable keycodes to be sent

initiate_audio_devices()
load_tones()
#Uncomment the next line if you are using the touch screen
#os.system("matchbox-keyboard &")
listen()
main_menu()      

#-------- end of script --------------

