1#!/usr/bin/env python 2 3# This script speaks the incoming caller ID for the SIP client Twinkle 4# The following programs are needed: espeak, ffmpeg and sox, mpc is optional 5# aptitude install ffmpeg espeak sox mpc 6# Further information about Twinkle scripts can be found at 7# http://mfnboer.home.xs4all.nl/twinkle/manual.html#profile_scripts 8 9import os, subprocess, sys, re 10import config 11 12def get_caller_id(from_hdr): 13 caller_id = from_hdr[from_hdr.find(":")+1:from_hdr.find("@")] 14 # remove all non digits from caller id 15 caller_id = re.sub("\D", "", caller_id) 16 # remove two digit country identification if present 17 if not caller_id.startswith("0"): 18 return caller_id[2:] 19 return caller_id 20 21def caller_from_addressbook(caller_id): 22 try: 23 callers = subprocess.check_output([config.khard_exe, "phone", "--parsable", caller_id]).strip() 24 except subprocess.CalledProcessError: 25 return caller_id 26 if len(callers.split("\n")) == 1: 27 return callers.split("\t")[1] 28 else: 29 # the contact contains multiple phone numbers and we have to obtain the right phone label 30 regexp = re.compile(caller_id, re.IGNORECASE) 31 for entry in callers.split("\n"): 32 if regexp.search(re.sub("\D", "", entry.split("\t")[0])) != None: 33 return "%s (%s)" % (entry.split("\t")[1], entry.split("\t")[2]) 34 return callers.split("\n")[0].split("\t")[1] 35 36def create_ringtone(caller_id): 37 if os.path.exists(config.new_ringtone) == True: 38 os.remove(config.new_ringtone) 39 if config.language == "de": 40 subprocess.call(["espeak", "-v", "de", "-s", "300", "-w", config.tmp_mono_file, caller_id]) 41 else: 42 subprocess.call(["espeak", "-v", "en-us", "-s", "300", "-w", config.tmp_mono_file, caller_id]) 43 subprocess.call(["ffmpeg", "-i", config.tmp_mono_file, "-ar", "48000", "-ac", "2", "-y", config.tmp_file_stereo], 44 stdout=open('/dev/null', 'w'), stderr=open('/dev/null', 'w')) 45 subprocess.call(["sox", config.constant_ringtone_segment, config.tmp_file_stereo, config.new_ringtone]) 46 47 48# main part of the script 49if os.path.exists(config.constant_ringtone_segment) == False: 50 print("The constant part of the ringtone file is missing. Create the sounds folder in your twinkle config and put a wav file in it") 51 sys.exit(1) 52 53# pause the music playback 54# I use a MPD server for playing music so I pause it with the client MPC 55# You can disable that in the config.py file 56if config.stop_music: 57 mpc_output = subprocess.check_output(["mpc", "-h", config.mpd_host, "-p", str(config.mpd_port), "status"]) 58 if "playing" in mpc_output: 59 subprocess.call(["mpc", "-h", config.mpd_host, "-p", str(config.mpd_port), "pause"]) 60 music_tmp_file = open(config.mpd_lockfile, "w") 61 music_tmp_file.close() 62 63if "SIP_FROM" in os.environ: 64 from_hdr = os.environ["SIP_FROM"] 65 # parse the caller ID of the string 66 caller_id = get_caller_id(from_hdr) 67 # look into the addressbook 68 if caller_id != "": 69 caller_id = caller_from_addressbook(caller_id) 70 else: 71 caller_id = "anonymous" 72 # create the ringtone 73 if config.language == "de": 74 create_ringtone("Anruf von " + caller_id) 75 else: 76 create_ringtone("Call from " + caller_id) 77 # save the caller id for later use 78 with open(config.caller_id_filename, "w") as caller_id_file: 79 caller_id_file.write(caller_id) 80 # if the file creation was successful and the file exists, tell twinkle to use it as the ringtone 81 # else do nothing and play the standard ringtone 82 if os.path.exists(config.new_ringtone) == True: 83 print("ringtone=" + config.new_ringtone) 84sys.exit() 85