48 from diagnostic_msgs.msg 
import DiagnosticArray
 
   49 from diagnostic_msgs.msg 
import DiagnosticStatus
 
   50 from diagnostic_msgs.msg 
import KeyValue
 
   51 from sound_play.msg 
import SoundRequest
 
   52 from sound_play.msg 
import SoundRequestAction
 
   53 from sound_play.msg 
import SoundRequestFeedback
 
   54 from sound_play.msg 
import SoundRequestResult
 
   59     gi.require_version(
'Gst', 
'1.0')
 
   60     from gi.repository 
import GObject 
as GObject
 
   61     from gi.repository 
import Gst 
as Gst
 
   64 ************************************************************** 
   65 Error opening pygst. Is gstreamer installed? 
   66 ************************************************************** 
   74     _feedback = SoundRequestFeedback()
 
   75     _result = SoundRequestResult()
 
   78         for sound 
in dict.values():
 
   87         if data.sound == SoundRequest.PLAY_FILE:
 
   91                         'command for uncached wave: "%s"' % data.arg)
 
   94                             data.arg, self.
device, data.volume)
 
   97                             'Error setting up to play "%s".' 
   98                             'Does this file exist on the machine' 
   99                             'on which sound_play is running?' % data.arg)
 
  102                     rospy.logdebug(
'command for cached wave: "%s"' % data.arg)
 
  104                     if filesound.sound.get_property(
'volume') != data.volume:
 
  106                             'volume for cached wave has changed,' 
  108                         filesound.sound.set_property(
'volume', data.volume)
 
  111                 absfilename = os.path.join(
 
  112                     roslib.packages.get_pkg_dir(data.arg2), data.arg)
 
  115                         'command for uncached wave: "%s"' % absfilename)
 
  118                             absfilename, self.
device, data.volume)
 
  121                             'Error setting up to play "%s" from package "%s".' 
  122                             'Does this file exist on the machine ' 
  123                             'on which sound_play is running?' 
  124                             % (data.arg, data.arg2))
 
  128                         'command for cached wave: "%s"' % absfilename)
 
  130                     if filesound.sound.get_property(
'volume') != data.volume:
 
  132                             'volume for cached wave has changed,' 
  134                         filesound.sound.set_property(
'volume', data.volume)
 
  136         elif data.sound == SoundRequest.SAY:
 
  137             voice_key = data.arg + 
'---' + data.arg2
 
  139                 rospy.logdebug(
'command for uncached text: "%s"' % voice_key)
 
  142                         'Plugin is not found {}.'.format(self.
plugin_name))
 
  148                     wavfilename = self.
plugin.sound_play_say_plugin(
 
  150                     if wavfilename 
is None:
 
  151                         rospy.logerr(
'Failed to generate wavfile.')
 
  154                             wavfilename, self.
device, data.volume)
 
  156                 rospy.logdebug(
'command for cached text: "%s"' % voice_key)
 
  158                 if voicesound.sound.get_property(
'volume') != data.volume:
 
  160                         'volume for cached text has changed, resetting volume')
 
  161                     voicesound.sound.set_property(
'volume', data.volume)
 
  164             rospy.logdebug(
'command for builtin wave: %i' % data.sound)
 
  172                     volume = (volume + params[1])/2
 
  174                     params[0], self.
device, volume)
 
  176         if sound.staleness != 0 
and data.command != SoundRequest.PLAY_STOP:
 
  178             rospy.logdebug(
"activating %i %s" % (data.sound, data.arg))
 
  188             if (data.sound == SoundRequest.ALL
 
  189                     and data.command == SoundRequest.PLAY_STOP):
 
  193                 sound.command(data.command)
 
  194         except Exception 
as e:
 
  195             rospy.logerr(
'Exception in callback: %s' % 
str(e))
 
  196             rospy.loginfo(traceback.format_exc())
 
  199             rospy.logdebug(
"done callback")
 
  204         for key, sound 
in iter(dict.items()):
 
  206                 staleness = sound.get_staleness()
 
  207             except Exception 
as e:
 
  209                     'Exception in cleanupdict for sound (%s): %s' 
  215                 purgelist.append(key)
 
  219         for key 
in purgelist:
 
  220             rospy.logdebug(
'Purging %s from cache' % key)
 
  234                 'Exception in cleanup: %s' % sys.exc_info()[0])
 
  240             da = DiagnosticArray()
 
  241             ds = DiagnosticStatus()
 
  242             ds.name = rospy.get_caller_id().lstrip(
'/') + 
": Node State" 
  244                 ds.level = DiagnosticStatus.OK
 
  250                         "Allocated sound channels",
 
  254                         "Buffered builtin sounds",
 
  258                         "Buffered wave sounds",
 
  262                         "Buffered voice sounds",
 
  265                 ds.level = DiagnosticStatus.WARN
 
  266                 ds.message = 
"Sound device not open yet." 
  268                 ds.level = DiagnosticStatus.ERROR
 
  269                 ds.message = 
