| 1 | # -*- coding: utf-8 -*-
|
|---|
| 2 | '''
|
|---|
| 3 | $Author: sreichholf $
|
|---|
| 4 | '''
|
|---|
| 5 | from enigma import eTimer, eSize, ePoint, getDesktop, eDVBVolumecontrol, eBackgroundFileEraser
|
|---|
| 6 |
|
|---|
| 7 | from Screens.Screen import Screen
|
|---|
| 8 | from Screens.MessageBox import MessageBox
|
|---|
| 9 | from Screens.NumericalTextInputHelpDialog import NumericalTextInputHelpDialog
|
|---|
| 10 | from Screens.InputBox import InputBox
|
|---|
| 11 | from Screens import Standby
|
|---|
| 12 | from Screens.HelpMenu import HelpableScreen
|
|---|
| 13 |
|
|---|
| 14 | from Components.config import config, ConfigSubsection, ConfigSelection, ConfigEnableDisable, getConfigListEntry, ConfigText, ConfigInteger
|
|---|
| 15 | from Components.ActionMap import ActionMap
|
|---|
| 16 | from Components.Label import Label
|
|---|
| 17 | from Components.Button import Button
|
|---|
| 18 | from Components.Pixmap import Pixmap
|
|---|
| 19 | from Components.Sources.List import List
|
|---|
| 20 | from Components.ConfigList import ConfigListScreen
|
|---|
| 21 | from Components.Harddisk import harddiskmanager
|
|---|
| 22 |
|
|---|
| 23 | from Plugins.Plugin import PluginDescriptor
|
|---|
| 24 | from Tools import Notifications
|
|---|
| 25 | from Tools.NumericalTextInput import NumericalTextInput
|
|---|
| 26 | from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE, SCOPE_CONFIG, SCOPE_MEDIA
|
|---|
| 27 | from Tools.LoadPixmap import LoadPixmap
|
|---|
| 28 | from GlobalActions import globalActionMap # for muting
|
|---|
| 29 |
|
|---|
| 30 | from twisted.internet import reactor
|
|---|
| 31 | from twisted.internet.protocol import ReconnectingClientFactory
|
|---|
| 32 | from twisted.protocols.basic import LineReceiver
|
|---|
| 33 |
|
|---|
| 34 | import re, os
|
|---|
| 35 |
|
|---|
| 36 | from datetime import datetime
|
|---|
| 37 |
|
|---|
| 38 | from . import debug, _
|
|---|
| 39 | from reverselookup import ReverseLookupAndNotify
|
|---|
| 40 |
|
|---|
| 41 | my_global_session = None
|
|---|
| 42 |
|
|---|
| 43 | COUNTRY_CODES = [
|
|---|
| 44 | ("0049", _("Germany")),
|
|---|
| 45 | ("0031", _("The Netherlands")),
|
|---|
| 46 | ("0033", _("France")),
|
|---|
| 47 | ("0039", _("Italy")),
|
|---|
| 48 | ("0041", _("Switzerland")),
|
|---|
| 49 | ("0043", _("Austria"))
|
|---|
| 50 | ]
|
|---|
| 51 |
|
|---|
| 52 | DESKTOP_WIDTH = getDesktop(0).size().width()
|
|---|
| 53 | DESKTOP_HEIGHT = getDesktop(0).size().height()
|
|---|
| 54 |
|
|---|
| 55 | #
|
|---|
| 56 | # this is pure magic.
|
|---|
| 57 | # It returns the first value, if HD (1280x720),
|
|---|
| 58 | # the second if SD (720x576),
|
|---|
| 59 | # else something scaled accordingly
|
|---|
| 60 | # if one of the parameters is -1, scale proportionally
|
|---|
| 61 | #
|
|---|
| 62 | def scaleH(y2, y1):
|
|---|
| 63 | if y2 == -1:
|
|---|
| 64 | y2 = y1 * 1280 / 720
|
|---|
| 65 | elif y1 == -1:
|
|---|
| 66 | y1 = y2 * 720 / 1280
|
|---|
| 67 | return scale(y2, y1, 1280, 720, DESKTOP_WIDTH)
|
|---|
| 68 | def scaleV(y2, y1):
|
|---|
| 69 | if y2 == -1:
|
|---|
| 70 | y2 = y1 * 720 / 576
|
|---|
| 71 | elif y1 == -1:
|
|---|
| 72 | y1 = y2 * 576 / 720
|
|---|
| 73 | return scale(y2, y1, 720, 576, DESKTOP_HEIGHT)
|
|---|
| 74 | def scale(y2, y1, x2, x1, x):
|
|---|
| 75 | return (y2 - y1) * (x - x1) / (x2 - x1) + y1
|
|---|
| 76 |
|
|---|
| 77 | def getMountedDevices():
|
|---|
| 78 | def handleMountpoint(loc):
|
|---|
| 79 | # debug("[NcidClient] handleMountpoint: %s" %repr(loc))
|
|---|
| 80 | mp = loc[0]
|
|---|
| 81 | while mp[-1] == '/':
|
|---|
| 82 | mp = mp[:-1]
|
|---|
| 83 |
|
|---|
| 84 | desc = loc[1]
|
|---|
| 85 | return (mp, desc + " (" + mp + ")")
|
|---|
| 86 |
|
|---|
| 87 | mountedDevs = [(resolveFilename(SCOPE_CONFIG), _("Flash")),
|
|---|
| 88 | (resolveFilename(SCOPE_MEDIA, "cf"), _("Compact Flash")),
|
|---|
| 89 | (resolveFilename(SCOPE_MEDIA, "usb"), _("USB Device"))]
|
|---|
| 90 | mountedDevs += map(lambda p: (p.mountpoint, (_(p.description) if p.description else "")), harddiskmanager.getMountedPartitions(True))
|
|---|
| 91 | mediaDir = resolveFilename(SCOPE_MEDIA)
|
|---|
| 92 | for p in os.listdir(mediaDir):
|
|---|
| 93 | if os.path.join(mediaDir, p) not in [path[0] for path in mountedDevs]:
|
|---|
| 94 | mountedDevs.append((os.path.join(mediaDir, p), _("Media directory")))
|
|---|
| 95 | debug("[NcidClient] getMountedDevices1: %s" % repr(mountedDevs))
|
|---|
| 96 | mountedDevs = filter(lambda path: os.path.isdir(path[0]) and os.access(path[0], os.W_OK | os.X_OK), mountedDevs)
|
|---|
| 97 | # put this after the write/executable check, that is far too slow...
|
|---|
| 98 | netDir = resolveFilename(SCOPE_MEDIA, "net")
|
|---|
| 99 | if os.path.isdir(netDir):
|
|---|
| 100 | mountedDevs += map(lambda p: (os.path.join(netDir, p), _("Network mount")), os.listdir(netDir))
|
|---|
| 101 | mountedDevs = map(handleMountpoint, mountedDevs)
|
|---|
| 102 | return mountedDevs
|
|---|
| 103 |
|
|---|
| 104 | config.plugins.NcidClient = ConfigSubsection()
|
|---|
| 105 | config.plugins.NcidClient.debug = ConfigEnableDisable(default=False)
|
|---|
| 106 | config.plugins.NcidClient.muteOnCall = ConfigEnableDisable(default=False)
|
|---|
| 107 | config.plugins.NcidClient.hostname = ConfigText(default="easy.box", fixed_size=False)
|
|---|
| 108 | config.plugins.NcidClient.port = ConfigInteger(limits=[1, 65535], default=3333)
|
|---|
| 109 | config.plugins.NcidClient.afterStandby = ConfigSelection(choices=[("none", _("show nothing")), ("inList", _("show as list")), ("each", _("show each call"))])
|
|---|
| 110 | config.plugins.NcidClient.timeout = ConfigInteger(default=15, limits=(0, 60))
|
|---|
| 111 | config.plugins.NcidClient.lookup = ConfigEnableDisable(default=False)
|
|---|
| 112 | config.plugins.NcidClient.internal = ConfigEnableDisable(default=False)
|
|---|
| 113 |
|
|---|
| 114 | config.plugins.NcidClient.addcallers = ConfigEnableDisable(default=False)
|
|---|
| 115 | config.plugins.NcidClient.enable = ConfigEnableDisable(default=True)
|
|---|
| 116 | config.plugins.NcidClient.extension = ConfigText(default='1', fixed_size=False)
|
|---|
| 117 | config.plugins.NcidClient.extension.setUseableChars('0123456789')
|
|---|
| 118 | config.plugins.NcidClient.showType = ConfigEnableDisable(default=True)
|
|---|
| 119 | config.plugins.NcidClient.prefix = ConfigText(default="", fixed_size=False)
|
|---|
| 120 | config.plugins.NcidClient.prefix.setUseableChars('0123456789')
|
|---|
| 121 | config.plugins.NcidClient.connectionVerbose = ConfigEnableDisable(default=True)
|
|---|
| 122 | config.plugins.NcidClient.phonebook = ConfigEnableDisable(default=False)
|
|---|
| 123 | config.plugins.NcidClient.phonebookLocation = ConfigSelection(choices=getMountedDevices())
|
|---|
| 124 | config.plugins.NcidClient.country = ConfigSelection(choices=COUNTRY_CODES)
|
|---|
| 125 | config.plugins.NcidClient.name = ConfigText(default="", fixed_size=False)
|
|---|
| 126 | config.plugins.NcidClient.number = ConfigText(default="", fixed_size=False)
|
|---|
| 127 | config.plugins.NcidClient.number.setUseableChars('0123456789')
|
|---|
| 128 |
|
|---|
| 129 | phonebook = None
|
|---|
| 130 | ncidsrv = None
|
|---|
| 131 |
|
|---|
| 132 | avon = {}
|
|---|
| 133 |
|
|---|
| 134 | def initAvon():
|
|---|
| 135 | avonFileName = resolveFilename(SCOPE_PLUGINS, "Extensions/NcidClient/avon.dat")
|
|---|
| 136 | if os.path.exists(avonFileName):
|
|---|
| 137 | for line in open(avonFileName):
|
|---|
| 138 | line = line.decode("iso-8859-1").encode('utf-8')
|
|---|
| 139 | if line[0] == '#':
|
|---|
| 140 | continue
|
|---|
| 141 | parts = line.split(':')
|
|---|
| 142 | if len(parts) == 2:
|
|---|
| 143 | avon[parts[0].replace('-', '').replace('*', '').replace('/', '')] = parts[1]
|
|---|
| 144 |
|
|---|
| 145 | def resolveNumberWithAvon(number, countrycode):
|
|---|
| 146 | if not number or number[0] != '0':
|
|---|
| 147 | return ""
|
|---|
| 148 |
|
|---|
| 149 | countrycode = countrycode.replace('00', '+')
|
|---|
| 150 | if number[:2] == '00':
|
|---|
| 151 | normNumber = '+' + number[2:]
|
|---|
| 152 | elif number[:1] == '0':
|
|---|
| 153 | normNumber = countrycode + number[1:]
|
|---|
| 154 | else: # this should can not happen, but safety first
|
|---|
| 155 | return ""
|
|---|
| 156 |
|
|---|
| 157 | # debug('normNumer: ' + normNumber)
|
|---|
| 158 | for i in reversed(range(min(10, len(number)))):
|
|---|
| 159 | if avon.has_key(normNumber[:i]):
|
|---|
| 160 | return '[' + avon[normNumber[:i]].strip() + ']'
|
|---|
| 161 | return ""
|
|---|
| 162 |
|
|---|
| 163 | def handleReverseLookupResult(name):
|
|---|
| 164 | found = re.match("NA: ([^;]*);VN: ([^;]*);STR: ([^;]*);HNR: ([^;]*);PLZ: ([^;]*);ORT: ([^;]*)", name)
|
|---|
| 165 | if found:
|
|---|
| 166 | (name, firstname, street, streetno, zipcode, city) = (found.group(1),
|
|---|
| 167 | found.group(2),
|
|---|
| 168 | found.group(3),
|
|---|
| 169 | found.group(4),
|
|---|
| 170 | found.group(5),
|
|---|
| 171 | found.group(6)
|
|---|
| 172 | )
|
|---|
| 173 | if firstname:
|
|---|
| 174 | name += ' ' + firstname
|
|---|
| 175 | if street or streetno or zipcode or city:
|
|---|
| 176 | name += ', '
|
|---|
| 177 | if street:
|
|---|
| 178 | name += street
|
|---|
| 179 | if streetno:
|
|---|
| 180 | name += ' ' + streetno
|
|---|
| 181 | if (street or streetno) and (zipcode or city):
|
|---|
| 182 | name += ', '
|
|---|
| 183 | if zipcode and city:
|
|---|
| 184 | name += zipcode + ' ' + city
|
|---|
| 185 | elif zipcode:
|
|---|
| 186 | name += zipcode
|
|---|
| 187 | elif city:
|
|---|
| 188 | name += city
|
|---|
| 189 | return name
|
|---|
| 190 |
|
|---|
| 191 | from xml.dom.minidom import parse
|
|---|
| 192 | cbcInfos = {}
|
|---|
| 193 | def initCbC():
|
|---|
| 194 | callbycallFileName = resolveFilename(SCOPE_PLUGINS, "Extensions/NcidClient/callbycall_world.xml")
|
|---|
| 195 | if os.path.exists(callbycallFileName):
|
|---|
| 196 | dom = parse(callbycallFileName)
|
|---|
| 197 | for top in dom.getElementsByTagName("callbycalls"):
|
|---|
| 198 | for cbc in top.getElementsByTagName("country"):
|
|---|
| 199 | code = cbc.getAttribute("code").replace("+", "00")
|
|---|
| 200 | cbcInfos[code] = cbc.getElementsByTagName("callbycall")
|
|---|
| 201 | else:
|
|---|
| 202 | debug("[NcidClient] initCbC: callbycallFileName does not exist?!?!")
|
|---|
| 203 |
|
|---|
| 204 | def stripCbCPrefix(number, countrycode):
|
|---|
| 205 | if number and number[:2] != "00" and cbcInfos.has_key(countrycode):
|
|---|
| 206 | for cbc in cbcInfos[countrycode]:
|
|---|
| 207 | if len(cbc.getElementsByTagName("length")) < 1 or len(cbc.getElementsByTagName("prefix")) < 1:
|
|---|
| 208 | debug("[NcidClient] stripCbCPrefix: entries for " + countrycode + " %s invalid")
|
|---|
| 209 | return number
|
|---|
| 210 | length = int(cbc.getElementsByTagName("length")[0].childNodes[0].data)
|
|---|
| 211 | prefix = cbc.getElementsByTagName("prefix")[0].childNodes[0].data
|
|---|
| 212 | # if re.match('^'+prefix, number):
|
|---|
| 213 | if number[:len(prefix)] == prefix:
|
|---|
| 214 | return number[length:]
|
|---|
| 215 | return number
|
|---|
| 216 |
|
|---|
| 217 |
|
|---|
| 218 | FBF_boxInfo = 0
|
|---|
| 219 | FBF_upTime = 1
|
|---|
| 220 | FBF_ipAddress = 2
|
|---|
| 221 | FBF_wlanState = 3
|
|---|
| 222 | FBF_dslState = 4
|
|---|
| 223 | FBF_tamActive = 5
|
|---|
| 224 | FBF_dectActive = 6
|
|---|
| 225 | FBF_faxActive = 7
|
|---|
| 226 | FBF_rufumlActive = 8
|
|---|
| 227 |
|
|---|
| 228 | class NcidCall:
|
|---|
| 229 | def __init__(self):
|
|---|
| 230 | debug("[NcidCall] __init__")
|
|---|
| 231 | self._callScreen = None
|
|---|
| 232 | self._callTimestamp = 0
|
|---|
| 233 | self._callList = []
|
|---|
| 234 |
|
|---|
| 235 | def _notify(self, text):
|
|---|
| 236 | debug("[NcidCall] notify: " + text)
|
|---|
| 237 | self._md5LoginTimestamp = None
|
|---|
| 238 | if self._callScreen:
|
|---|
| 239 | debug("[NcidCall] notify: try to close callScreen")
|
|---|
| 240 | self._callScreen.close()
|
|---|
| 241 | self._callScreen = None
|
|---|
| 242 | Notifications.AddNotification(MessageBox, text, type=MessageBox.TYPE_ERROR, timeout=config.plugins.NcidClient.timeout.value)
|
|---|
| 243 |
|
|---|
| 244 | class NcidClientPhonebook:
|
|---|
| 245 | def __init__(self):
|
|---|
| 246 | debug("[NcidClientPhonebook] init")
|
|---|
| 247 | # Beware: strings in phonebook.phonebook have to be in utf-8!
|
|---|
| 248 | self.phonebook = {}
|
|---|
| 249 | self.reload()
|
|---|
| 250 |
|
|---|
| 251 | def reload(self):
|
|---|
| 252 | debug("[NcidClientPhonebook] reload")
|
|---|
| 253 | # Beware: strings in phonebook.phonebook have to be in utf-8!
|
|---|
| 254 | self.phonebook = {}
|
|---|
| 255 |
|
|---|
| 256 | if not config.plugins.NcidClient.enable.value:
|
|---|
| 257 | return
|
|---|
| 258 |
|
|---|
| 259 | phonebookFilename = os.path.join(config.plugins.NcidClient.phonebookLocation.value, "PhoneBook.txt")
|
|---|
| 260 | if config.plugins.NcidClient.phonebook.value and os.path.exists(phonebookFilename):
|
|---|
| 261 | debug("[NcidClientPhonebook] reload: read " + phonebookFilename)
|
|---|
| 262 | phonebookTxtCorrupt = False
|
|---|
| 263 | self.phonebook = {}
|
|---|
| 264 | for line in open(phonebookFilename):
|
|---|
| 265 | try:
|
|---|
| 266 | # Beware: strings in phonebook.phonebook have to be in utf-8!
|
|---|
| 267 | line = line.decode("utf-8")
|
|---|
| 268 | except UnicodeDecodeError: # this is just for the case, somebody wrote latin1 chars into PhoneBook.txt
|
|---|
| 269 | try:
|
|---|
| 270 | line = line.decode("iso-8859-1")
|
|---|
| 271 | debug("[NcidClientPhonebook] Fallback to ISO-8859-1 in %s" % line)
|
|---|
| 272 | phonebookTxtCorrupt = True
|
|---|
| 273 | except UnicodeDecodeError:
|
|---|
| 274 | debug("[NcidClientPhonebook] Could not parse internal Phonebook Entry %s" % line)
|
|---|
| 275 | phonebookTxtCorrupt = True
|
|---|
| 276 | line = line.encode("utf-8")
|
|---|
| 277 | elems = line.split('#')
|
|---|
| 278 | if len(elems) == 2:
|
|---|
| 279 | try:
|
|---|
| 280 | self.phonebook[elems[0]] = elems[1]
|
|---|
| 281 | except ValueError: # how could this possibly happen?!?!
|
|---|
| 282 | debug("[NcidClientPhonebook] Could not parse internal Phonebook Entry %s" % line)
|
|---|
| 283 | phonebookTxtCorrupt = True
|
|---|
| 284 | else:
|
|---|
| 285 | debug("[NcidClientPhonebook] Could not parse internal Phonebook Entry %s" % line)
|
|---|
| 286 | phonebookTxtCorrupt = True
|
|---|
| 287 |
|
|---|
| 288 | if phonebookTxtCorrupt:
|
|---|
| 289 | # dump phonebook to PhoneBook.txt
|
|---|
| 290 | debug("[NcidClientPhonebook] dump Phonebook.txt")
|
|---|
| 291 | try:
|
|---|
| 292 | os.rename(phonebookFilename, phonebookFilename + ".bck")
|
|---|
| 293 | fNew = open(phonebookFilename, 'w')
|
|---|
| 294 | # Beware: strings in phonebook.phonebook are utf-8!
|
|---|
| 295 | for (number, name) in self.phonebook.iteritems():
|
|---|
| 296 | # Beware: strings in PhoneBook.txt have to be in utf-8!
|
|---|
| 297 | fNew.write(number + "#" + name.encode("utf-8"))
|
|---|
| 298 | fNew.close()
|
|---|
| 299 | except (IOError, OSError):
|
|---|
| 300 | debug("[NcidClientPhonebook] error renaming or writing to %s" % phonebookFilename)
|
|---|
| 301 |
|
|---|
| 302 | def search(self, number):
|
|---|
| 303 | # debug("[NcidClientPhonebook] Searching for %s" %number)
|
|---|
| 304 | name = ""
|
|---|
| 305 | if not self.phonebook or not number:
|
|---|
| 306 | return
|
|---|
| 307 |
|
|---|
| 308 | if config.plugins.NcidClient.prefix.value:
|
|---|
| 309 | prefix = config.plugins.NcidClient.prefix.value
|
|---|
| 310 | if number[0] != '0':
|
|---|
| 311 | number = prefix + number
|
|---|
| 312 | # debug("[NcidClientPhonebook] search: added prefix: %s" %number)
|
|---|
| 313 | elif number[:len(prefix)] == prefix and self.phonebook.has_key(number[len(prefix):]):
|
|---|
| 314 | # debug("[NcidClientPhonebook] search: same prefix")
|
|---|
| 315 | name = self.phonebook[number[len(prefix):]]
|
|---|
| 316 | # debug("[NcidClientPhonebook] search: result: %s" %name)
|
|---|
| 317 | else:
|
|---|
| 318 | prefix = ""
|
|---|
| 319 |
|
|---|
| 320 | if not name and self.phonebook.has_key(number):
|
|---|
| 321 | name = self.phonebook[number]
|
|---|
| 322 |
|
|---|
| 323 | return name.replace(", ", "\n").strip()
|
|---|
| 324 |
|
|---|
| 325 | def add(self, number, name):
|
|---|
| 326 | '''
|
|---|
| 327 |
|
|---|
| 328 | @param number: number of entry
|
|---|
| 329 | @param name: name of entry, has to be in utf-8
|
|---|
| 330 | '''
|
|---|
| 331 | debug("[NcidClientPhonebook] add")
|
|---|
| 332 | name = name.replace("\n", ", ").replace('#', '') # this is just for safety reasons. add should only be called with newlines converted into commas
|
|---|
| 333 | self.remove(number)
|
|---|
| 334 | self.phonebook[number] = name
|
|---|
| 335 | if number and number != 0:
|
|---|
| 336 | if config.plugins.NcidClient.phonebook.value:
|
|---|
| 337 | try:
|
|---|
| 338 | name = name.strip() + "\n"
|
|---|
| 339 | string = "%s#%s" % (number, name)
|
|---|
| 340 | # Beware: strings in PhoneBook.txt have to be in utf-8!
|
|---|
| 341 | f = open(os.path.join(config.plugins.NcidClient.phonebookLocation.value, "PhoneBook.txt"), 'a')
|
|---|
| 342 | f.write(string)
|
|---|
| 343 | f.close()
|
|---|
| 344 | debug("[NcidClientPhonebook] added %s with %s to Phonebook.txt" % (number, name.strip()))
|
|---|
| 345 | return True
|
|---|
| 346 |
|
|---|
| 347 | except IOError:
|
|---|
| 348 | return False
|
|---|
| 349 |
|
|---|
| 350 | def remove(self, number):
|
|---|
| 351 | if number in self.phonebook:
|
|---|
| 352 | debug("[NcidClientPhonebook] remove entry in phonebook")
|
|---|
| 353 | del self.phonebook[number]
|
|---|
| 354 | if config.plugins.NcidClient.phonebook.value:
|
|---|
| 355 | try:
|
|---|
| 356 | phonebookFilename = os.path.join(config.plugins.NcidClient.phonebookLocation.value, "PhoneBook.txt")
|
|---|
| 357 | debug("[NcidClientPhonebook] remove entry in Phonebook.txt")
|
|---|
| 358 | fOld = open(phonebookFilename, 'r')
|
|---|
| 359 | fNew = open(phonebookFilename + str(os.getpid()), 'w')
|
|---|
| 360 | line = fOld.readline()
|
|---|
| 361 | while (line):
|
|---|
| 362 | elems = line.split('#')
|
|---|
| 363 | if len(elems) == 2 and not elems[0] == number:
|
|---|
| 364 | fNew.write(line)
|
|---|
| 365 | line = fOld.readline()
|
|---|
| 366 | fOld.close()
|
|---|
| 367 | fNew.close()
|
|---|
| 368 | # os.remove(phonebookFilename)
|
|---|
| 369 | eBackgroundFileEraser.getInstance().erase(phonebookFilename)
|
|---|
| 370 | os.rename(phonebookFilename + str(os.getpid()), phonebookFilename)
|
|---|
| 371 | debug("[NcidClientPhonebook] removed %s from Phonebook.txt" % number)
|
|---|
| 372 | return True
|
|---|
| 373 |
|
|---|
| 374 | except (IOError, OSError):
|
|---|
| 375 | debug("[NcidClientPhonebook] error removing %s from %s" % (number, phonebookFilename))
|
|---|
| 376 | return False
|
|---|
| 377 |
|
|---|
| 378 | class NcidDisplayPhonebook(Screen, NumericalTextInput):
|
|---|
| 379 |
|
|---|
| 380 | def __init__(self, session):
|
|---|
| 381 | self.entriesWidth = DESKTOP_WIDTH * scaleH(75, 85) / 100
|
|---|
| 382 | self.height = DESKTOP_HEIGHT * 0.75
|
|---|
| 383 | numberFieldWidth = scaleH(220, 160)
|
|---|
| 384 | fieldWidth = self.entriesWidth - 5 - numberFieldWidth - 10
|
|---|
| 385 | fontSize = scaleV(22, 18)
|
|---|
| 386 | fontHeight = scaleV(24, 20)
|
|---|
| 387 | buttonGap = (self.entriesWidth - 4 * 140) / 5
|
|---|
| 388 | debug("[NcidDisplayPhonebook] width: " + str(self.entriesWidth))
|
|---|
| 389 | self.skin = """
|
|---|
| 390 | <screen name="NcidDisplayPhonebook" position="center,center" size="%d,%d" title="Phonebook" >
|
|---|
| 391 | <eLabel position="0,0" size="%d,2" backgroundColor="#aaaaaa" />
|
|---|
| 392 | <widget source="entries" render="Listbox" position="%d,%d" size="%d,%d" scrollbarMode="showOnDemand" transparent="1">
|
|---|
| 393 | <convert type="TemplatedMultiContent">
|
|---|
| 394 | {"template": [
|
|---|
| 395 | MultiContentEntryText(pos = (%d,%d), size = (%d,%d), font=0, flags = RT_HALIGN_LEFT, text = 1), # index 0 is the name, index 1 is shortname
|
|---|
| 396 | MultiContentEntryText(pos = (%d,%d), size = (%d,%d), font=0, flags = RT_HALIGN_LEFT, text = 2), # index 2 is number
|
|---|
| 397 | ],
|
|---|
| 398 | "fonts": [gFont("Regular", %d)],
|
|---|
| 399 | "itemHeight": %d
|
|---|
| 400 | }
|
|---|
| 401 | </convert>
|
|---|
| 402 | </widget>
|
|---|
| 403 | <eLabel position="0,%d" size="%d,2" backgroundColor="#aaaaaa" />
|
|---|
| 404 | <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
|
|---|
| 405 | <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
|
|---|
| 406 | <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
|
|---|
| 407 | <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
|
|---|
| 408 | <widget name="key_red" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
|
|---|
| 409 | <widget name="key_green" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
|
|---|
| 410 | <widget name="key_yellow" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
|
|---|
| 411 | <widget name="key_blue" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
|
|---|
| 412 | </screen>""" % (
|
|---|
| 413 | # scaleH(90, 75), scaleV(100, 73), # position
|
|---|
| 414 | self.entriesWidth, self.height, # size
|
|---|
| 415 | self.entriesWidth, # eLabel width
|
|---|
| 416 | scaleH(40, 5), scaleV(20, 5), # entries position
|
|---|
| 417 | self.entriesWidth - scaleH(40, 5), self.height - scaleV(20, 5) - 5 - 5 - 40, # entries size
|
|---|
| 418 | 0, 0, fieldWidth, scaleH(24, 20), # name pos/size
|
|---|
| 419 | fieldWidth + 5, 0, numberFieldWidth, scaleH(24, 20), # dir pos/size
|
|---|
| 420 | fontSize, # fontsize
|
|---|
| 421 | fontHeight, # itemHeight
|
|---|
| 422 | self.height - 40 - 5, # eLabel position vertical
|
|---|
| 423 | self.entriesWidth, # eLabel width
|
|---|
| 424 | buttonGap, self.height - 40, "skin_default/buttons/red.png", # ePixmap red
|
|---|
| 425 | 2 * buttonGap + 140, self.height - 40, "skin_default/buttons/green.png", # ePixmap green
|
|---|
| 426 | 3 * buttonGap + 2 * 140, self.height - 40, "skin_default/buttons/yellow.png", # ePixmap yellow
|
|---|
| 427 | 4 * buttonGap + 3 * 140, self.height - 40, "skin_default/buttons/blue.png", # ePixmap blue
|
|---|
| 428 | buttonGap, self.height - 40, scaleV(22, 21), # widget red
|
|---|
| 429 | 2 * buttonGap + 140, self.height - 40, scaleV(22, 21), # widget green
|
|---|
| 430 | 3 * buttonGap + 2 * 140, self.height - 40, scaleV(22, 21), # widget yellow
|
|---|
| 431 | 4 * buttonGap + 3 * 140, self.height - 40, scaleV(22, 21), # widget blue
|
|---|
| 432 | )
|
|---|
| 433 |
|
|---|
| 434 | # debug("[NcidDisplayCalls] skin: " + self.skin)
|
|---|
| 435 | Screen.__init__(self, session)
|
|---|
| 436 | NumericalTextInput.__init__(self)
|
|---|
| 437 | HelpableScreen.__init__(self)
|
|---|
| 438 |
|
|---|
| 439 | # TRANSLATORS: keep it short, this is a button
|
|---|
| 440 | self["key_red"] = Button(_("Delete"))
|
|---|
| 441 | # TRANSLATORS: keep it short, this is a button
|
|---|
| 442 | self["key_green"] = Button(_("New"))
|
|---|
| 443 | # TRANSLATORS: keep it short, this is a button
|
|---|
| 444 | self["key_yellow"] = Button(_("Edit"))
|
|---|
| 445 | # TRANSLATORS: keep it short, this is a button
|
|---|
| 446 | self["key_blue"] = Button(_("Search"))
|
|---|
| 447 |
|
|---|
| 448 | self["setupActions"] = ActionMap(["OkCancelActions", "ColorActions"],
|
|---|
| 449 | {
|
|---|
| 450 | "red": self.delete,
|
|---|
| 451 | "green": self.add,
|
|---|
| 452 | "yellow": self.edit,
|
|---|
| 453 | "blue": self.search,
|
|---|
| 454 | "cancel": self.exit,
|
|---|
| 455 | "ok": self.showEntry, }, -2)
|
|---|
| 456 |
|
|---|
| 457 | self["entries"] = List([])
|
|---|
| 458 | debug("[NcidClientPhonebook] displayPhonebook init")
|
|---|
| 459 | self.help_window = None
|
|---|
| 460 | self.sortlist = []
|
|---|
| 461 | self.onLayoutFinish.append(self.setWindowTitle)
|
|---|
| 462 | self.display()
|
|---|
| 463 |
|
|---|
| 464 | def setWindowTitle(self):
|
|---|
| 465 | # TRANSLATORS: this is a window title.
|
|---|
| 466 | self.setTitle(_("Phonebook"))
|
|---|
| 467 |
|
|---|
| 468 | def display(self, filterNumber=""):
|
|---|
| 469 | debug("[NcidClientPhonebook] displayPhonebook/display")
|
|---|
| 470 | self.sortlist = []
|
|---|
| 471 | # Beware: strings in phonebook.phonebook are utf-8!
|
|---|
| 472 | sortlistHelp = sorted((name.lower(), name, number) for (number, name) in phonebook.phonebook.iteritems())
|
|---|
| 473 | for (low, name, number) in sortlistHelp:
|
|---|
| 474 | if number == "01234567890":
|
|---|
| 475 | continue
|
|---|
| 476 | try:
|
|---|
| 477 | low = low.decode("utf-8")
|
|---|
| 478 | except UnicodeDecodeError: # this should definitely not happen
|
|---|
| 479 | try:
|
|---|
| 480 | low = low.decode("iso-8859-1")
|
|---|
| 481 | except UnicodeDecodeError:
|
|---|
| 482 | debug("[NcidClientPhonebook] displayPhonebook/display: corrupt phonebook entry for %s" % number)
|
|---|
| 483 | # self.session.open(MessageBox, _("Corrupt phonebook entry\nfor number %s\nDeleting.") %number, type = MessageBox.TYPE_ERROR)
|
|---|
| 484 | phonebook.remove(number)
|
|---|
| 485 | continue
|
|---|
| 486 | else:
|
|---|
| 487 | if filterNumber:
|
|---|
| 488 | filterNumber = filterNumber.lower()
|
|---|
| 489 | if low.find(filterNumber) == -1:
|
|---|
| 490 | continue
|
|---|
| 491 | name = name.strip().decode("utf-8")
|
|---|
| 492 | number = number.strip().decode("utf-8")
|
|---|
| 493 | comma = name.find(',')
|
|---|
| 494 | if comma != -1:
|
|---|
| 495 | shortname = name[:comma]
|
|---|
| 496 | else:
|
|---|
| 497 | shortname = name
|
|---|
| 498 | number = number.encode("utf-8", "replace")
|
|---|
| 499 | name = name.encode("utf-8", "replace")
|
|---|
| 500 | shortname = shortname.encode('utf-8', 'replace')
|
|---|
| 501 | self.sortlist.append((name, shortname, number))
|
|---|
| 502 |
|
|---|
| 503 | self["entries"].setList(self.sortlist)
|
|---|
| 504 |
|
|---|
| 505 | def showEntry(self):
|
|---|
| 506 | cur = self["entries"].getCurrent()
|
|---|
| 507 | if cur:
|
|---|
| 508 | debug("[NcidClientPhonebook] displayPhonebook/showEntry %s" % (repr(cur)))
|
|---|
| 509 | number = cur[2]
|
|---|
| 510 | name = cur[0]
|
|---|
| 511 | self.session.open(NcidOfferAction, self, number, name)
|
|---|
| 512 |
|
|---|
| 513 | def delete(self):
|
|---|
| 514 | cur = self["entries"].getCurrent()
|
|---|
| 515 | if cur:
|
|---|
| 516 | debug("[NcidClientPhonebook] displayPhonebook/delete %s" % (repr(cur)))
|
|---|
| 517 | self.session.openWithCallback(
|
|---|
| 518 | self.deleteConfirmed,
|
|---|
| 519 | MessageBox,
|
|---|
| 520 | _("Do you really want to delete entry for\n\n%(number)s\n\n%(name)s?")
|
|---|
| 521 | % { 'number':str(cur[2]), 'name':str(cur[0]).replace(", ", "\n") }
|
|---|
| 522 | )
|
|---|
| 523 | else:
|
|---|
| 524 | self.session.open(MessageBox, _("No entry selected"), MessageBox.TYPE_INFO)
|
|---|
| 525 |
|
|---|
| 526 | def deleteConfirmed(self, ret):
|
|---|
| 527 | debug("[NcidClientPhonebook] displayPhonebook/deleteConfirmed")
|
|---|
| 528 | #
|
|---|
| 529 | # if ret: delete number from sortlist, delete number from phonebook.phonebook and write it to disk
|
|---|
| 530 | #
|
|---|
| 531 | cur = self["entries"].getCurrent()
|
|---|
| 532 | if cur:
|
|---|
| 533 | if ret:
|
|---|
| 534 | # delete number from sortlist, delete number from phonebook.phonebook and write it to disk
|
|---|
| 535 | debug("[NcidClientPhonebook] displayPhonebook/deleteConfirmed %s" % (repr(cur)))
|
|---|
| 536 | phonebook.remove(cur[2])
|
|---|
| 537 | self.display()
|
|---|
| 538 | # else:
|
|---|
| 539 | # self.session.open(MessageBox, _("Not deleted."), MessageBox.TYPE_INFO)
|
|---|
| 540 | else:
|
|---|
| 541 | self.session.open(MessageBox, _("No entry selected"), MessageBox.TYPE_INFO)
|
|---|
| 542 |
|
|---|
| 543 | def add(self, parent=None, number="", name=""):
|
|---|
| 544 | class AddScreen(Screen, ConfigListScreen):
|
|---|
| 545 | '''ConfiglistScreen with two ConfigTexts for Name and Number'''
|
|---|
| 546 |
|
|---|
| 547 | def __init__(self, session, parent, number="", name=""):
|
|---|
| 548 | #
|
|---|
| 549 | # setup screen with two ConfigText and OK and ABORT button
|
|---|
| 550 | #
|
|---|
| 551 | noButtons = 2
|
|---|
| 552 | width = max(scaleH(-1, 570), noButtons * 140)
|
|---|
| 553 | height = scaleV(-1, 100) # = 5 + 126 + 40 + 5; 6 lines of text possible
|
|---|
| 554 | buttonsGap = (width - noButtons * 140) / (noButtons + 1)
|
|---|
| 555 | buttonsVPos = height - 40 - 5
|
|---|
| 556 | self.skin = """
|
|---|
| 557 | <screen position="center,center" size="%d,%d" title="Add entry to phonebook" >
|
|---|
| 558 | <widget name="config" position="5,5" size="%d,%d" scrollbarMode="showOnDemand" />
|
|---|
| 559 | <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
|
|---|
| 560 | <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
|
|---|
| 561 | <widget name="key_red" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
|
|---|
| 562 | <widget name="key_green" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
|
|---|
| 563 | </screen>""" % (
|
|---|
| 564 | width, height,
|
|---|
| 565 | width - 5 - 5, height - 5 - 40 - 5,
|
|---|
| 566 | buttonsGap, buttonsVPos, "skin_default/buttons/red.png",
|
|---|
| 567 | buttonsGap + 140 + buttonsGap, buttonsVPos, "skin_default/buttons/green.png",
|
|---|
| 568 | buttonsGap, buttonsVPos,
|
|---|
| 569 | buttonsGap + 140 + buttonsGap, buttonsVPos,
|
|---|
| 570 | )
|
|---|
| 571 | Screen.__init__(self, session)
|
|---|
| 572 | self.session = session
|
|---|
| 573 | self.parent = parent
|
|---|
| 574 | # TRANSLATORS: keep it short, this is a button
|
|---|
| 575 | self["key_red"] = Button(_("Cancel"))
|
|---|
| 576 | # TRANSLATORS: keep it short, this is a button
|
|---|
| 577 | self["key_green"] = Button(_("OK"))
|
|---|
| 578 | self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
|
|---|
| 579 | {
|
|---|
| 580 | "cancel": self.cancel,
|
|---|
| 581 | "red": self.cancel,
|
|---|
| 582 | "green": self.add,
|
|---|
| 583 | "ok": self.add,
|
|---|
| 584 | }, -2)
|
|---|
| 585 |
|
|---|
| 586 | self.list = [ ]
|
|---|
| 587 | ConfigListScreen.__init__(self, self.list, session=session)
|
|---|
| 588 | self.name = name
|
|---|
| 589 | self.number = number
|
|---|
| 590 | config.plugins.NcidClient.name.value = name
|
|---|
| 591 | config.plugins.NcidClient.number.value = number
|
|---|
| 592 | self.list.append(getConfigListEntry(_("Name"), config.plugins.NcidClient.name))
|
|---|
| 593 | self.list.append(getConfigListEntry(_("Number"), config.plugins.NcidClient.number))
|
|---|
| 594 | self["config"].list = self.list
|
|---|
| 595 | self["config"].l.setList(self.list)
|
|---|
| 596 | self.onLayoutFinish.append(self.setWindowTitle)
|
|---|
| 597 |
|
|---|
| 598 | def setWindowTitle(self):
|
|---|
| 599 | # TRANSLATORS: this is a window title.
|
|---|
| 600 | self.setTitle(_("Add entry to phonebook"))
|
|---|
| 601 |
|
|---|
| 602 | def add(self):
|
|---|
| 603 | # get texts from Screen
|
|---|
| 604 | # add (number,name) to sortlist and phonebook.phonebook and disk
|
|---|
| 605 | self.name = config.plugins.NcidClient.name.value
|
|---|
| 606 | self.number = config.plugins.NcidClient.number.value
|
|---|
| 607 | if not self.number or not self.name:
|
|---|
| 608 | self.session.open(MessageBox, _("Entry incomplete."), type=MessageBox.TYPE_ERROR)
|
|---|
| 609 | return
|
|---|
| 610 |
|
|---|
| 611 | phonebook.add(self.number, self.name)
|
|---|
| 612 | self.close()
|
|---|
| 613 | self.parent.display()
|
|---|
| 614 |
|
|---|
| 615 | def overwriteConfirmed(self, ret):
|
|---|
| 616 | if ret:
|
|---|
| 617 | phonebook.remove(self.number)
|
|---|
| 618 | phonebook.add(self.number, self.name)
|
|---|
| 619 | self.parent.display()
|
|---|
| 620 |
|
|---|
| 621 | def cancel(self):
|
|---|
| 622 | self.close()
|
|---|
| 623 |
|
|---|
| 624 | debug("[NcidClientPhonebook] displayPhonebook/add")
|
|---|
| 625 | if not parent:
|
|---|
| 626 | parent = self
|
|---|
| 627 | self.session.open(AddScreen, parent, number, name)
|
|---|
| 628 |
|
|---|
| 629 | def edit(self):
|
|---|
| 630 | debug("[NcidClientPhonebook] displayPhonebook/edit")
|
|---|
| 631 | cur = self["entries"].getCurrent()
|
|---|
| 632 | if cur is None:
|
|---|
| 633 | self.session.open(MessageBox, _("No entry selected"), MessageBox.TYPE_INFO)
|
|---|
| 634 | else:
|
|---|
| 635 | self.add(self, cur[2], cur[0])
|
|---|
| 636 |
|
|---|
| 637 | def search(self):
|
|---|
| 638 | debug("[NcidClientPhonebook] displayPhonebook/search")
|
|---|
| 639 | self.help_window = self.session.instantiateDialog(NumericalTextInputHelpDialog, self)
|
|---|
| 640 | self.help_window.show()
|
|---|
| 641 | # VirtualKeyboard instead of InputBox?
|
|---|
| 642 | self.session.openWithCallback(self.doSearch, InputBox, _("Enter Search Terms"), _("Search phonebook"))
|
|---|
| 643 |
|
|---|
| 644 | def doSearch(self, searchTerms):
|
|---|
| 645 | if not searchTerms:
|
|---|
| 646 | searchTerms = ""
|
|---|
| 647 | debug("[NcidClientPhonebook] displayPhonebook/doSearch: " + searchTerms)
|
|---|
| 648 | if self.help_window:
|
|---|
| 649 | self.session.deleteDialog(self.help_window)
|
|---|
| 650 | self.help_window = None
|
|---|
| 651 | self.display(searchTerms)
|
|---|
| 652 |
|
|---|
| 653 | def exit(self):
|
|---|
| 654 | self.close()
|
|---|
| 655 |
|
|---|
| 656 | phonebook = NcidClientPhonebook()
|
|---|
| 657 |
|
|---|
| 658 | class NcidClientSetup(Screen, ConfigListScreen):
|
|---|
| 659 |
|
|---|
| 660 | def __init__(self, session, args=None): #@UnusedVariable # pylint: disable=W0613
|
|---|
| 661 | self.width = scaleH(20 + 4 * (140 + 90) + 2 * (35 + 40) + 20, 4 * 140 + 2 * 35)
|
|---|
| 662 | width = self.width
|
|---|
| 663 | debug("[NcidClientSetup] width: " + str(self.width))
|
|---|
| 664 | self.skin = """
|
|---|
| 665 | <screen name="NcidClientSetup" position="center,center" size="%d,%d" title="NcidClient Setup" >
|
|---|
| 666 | <eLabel position="0,0" size="%d,2" backgroundColor="#aaaaaa" />
|
|---|
| 667 | <eLabel position="0,%d" size="%d,2" backgroundColor="#aaaaaa" />
|
|---|
| 668 | <widget name="config" position="%d,%d" size="%d,%d" scrollbarMode="showOnDemand" backgroundColor="#20040404" transparent="1" />
|
|---|
| 669 | <eLabel position="0,%d" size="%d,2" backgroundColor="#aaaaaa" />
|
|---|
| 670 | <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
|
|---|
| 671 | <ePixmap position="%d,%d" zPosition="4" size="140,40" pixmap="%s" transparent="1" alphatest="on" />
|
|---|
| 672 | <widget name="key_red" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
|
|---|
| 673 | <widget name="key_green" position="%d,%d" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;%d" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
|
|---|
| 674 | </screen>""" % (
|
|---|
| 675 | # (DESKTOP_WIDTH-width)/2, scaleV(100, 73), # position
|
|---|
| 676 | width, scaleV(560, 430), # size
|
|---|
| 677 | width, # eLabel width
|
|---|
| 678 | scaleV(40, 50), # eLabel position vertical
|
|---|
| 679 | width, # eLabel width
|
|---|
| 680 | scaleH(40, 5), scaleV(60, 57), # config position
|
|---|
| 681 | scaleH(width - 80, width - 10), scaleV(453, 328), # config size
|
|---|
| 682 | scaleV(518, 390), # eLabel position vertical
|
|---|
| 683 | width, # eLabel width
|
|---|
| 684 | scaleH(20, 0), scaleV(525, 395), "skin_default/buttons/red.png", # pixmap red
|
|---|
| 685 | scaleH(20 + 140 + 90, 140), scaleV(525, 395), "skin_default/buttons/green.png", # pixmap green
|
|---|
| 686 | scaleH(20, 0), scaleV(525, 395), scaleV(21, 21), # widget red
|
|---|
| 687 | scaleH(20 + (140 + 90), 140), scaleV(525, 395), scaleV(21, 21), # widget green
|
|---|
| 688 | )
|
|---|
| 689 |
|
|---|
| 690 | Screen.__init__(self, session)
|
|---|
| 691 | self.session = session
|
|---|
| 692 |
|
|---|
| 693 | self.list = []
|
|---|
| 694 |
|
|---|
| 695 | # Initialize Buttons
|
|---|
| 696 | # TRANSLATORS: keep it short, this is a button
|
|---|
| 697 | self["key_red"] = Button(_("Cancel"))
|
|---|
| 698 | # TRANSLATORS: keep it short, this is a button
|
|---|
| 699 | self["key_green"] = Button(_("OK"))
|
|---|
| 700 |
|
|---|
| 701 | self["setupActions"] = ActionMap(["ColorActions", "OkCancelActions", "MenuActions", "EPGSelectActions"],
|
|---|
| 702 | {
|
|---|
| 703 | "red": self.cancel,
|
|---|
| 704 | "green": self.save,
|
|---|
| 705 | "cancel": self.cancel,
|
|---|
| 706 | "ok": self.save,
|
|---|
| 707 | }, -2)
|
|---|
| 708 |
|
|---|
| 709 | ConfigListScreen.__init__(self, self.list, session=session)
|
|---|
| 710 |
|
|---|
| 711 | # get new list of locations for PhoneBook.txt
|
|---|
| 712 | self._mountedDevices = getMountedDevices()
|
|---|
| 713 | self.createSetup()
|
|---|
| 714 | self.onLayoutFinish.append(self.setWindowTitle)
|
|---|
| 715 |
|
|---|
| 716 | def setWindowTitle(self):
|
|---|
| 717 | # TRANSLATORS: this is a window title.
|
|---|
| 718 | self.setTitle(_("NCID Client - Setup"))
|
|---|
| 719 |
|
|---|
| 720 | def keyLeft(self):
|
|---|
| 721 | ConfigListScreen.keyLeft(self)
|
|---|
| 722 | self.createSetup()
|
|---|
| 723 |
|
|---|
| 724 | def keyRight(self):
|
|---|
| 725 | ConfigListScreen.keyRight(self)
|
|---|
| 726 | self.createSetup()
|
|---|
| 727 |
|
|---|
| 728 | def createSetup(self):
|
|---|
| 729 | self.list = [ ]
|
|---|
| 730 | self.list.append(getConfigListEntry(_("Call monitoring"), config.plugins.NcidClient.enable))
|
|---|
| 731 | if config.plugins.NcidClient.enable.value:
|
|---|
| 732 | self.list.append(getConfigListEntry(_("NCID server (Name or IP)"), config.plugins.NcidClient.hostname))
|
|---|
| 733 | self.list.append(getConfigListEntry(_("NCID server listening port (1-65535)"), config.plugins.NcidClient.port))
|
|---|
| 734 |
|
|---|
| 735 | self.list.append(getConfigListEntry(_("Show after Standby"), config.plugins.NcidClient.afterStandby))
|
|---|
| 736 |
|
|---|
| 737 | # not only for outgoing: config.plugins.NcidClient.showOutgoing.value:
|
|---|
| 738 | self.list.append(getConfigListEntry(_("Areacode to add to calls without one (if necessary)"), config.plugins.NcidClient.prefix))
|
|---|
| 739 | self.list.append(getConfigListEntry(_("Timeout for Call Notifications (seconds)"), config.plugins.NcidClient.timeout))
|
|---|
| 740 | self.list.append(getConfigListEntry(_("Reverse Lookup Caller ID (select country below)"), config.plugins.NcidClient.lookup))
|
|---|
| 741 | if config.plugins.NcidClient.lookup.value:
|
|---|
| 742 | self.list.append(getConfigListEntry(_("Country"), config.plugins.NcidClient.country))
|
|---|
| 743 |
|
|---|
| 744 | self.list.append(getConfigListEntry(_("Use internal PhoneBook"), config.plugins.NcidClient.phonebook))
|
|---|
| 745 | if config.plugins.NcidClient.phonebook.value:
|
|---|
| 746 | if config.plugins.NcidClient.phonebookLocation.value in self._mountedDevices:
|
|---|
| 747 | config.plugins.NcidClient.phonebookLocation.setChoices(self._mountedDevices, config.plugins.NcidClient.phonebookLocation.value)
|
|---|
| 748 | else:
|
|---|
| 749 | config.plugins.NcidClient.phonebookLocation.setChoices(self._mountedDevices)
|
|---|
| 750 | path = config.plugins.NcidClient.phonebookLocation.value
|
|---|
| 751 | # check whether we can write to PhoneBook.txt
|
|---|
| 752 | if os.path.exists(os.path.join(path[0], "PhoneBook.txt")):
|
|---|
| 753 | if not os.access(os.path.join(path[0], "PhoneBook.txt"), os.W_OK):
|
|---|
| 754 | debug("[NcidClientSetup] createSetup: %s/PhoneBook.txt not writable, resetting to default" % (path[0]))
|
|---|
| 755 | config.plugins.NcidClient.phonebookLocation.setChoices(self._mountedDevices)
|
|---|
| 756 | elif not (os.path.isdir(path[0]) and os.access(path[0], os.W_OK | os.X_OK)):
|
|---|
| 757 | debug("[NcidClientSetup] createSetup: directory %s not writable, resetting to default" % (path[0]))
|
|---|
| 758 | config.plugins.NcidClient.phonebookLocation.setChoices(self._mountedDevices)
|
|---|
| 759 |
|
|---|
| 760 | self.list.append(getConfigListEntry(_("PhoneBook Location"), config.plugins.NcidClient.phonebookLocation))
|
|---|
| 761 | if config.plugins.NcidClient.lookup.value:
|
|---|
| 762 | self.list.append(getConfigListEntry(_("Automatically add new Caller to PhoneBook"), config.plugins.NcidClient.addcallers))
|
|---|
| 763 |
|
|---|
| 764 | self.list.append(getConfigListEntry(_("Strip Leading 0"), config.plugins.NcidClient.internal))
|
|---|
| 765 | self.list.append(getConfigListEntry(_("Show connection information popups"), config.plugins.NcidClient.connectionVerbose))
|
|---|
| 766 |
|
|---|
| 767 | self["config"].list = self.list
|
|---|
| 768 | self["config"].l.setList(self.list)
|
|---|
| 769 |
|
|---|
| 770 | def save(self):
|
|---|
| 771 | # debug("[NcidClientSetup] save"
|
|---|
| 772 | for x in self["config"].list:
|
|---|
| 773 | x[1].save()
|
|---|
| 774 | if config.plugins.NcidClient.phonebookLocation.isChanged():
|
|---|
| 775 | global phonebook
|
|---|
| 776 | phonebook = NcidClientPhonebook()
|
|---|
| 777 | if ncid_call:
|
|---|
| 778 | if config.plugins.NcidClient.enable.value:
|
|---|
| 779 | ncid_call.connect()
|
|---|
| 780 | else:
|
|---|
| 781 | ncid_call.shutdown()
|
|---|
| 782 | self.close()
|
|---|
| 783 |
|
|---|
| 784 | def cancel(self):
|
|---|
| 785 | # debug("[NcidClientSetup] cancel"
|
|---|
| 786 | for x in self["config"].list:
|
|---|
| 787 | x[1].cancel()
|
|---|
| 788 | self.close()
|
|---|
| 789 |
|
|---|
| 790 | def displayPhonebook(self):
|
|---|
| 791 | if phonebook:
|
|---|
| 792 | if config.plugins.NcidClient.enable.value:
|
|---|
| 793 | self.session.open(phonebook.NcidDisplayPhonebook)
|
|---|
| 794 | else:
|
|---|
| 795 | self.session.open(MessageBox, _("Plugin not active"), type=MessageBox.TYPE_INFO)
|
|---|
| 796 | else:
|
|---|
| 797 | self.session.open(MessageBox, _("No phonebook"), type=MessageBox.TYPE_INFO)
|
|---|
| 798 |
|
|---|
| 799 |
|
|---|
| 800 | standbyMode = False
|
|---|
| 801 |
|
|---|
| 802 | class NcidCallList:
|
|---|
| 803 | def __init__(self):
|
|---|
| 804 | self.callList = [ ]
|
|---|
| 805 |
|
|---|
| 806 | def add(self, date, number, caller):
|
|---|
| 807 | debug("[NcidCallList] add: %s %s" % (number, caller))
|
|---|
| 808 | if len(self.callList) > 10:
|
|---|
| 809 | if self.callList[0] != "Start":
|
|---|
| 810 | self.callList[0] = "Start"
|
|---|
| 811 | del self.callList[1]
|
|---|
| 812 |
|
|---|
| 813 | self.callList.append((number, date, caller))
|
|---|
| 814 |
|
|---|
| 815 | def display(self):
|
|---|
| 816 | debug("[NcidCallList] display")
|
|---|
| 817 | global standbyMode
|
|---|
| 818 | standbyMode = False
|
|---|
| 819 | # Standby.inStandby.onClose.remove(self.display) object does not exist anymore...
|
|---|
| 820 | # build screen from call list
|
|---|
| 821 | text = "\n"
|
|---|
| 822 |
|
|---|
| 823 | if not self.callList:
|
|---|
| 824 | text = _("no calls")
|
|---|
| 825 | else:
|
|---|
| 826 | if self.callList[0] == "Start":
|
|---|
| 827 | text = text + _("Last 10 calls:\n")
|
|---|
| 828 | del self.callList[0]
|
|---|
| 829 |
|
|---|
| 830 | for call in self.callList:
|
|---|
| 831 | (number, date, caller) = call
|
|---|
| 832 |
|
|---|
| 833 | # should not happen, for safety reasons
|
|---|
| 834 | if not caller:
|
|---|
| 835 | caller = _("UNKNOWN")
|
|---|
| 836 |
|
|---|
| 837 | # if we have an unknown number, show the number
|
|---|
| 838 | if caller == _("UNKNOWN") and number != "":
|
|---|
| 839 | caller = number
|
|---|
| 840 | else:
|
|---|
| 841 | # strip off the address part of the remote caller/callee, if there is any
|
|---|
| 842 | nl = caller.find('\n')
|
|---|
| 843 | if nl != -1:
|
|---|
| 844 | caller = caller[:nl]
|
|---|
| 845 | elif caller[0] == '[' and caller[-1] == ']':
|
|---|
| 846 | # that means, we've got an unknown number with a city added from avon.dat
|
|---|
| 847 | if (len(number) + 1 + len(caller)) <= 40:
|
|---|
| 848 | caller = number + ' ' + caller
|
|---|
| 849 | else:
|
|---|
| 850 | caller = number
|
|---|
| 851 |
|
|---|
| 852 | while (len(caller)) > 40:
|
|---|
| 853 | caller = caller[:-1]
|
|---|
| 854 |
|
|---|
| 855 | text = text + "%s - %s\n" % (date, caller)
|
|---|
| 856 | debug("[NcidCallList] display: '%s - %s'" % (date, caller))
|
|---|
| 857 |
|
|---|
| 858 | # display screen
|
|---|
| 859 | Notifications.AddNotification(MessageBox, text, type=MessageBox.TYPE_INFO)
|
|---|
| 860 | # TODO please HELP: from where can I get a session?
|
|---|
| 861 | # my_global_session.open(NcidDisplayCalls, text)
|
|---|
| 862 | self.callList = [ ]
|
|---|
| 863 |
|
|---|
| 864 | callList = NcidCallList()
|
|---|
| 865 |
|
|---|
| 866 | global_muted = None
|
|---|
| 867 | def notifyCall(date, number, caller):
|
|---|
| 868 | if Standby.inStandby is None or config.plugins.NcidClient.afterStandby.value == "each":
|
|---|
| 869 | global global_muted
|
|---|
| 870 | if config.plugins.NcidClient.muteOnCall.value and not global_muted:
|
|---|
| 871 | # eDVBVolumecontrol.getInstance().volumeMute() # with this, we get no mute icon...
|
|---|
| 872 | if not eDVBVolumecontrol.getInstance().isMuted():
|
|---|
| 873 | globalActionMap.actions["volumeMute"]()
|
|---|
| 874 | text = _("Incoming Call on %s from\n---------------------------------------------\n%s\n%s\n---------------------------------------------") % (date, number, caller)
|
|---|
| 875 | debug("[NcidClient] notifyCall:\n%s" % text)
|
|---|
| 876 | Notifications.AddNotification(MessageBox, text, type=MessageBox.TYPE_INFO, timeout=config.plugins.NcidClient.timeout.value)
|
|---|
| 877 | #Notifications.AddNotification(MessageBoxPixmap, text, number=number, name=caller, timeout=config.plugins.NcidClient.timeout.value)
|
|---|
| 878 | elif config.plugins.NcidClient.afterStandby.value == "inList":
|
|---|
| 879 | #
|
|---|
| 880 | # if not yet done, register function to show call list
|
|---|
| 881 | global standbyMode
|
|---|
| 882 | if not standbyMode :
|
|---|
| 883 | standbyMode = True
|
|---|
| 884 | Standby.inStandby.onHide.append(callList.display) #@UndefinedVariable
|
|---|
| 885 | # add text/timeout to call list
|
|---|
| 886 | callList.add(date, number, caller)
|
|---|
| 887 | debug("[NcidClient] notifyCall: added to callList")
|
|---|
| 888 | else: # this is the "None" case
|
|---|
| 889 | debug("[NcidClient] notifyCall: standby and no show")
|
|---|
| 890 |
|
|---|
| 891 |
|
|---|
| 892 | #===============================================================================
|
|---|
| 893 | # We need a separate class for each invocation of reverseLookup to retain
|
|---|
| 894 | # the necessary data for the notification
|
|---|
| 895 | #===============================================================================
|
|---|
| 896 |
|
|---|
| 897 | countries = { }
|
|---|
| 898 | reverselookupMtime = 0
|
|---|
| 899 |
|
|---|
| 900 | class NcidReverseLookupAndNotify:
|
|---|
| 901 | def __init__(self, number, caller, date):
|
|---|
| 902 | '''
|
|---|
| 903 |
|
|---|
| 904 | Initiate a reverse lookup for the given number in the configured country
|
|---|
| 905 | @param number: number to be looked up
|
|---|
| 906 | @param caller: caller including name and address
|
|---|
| 907 | @param date: date of call
|
|---|
| 908 | '''
|
|---|
| 909 | debug("[NcidReverseLookupAndNotify] reverse Lookup for %s!" % number)
|
|---|
| 910 | self.number = number
|
|---|
| 911 | self.caller = caller
|
|---|
| 912 | self.date = date
|
|---|
| 913 |
|
|---|
| 914 | if number[0] != "0":
|
|---|
| 915 | self.notifyAndReset(number, caller)
|
|---|
| 916 | return
|
|---|
| 917 |
|
|---|
| 918 | ReverseLookupAndNotify(number, self.notifyAndReset, "UTF-8", config.plugins.NcidClient.country.value)
|
|---|
| 919 |
|
|---|
| 920 | def notifyAndReset(self, number, caller):
|
|---|
| 921 | '''
|
|---|
| 922 |
|
|---|
| 923 | this gets called with the result of the reverse lookup
|
|---|
| 924 |
|
|---|
| 925 | @param number: number
|
|---|
| 926 | @param caller: name and address of remote. it comes in with name, address and city separated by commas
|
|---|
| 927 | '''
|
|---|
| 928 | debug("[NcidReverseLookupAndNotify] got: %s" % caller)
|
|---|
| 929 | self.number = number
|
|---|
| 930 | name = handleReverseLookupResult(caller)
|
|---|
| 931 | if name:
|
|---|
| 932 | self.caller = name.replace(", ", "\n").replace('#', '')
|
|---|
| 933 |
|
|---|
| 934 | if self.number != 0 and config.plugins.NcidClient.addcallers.value:
|
|---|
| 935 | debug("[NcidReverseLookupAndNotify] add to phonebook")
|
|---|
| 936 | phonebook.add(self.number, self.caller)
|
|---|
| 937 | else:
|
|---|
| 938 | name = resolveNumberWithAvon(self.number, config.plugins.NcidClient.country.value)
|
|---|
| 939 | if not name:
|
|---|
| 940 | self.caller = _("UNKNOWN")
|
|---|
| 941 | else:
|
|---|
| 942 | self.caller = name
|
|---|
| 943 | notifyCall(self.date, self.number, self.caller)
|
|---|
| 944 |
|
|---|
| 945 | class NcidLineReceiver(LineReceiver):
|
|---|
| 946 | def __init__(self):
|
|---|
| 947 | global global_muted
|
|---|
| 948 | global_muted = None
|
|---|
| 949 | self.resetValues()
|
|---|
| 950 |
|
|---|
| 951 | def resetValues(self):
|
|---|
| 952 | self.number = None
|
|---|
| 953 | self.caller = None
|
|---|
| 954 | self.date = '01011970'
|
|---|
| 955 | self.time = '0001'
|
|---|
| 956 | self.line = ''
|
|---|
| 957 |
|
|---|
| 958 | def notifyAndReset(self):
|
|---|
| 959 | notifyCall(self.date, self.number, self.caller)
|
|---|
| 960 | self.resetValues()
|
|---|
| 961 |
|
|---|
| 962 | def lineReceived(self, line):
|
|---|
| 963 | debug("[NcidLineReceiver] lineReceived: %s" % line)
|
|---|
| 964 | #200 NCID Server: ARC_ncidd 0.01
|
|---|
| 965 | #CIDLOG: *DATE*21102010*TIME*1454*LINE**NMBR*089999999999*MESG*NONE*NAME*NO NAME*
|
|---|
| 966 | #CIDLOG: *DATE*21102010*TIME*1456*LINE**NMBR*089999999999*MESG*NONE*NAME*NO NAME*
|
|---|
| 967 | #CID: *DATE*22102010*TIME*1502*LINE**NMBR*015209957840*MESG*NONE*NAME*NO NAME*
|
|---|
| 968 |
|
|---|
| 969 | #Callog entries begin with CIDLOG, "current" events begin with CID
|
|---|
| 970 | #we don't want to do anything with log-entries
|
|---|
| 971 | if line.startswith("CID:"):
|
|---|
| 972 | line = line[6:]
|
|---|
| 973 | debug("[NcidLineReceiver.lineReceived] filtered Line: %s" % line)
|
|---|
| 974 | else:
|
|---|
| 975 | return
|
|---|
| 976 |
|
|---|
| 977 | items = line.split('*')
|
|---|
| 978 |
|
|---|
| 979 | for i in range(0, len(items)):
|
|---|
| 980 | item = items[i]
|
|---|
| 981 |
|
|---|
| 982 | if item == 'DATE':
|
|---|
| 983 | self.date = items[i + 1]
|
|---|
| 984 | elif item == 'TIME':
|
|---|
| 985 | self.time = items[i + 1]
|
|---|
| 986 | elif item == 'LINE':
|
|---|
| 987 | self.line = items[i + 1]
|
|---|
| 988 | elif item == 'NMBR':
|
|---|
| 989 | self.number = items[i + 1]
|
|---|
| 990 |
|
|---|
| 991 | date = datetime.strptime("%s - %s" % (self.date, self.time), "%d%m%Y - %H%M")
|
|---|
| 992 | self.date = date.strftime("%d.%m.%Y - %H:%M")
|
|---|
| 993 |
|
|---|
| 994 | if not self.number:
|
|---|
| 995 | debug("[NcidLineReceiver] lineReceived: no number")
|
|---|
| 996 | self.number = _("number suppressed")
|
|---|
| 997 | self.caller = _("UNKNOWN")
|
|---|
| 998 | else:
|
|---|
| 999 | if config.plugins.NcidClient.internal.value and len(self.number) > 3 and self.number[0] == "0":
|
|---|
| 1000 | debug("[NcidLineReceiver] lineReceived: strip leading 0")
|
|---|
| 1001 | self.number = self.number[1:]
|
|---|
| 1002 | else:
|
|---|
| 1003 | if self.number[0] != '0':
|
|---|
| 1004 | debug("[NcidLineReceiver] lineReceived: add local prefix")
|
|---|
| 1005 | self.number = config.plugins.NcidClient.prefix.value + self.number
|
|---|
| 1006 |
|
|---|
| 1007 | self.number = stripCbCPrefix(self.number, config.plugins.NcidClient.country.value)
|
|---|
| 1008 |
|
|---|
| 1009 | debug("[NcidLineReceiver] lineReceived phonebook.search: %s" % self.number)
|
|---|
| 1010 | self.caller = phonebook.search(self.number)
|
|---|
| 1011 | debug("[NcidLineReceiver] lineReceived phonebook.search reault: %s" % self.caller)
|
|---|
| 1012 | if not self.caller:
|
|---|
| 1013 | if config.plugins.NcidClient.lookup.value:
|
|---|
| 1014 | NcidReverseLookupAndNotify(self.number, self.caller, self.date)
|
|---|
| 1015 | return # reverselookup is supposed to handle the message itself
|
|---|
| 1016 | else:
|
|---|
| 1017 | self.caller = _("UNKNOWN")
|
|---|
| 1018 |
|
|---|
| 1019 | self.notifyAndReset()
|
|---|
| 1020 |
|
|---|
| 1021 | class NcidClientFactory(ReconnectingClientFactory):
|
|---|
| 1022 | initialDelay = 20
|
|---|
| 1023 | maxDelay = 30
|
|---|
| 1024 |
|
|---|
| 1025 | def __init__(self):
|
|---|
| 1026 | self.hangup_ok = False
|
|---|
| 1027 | def startedConnecting(self, connector): #@UnusedVariable # pylint: disable=W0613
|
|---|
| 1028 | if config.plugins.NcidClient.connectionVerbose.value:
|
|---|
| 1029 | Notifications.AddNotification(MessageBox, _("Connecting to NCID Server..."), type=MessageBox.TYPE_INFO, timeout=2)
|
|---|
| 1030 |
|
|---|
| 1031 | def buildProtocol(self, addr): #@UnusedVariable # pylint: disable=W0613
|
|---|
| 1032 | global ncidsrv, phonebook
|
|---|
| 1033 | if config.plugins.NcidClient.connectionVerbose.value:
|
|---|
| 1034 | Notifications.AddNotification(MessageBox, _("Connected to NCID Server"), type=MessageBox.TYPE_INFO, timeout=4)
|
|---|
| 1035 | self.resetDelay()
|
|---|
| 1036 | initAvon()
|
|---|
| 1037 | ncidsrv = NcidCall()
|
|---|
| 1038 | phonebook = NcidClientPhonebook()
|
|---|
| 1039 | return NcidLineReceiver()
|
|---|
| 1040 |
|
|---|
| 1041 | def clientConnectionLost(self, connector, reason):
|
|---|
| 1042 | global ncidsrv
|
|---|
| 1043 | if not self.hangup_ok and config.plugins.NcidClient.connectionVerbose.value:
|
|---|
| 1044 | Notifications.AddNotification(MessageBox, _("Connection to NCID Server lost\n (%s)\nretrying...") % reason.getErrorMessage(), type=MessageBox.TYPE_INFO, timeout=config.plugins.NcidClient.timeout.value)
|
|---|
| 1045 | ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
|
|---|
| 1046 | # config.plugins.NcidClient.enable.value = False
|
|---|
| 1047 | ncidsrv = None
|
|---|
| 1048 |
|
|---|
| 1049 | def clientConnectionFailed(self, connector, reason):
|
|---|
| 1050 | global ncidsrv
|
|---|
| 1051 | if config.plugins.NcidClient.connectionVerbose.value:
|
|---|
| 1052 | Notifications.AddNotification(MessageBox, _("Connecting to NCID Server failed\n (%s)\nretrying...") % reason.getErrorMessage(), type=MessageBox.TYPE_INFO, timeout=config.plugins.NcidClient.timeout.value)
|
|---|
| 1053 | ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
|
|---|
| 1054 | # config.plugins.NcidClient.enable.value = False
|
|---|
| 1055 | ncidsrv = None
|
|---|
| 1056 |
|
|---|
| 1057 | class NcidClient:
|
|---|
| 1058 | def __init__(self):
|
|---|
| 1059 | self.dialog = None
|
|---|
| 1060 | self.desc = None
|
|---|
| 1061 | if config.plugins.NcidClient.enable.value:
|
|---|
| 1062 | self.connect()
|
|---|
| 1063 |
|
|---|
| 1064 | def connect(self):
|
|---|
| 1065 | self.abort()
|
|---|
| 1066 | if config.plugins.NcidClient.enable.value:
|
|---|
| 1067 | factory = NcidClientFactory()
|
|---|
| 1068 | self.desc = (factory, reactor.connectTCP(config.plugins.NcidClient.hostname.value, config.plugins.NcidClient.port.value, factory))
|
|---|
| 1069 |
|
|---|
| 1070 | def shutdown(self):
|
|---|
| 1071 | self.abort()
|
|---|
| 1072 |
|
|---|
| 1073 | def abort(self):
|
|---|
| 1074 | if self.desc is not None:
|
|---|
| 1075 | self.desc[0].hangup_ok = True
|
|---|
| 1076 | self.desc[0].stopTrying()
|
|---|
| 1077 | self.desc[1].disconnect()
|
|---|
| 1078 | self.desc = None
|
|---|
| 1079 |
|
|---|
| 1080 | def main(session):
|
|---|
| 1081 | session.open(NcidClientSetup)
|
|---|
| 1082 |
|
|---|
| 1083 | ncid_call = None
|
|---|
| 1084 |
|
|---|
| 1085 | def autostart(reason, **kwargs):
|
|---|
| 1086 | global ncid_call
|
|---|
| 1087 |
|
|---|
| 1088 | # ouch, this is a hack
|
|---|
| 1089 | if kwargs.has_key("session"):
|
|---|
| 1090 | global my_global_session
|
|---|
| 1091 | my_global_session = kwargs["session"]
|
|---|
| 1092 | return
|
|---|
| 1093 |
|
|---|
| 1094 | debug("[NcidClient] - Autostart")
|
|---|
| 1095 | if reason == 0:
|
|---|
| 1096 | ncid_call = NcidClient()
|
|---|
| 1097 | elif reason == 1:
|
|---|
| 1098 | ncid_call.shutdown()
|
|---|
| 1099 | ncid_call = None
|
|---|
| 1100 |
|
|---|
| 1101 | def Plugins(**kwargs): #@UnusedVariable # pylint: disable=W0613,C0103
|
|---|
| 1102 | what = _("Display Fon calls on screen")
|
|---|
| 1103 | return [ PluginDescriptor(name="NCID Client", description=what, where=PluginDescriptor.WHERE_PLUGINMENU, icon="plugin.png", fnc=main),
|
|---|
| 1104 | PluginDescriptor(where=[PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc=autostart) ]
|
|---|
| 1105 |
|
|---|