NeuronModule.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import logging
  2. import os
  3. import random
  4. from jinja2 import Template
  5. from core.ConfigurationManager import SettingLoader
  6. logging.basicConfig()
  7. logger = logging.getLogger("jarvis")
  8. class NoTemplateException(Exception):
  9. pass
  10. class MultipleTemplateException(Exception):
  11. pass
  12. class TemplateFileNotFoundException(Exception):
  13. pass
  14. class TTSModuleNotFound(Exception):
  15. pass
  16. class TTSNotInstantiable(Exception):
  17. pass
  18. class NeuronModule(object):
  19. def __init__(self, **kwargs):
  20. """
  21. Class used by neuron for talking
  22. :param kwargs: Same parameter as the Child. Can contain info about the tts to use instead of the
  23. default one
  24. """
  25. # get the child who called the class
  26. child_name = self.__class__.__name__
  27. logger.debug("NeuronModule called from class %s with parameters: %s" % (child_name, kwargs))
  28. # check if the user has overrider the TTS
  29. tts = kwargs.get('tts', None)
  30. if tts is None:
  31. # No tts provided, we load the default one
  32. self.tts = SettingLoader().get_default_text_to_speech()
  33. else:
  34. self.tts = tts
  35. # get if the cache settings is present
  36. self.override_cache = kwargs.get('cache', None)
  37. # get templates if provided
  38. # Check if there is a template associate to the output message
  39. self.say_template = kwargs.get('say_template', None)
  40. # check if there is a template file associate to the output message
  41. self.file_template = kwargs.get('file_template', None)
  42. def say(self, message):
  43. """
  44. USe TTS to speak out loud the Message.
  45. A message can be a string, a list or a dict
  46. If it's a string, simply use the TTS with the message
  47. If it's a list, we select randomly a string in the list and give it to the TTS
  48. If it's a dict, we use the template given in parameter to create a string that we give to the TTS
  49. :param message: Can be a String or a dict
  50. :return:
  51. """
  52. logger.debug("NeuronModule Say() called with message: %s" % message)
  53. tts_message = None
  54. if isinstance(message, str):
  55. print "message is string"
  56. tts_message = message
  57. if isinstance(message, list):
  58. print "message is list"
  59. tts_message = self._get_message_from_list(message)
  60. if isinstance(message, dict):
  61. print "message is dict"
  62. tts_message = self._get_message_from_dict(message)
  63. if message is not None:
  64. # get an instance of the target TTS
  65. tts_instance = self._get_tts_instance(self.tts)
  66. tts_args = SettingLoader().get_tts_args(self.tts)
  67. # change the cache settings with the one precised for the current neuron
  68. if self.override_cache:
  69. tts_args = self._update_cache_var(self.override_cache, tts_args)
  70. tts_instance.say(words=tts_message, **(tts_args if tts_args is not None else {}))
  71. @staticmethod
  72. def _get_message_from_list(message_list):
  73. """
  74. Return an element from the list randomly
  75. :param message_list:
  76. :return:
  77. """
  78. return random.choice(message_list)
  79. def _get_message_from_dict(self, message_dict):
  80. returned_message = None
  81. if (self.say_template is not None and self.file_template is None) or \
  82. (self.say_template is None and self.file_template is not None):
  83. # the user choose a say_template option
  84. if self.say_template is not None:
  85. if isinstance(self.say_template, list):
  86. # then we pick randomly one template
  87. self.say_template = random.choice(self.say_template)
  88. t = Template(self.say_template)
  89. returned_message = t.render(**message_dict)
  90. # the user choose a file_template option
  91. if self.file_template is not None: # the user choose a file_template option
  92. real_file_template_path = "templates/%s" % self.file_template
  93. if os.path.isfile(real_file_template_path):
  94. # load the content of the file as template
  95. t = Template(self._get_content_of_file(real_file_template_path))
  96. returned_message = t.render(**message_dict)
  97. else:
  98. raise TemplateFileNotFoundException("Template file %s not found in templates folder"
  99. % real_file_template_path)
  100. return returned_message
  101. else:
  102. raise NoTemplateException("You must specify a say_template or a file_template")
  103. @staticmethod
  104. def _get_content_of_file(real_file_template_path):
  105. with open(real_file_template_path, 'r') as content_file:
  106. return content_file.read()
  107. @staticmethod
  108. def _get_tts_instance(tts_name):
  109. # capitalise for loading module name
  110. tts = tts_name.capitalize()
  111. logger.debug("Import TTS module named %s " % tts)
  112. mod = __import__('tts', fromlist=[str(tts)])
  113. try:
  114. klass = getattr(mod, tts)
  115. except ImportError, e:
  116. raise TTSModuleNotFound("The TTS not found: %s" % e)
  117. if klass is not None:
  118. # run the plugin
  119. return klass()
  120. else:
  121. raise TTSNotInstantiable("TTS module %s not instantiable" % tts)
  122. @staticmethod
  123. def _update_cache_var(new_override_cache, args_list):
  124. print "args for TTS plugin before update: %s" % str(args_list)
  125. args_list["cache"] = new_override_cache
  126. print "args for TTS plugin after update: %s" % str(args_list)
  127. return args_list