"Can't open sound device." +\
 
  270                     "See http://wiki.ros.org/sound_play/Troubleshooting" 
  272             da.header.stamp = rospy.get_rostime()
 
  274         except Exception 
as e:
 
  275             rospy.loginfo(
'Exception in diagnostics: %s' % 
str(e))
 
  278         data = data.sound_request
 
  280             rospy.logerr(
'soundplay_node is not initialized yet.')
 
  281             self.
_as.set_aborted()
 
  287             if (data.sound == SoundRequest.ALL
 
  288                     and data.command == SoundRequest.PLAY_STOP):
 
  292                 sound.command(data.command)
 
  295                 start_time = rospy.get_rostime()
 
  297                 while sound.get_playing():
 
  299                     if self.
_as.is_preempt_requested():
 
  300                         rospy.loginfo(
'sound_play action: Preempted')
 
  302                         self.
_as.set_preempted()
 
  306                     self.
_feedback.playing = sound.get_playing()
 
  307                     self.
_feedback.stamp = rospy.get_rostime() - start_time
 
  314                     rospy.loginfo(
'sound_play action: Succeeded')
 
  317         except Exception 
as e:
 
  318             self.
_as.set_aborted()
 
  320                 'Exception in actionlib callback: %s' % 
str(e))
 
  321             rospy.loginfo(traceback.format_exc())
 
  324             rospy.logdebug(
"done actionlib callback")
 
  330         GObject.threads_init()
 
  331         self.
g_loop = threading.Thread(target=GObject.MainLoop().run)
 
  335         rospy.init_node(
'sound_play')
 
  337         self.
device = rospy.get_param(
"~device", 
"default")
 
  340             '~plugin', 
'sound_play/festival_plugin')
 
  342             "/diagnostics", DiagnosticArray, queue_size=1)
 
  343         rootdir = os.path.join(
 
  344             roslib.packages.get_pkg_dir(
'sound_play'), 
'sounds')
 
  347         rospack = rospkg.RosPack()
 
  348         depend_pkgs = rospack.get_depends_on(
'sound_play', implicit=
False)
 
  349         depend_pkgs = [
'sound_play'] + depend_pkgs
 
  350         rospy.loginfo(
"Loading from plugin definitions")
 
  352         for depend_pkg 
in depend_pkgs:
 
  353             manifest = rospack.get_manifest(depend_pkg)
 
  354             plugin_yaml = manifest.get_export(
'sound_play', 
'plugin')
 
  355             if len(plugin_yaml) != 0:
 
  356                 plugin_yamls += plugin_yaml
 
  357                 for plugin_y 
in plugin_yaml:
 
  358                     rospy.logdebug(
'Loading plugin in {}'.format(plugin_y))
 
  360         for plugin_yaml 
in plugin_yamls:
 
  361             if not os.path.exists(plugin_yaml):
 
  363                     'Failed to load plugin yaml: {}'.format(plugin_yaml))
 
  365                     'Missing plugin yaml: {}'.format(plugin_yaml))
 
  367             with open(plugin_yaml) 
as f:
 
  368                 plugin_descs = yaml.safe_load(f)
 
  369             for plugin_desc 
in plugin_descs:
 
  370                 plugin_dict[plugin_desc[
'name']] = plugin_desc[
'module']
 
  375             mod = __import__(plugin_module.split(
'.')[0])
 
  376             for sub_mod 
in plugin_module.split(
'.')[1:]:
 
  377                 mod = getattr(mod, sub_mod)
 
  381             SoundRequest.BACKINGUP: (
 
  382                 os.path.join(rootdir, 
'BACKINGUP.ogg'), 0.1),
 
  383             SoundRequest.NEEDS_UNPLUGGING: (
 
  384                 os.path.join(rootdir, 
'NEEDS_UNPLUGGING.ogg'), 1),
 
  385             SoundRequest.NEEDS_PLUGGING: (
 
  386                 os.path.join(rootdir, 
'NEEDS_PLUGGING.ogg'), 1),
 
  387             SoundRequest.NEEDS_UNPLUGGING_BADLY: (
 
  388                 os.path.join(rootdir, 
'NEEDS_UNPLUGGING_BADLY.ogg'), 1),
 
  389             SoundRequest.NEEDS_PLUGGING_BADLY: (
 
  390                 os.path.join(rootdir, 
'NEEDS_PLUGGING_BADLY.ogg'), 1),
 
  398         self.
sub = rospy.Subscriber(
"robotsound", SoundRequest, self.
callback)
 
  400             'sound_play', SoundRequestAction,
 
  408         while not rospy.is_shutdown():
 
  409             while not rospy.is_shutdown():
 
  414                 if not self.
_as.action_server.started:
 
  422                         'Exception in idle_loop: %s' % sys.exc_info()[0])
 
  436             rospy.loginfo(
'sound_play node is ready to play sound')
 
  440             rospy.sleep(duration)
 
  441         except rospy.exceptions.ROSInterruptException:
 
  451         while (
not rospy.is_shutdown()
 
  461 if __name__ == 
'__main__':