48 from diagnostic_msgs.msg
import DiagnosticStatus, KeyValue, DiagnosticArray
49 from sound_play.msg
import SoundRequest, SoundRequestAction, SoundRequestResult, SoundRequestFeedback
79 def __init__(self, file, device, volume = 1.0):
80 self.
lock = threading.RLock()
90 elif os.path.isfile(file):
91 uri =
"file://" + os.path.abspath(file)
93 rospy.logerr(
'Error: URI is invalid: %s'%file)
146 rospy.logdebug(
"Playing %s"%self.
uri)
158 if cmd == SoundRequest.PLAY_STOP:
160 elif cmd == SoundRequest.PLAY_ONCE:
162 elif cmd == SoundRequest.PLAY_START:
179 if position != duration:
189 _feedback = SoundRequestFeedback()
190 _result = SoundRequestResult()
193 for sound
in dict.values():
202 if data.sound == SoundRequest.PLAY_FILE:
204 if not data.arg
in self.filesounds.keys():
205 rospy.logdebug(
'command for uncached wave: "%s"'%data.arg)
209 rospy.logerr(
'Error setting up to play "%s". Does this file exist on the machine on which sound_play is running?'%data.arg)
212 rospy.logdebug(
'command for cached wave: "%s"'%data.arg)
215 absfilename = os.path.join(roslib.packages.get_pkg_dir(data.arg2), data.arg)
216 if not absfilename
in self.filesounds.keys():
217 rospy.logdebug(
'command for uncached wave: "%s"'%absfilename)
221 rospy.logerr(
'Error setting up to play "%s" from package "%s". Does this file exist on the machine on which sound_play is running?'%(data.arg, data.arg2))
224 rospy.logdebug(
'command for cached wave: "%s"'%absfilename)
226 elif data.sound == SoundRequest.SAY:
227 if not data.arg
in self.voicesounds.keys():
228 rospy.logdebug(
'command for uncached text: "%s"' % data.arg)
229 txtfile = tempfile.NamedTemporaryFile(prefix=
'sound_play', suffix=
'.txt')
230 (wavfile,wavfilename) = tempfile.mkstemp(prefix=
'sound_play', suffix=
'.wav')
231 txtfilename=txtfile.name
235 txtfile.write(data.arg)
237 rospy.loginfo(
"text2wave -eval '("+voice+
")' "+txtfilename+
" -o "+wavfilename)
239 os.system("text2wave -eval '("+voice+")' "+txtfilename+" -o "+wavfilename) 241 if os.stat(wavfilename).st_size == 0: 242 raise OSError # So we hit the same catch block 244 rospy.logerr("text2wave -eval '("+voice+")' "+txtfilename+" -o "+wavfilename) 245 rospy.logerr('Sound synthesis failed. Is festival installed? Is a festival voice installed? Try running "rosdep satisfy sound_play|sh". Refer to http://wiki.ros.org/sound_play/Troubleshooting') 252 rospy.logdebug(
'command for cached text: "%s"'%data.arg)
255 rospy.logdebug(
'command for builtin wave: %i'%data.sound)
260 if sound.staleness != 0
and data.command != SoundRequest.PLAY_STOP:
262 rospy.logdebug(
"activating %i %s"%(data.sound,data.arg))
277 if data.sound == SoundRequest.ALL
and data.command == SoundRequest.PLAY_STOP:
281 sound.command(data.command)
283 rospy.logerr(
'Exception in callback: %s'%str(e))
284 rospy.loginfo(traceback.format_exc())
287 rospy.logdebug(
"done callback")
292 for (key,sound)
in dict.iteritems():
294 staleness = sound.get_staleness()
296 rospy.logerr(
'Exception in cleanupdict for sound (%s): %s'%(str(key),str(e)))
300 purgelist.append(key)
303 for key
in purgelist:
304 rospy.logdebug(
'Purging %s from cache'%key)
316 rospy.loginfo(
'Exception in cleanup: %s'%sys.exc_info()[0])
322 da = DiagnosticArray()
323 ds = DiagnosticStatus()
324 ds.name = rospy.get_caller_id().lstrip(
'/') +
": Node State" 326 ds.level = DiagnosticStatus.OK
328 ds.values.append(KeyValue(
"Active sounds", str(self.
active_sounds)))
329 ds.values.append(KeyValue(
"Allocated sound channels", str(self.
num_channels)))
330 ds.values.append(KeyValue(
"Buffered builtin sounds", str(len(self.
builtinsounds))))
331 ds.values.append(KeyValue(
"Buffered wave sounds", str(len(self.
filesounds))))
332 ds.values.append(KeyValue(
"Buffered voice sounds", str(len(self.
voicesounds))))
334 ds.level = DiagnosticStatus.WARN
335 ds.message =
"Sound device not open yet." 337 ds.level = DiagnosticStatus.ERROR
338 ds.message =
"Can't open sound device. See http://wiki.ros.org/sound_play/Troubleshooting" 340 da.header.stamp = rospy.get_rostime()
341 self.diagnostic_pub.publish(da)
343 rospy.loginfo(
'Exception in diagnostics: %s'%str(e))
346 data = data.sound_request
353 if data.sound == SoundRequest.ALL
and data.command == SoundRequest.PLAY_STOP:
357 sound.command(data.command)
360 start_time = rospy.get_rostime()
362 while sound.get_playing():
364 if self._as.is_preempt_requested():
365 rospy.loginfo(
'sound_play action: Preempted')
367 self._as.set_preempted()
371 self._feedback.playing = sound.get_playing()
372 self._feedback.stamp = rospy.get_rostime() - start_time
373 self._as.publish_feedback(self.
_feedback)
377 self._result.playing = self._feedback.playing
378 self._result.stamp = self._feedback.stamp
379 rospy.loginfo(
'sound_play action: Succeeded')
380 self._as.set_succeeded(self.
_result)
383 rospy.logerr(
'Exception in actionlib callback: %s'%str(e))
384 rospy.loginfo(traceback.format_exc())
387 rospy.logdebug(
"done actionlib callback")
390 rospy.init_node(
'sound_play')
391 self.
device = rospy.get_param(
"~device", str())
392 self.
diagnostic_pub = rospy.Publisher(
"/diagnostics", DiagnosticArray, queue_size=1)
393 rootdir = os.path.join(roslib.packages.get_pkg_dir(
'sound_play'),
'sounds')
396 SoundRequest.BACKINGUP : (os.path.join(rootdir,
'BACKINGUP.ogg'), 0.1),
397 SoundRequest.NEEDS_UNPLUGGING : (os.path.join(rootdir,
'NEEDS_UNPLUGGING.ogg'), 1),
398 SoundRequest.NEEDS_PLUGGING : (os.path.join(rootdir,
'NEEDS_PLUGGING.ogg'), 1),
399 SoundRequest.NEEDS_UNPLUGGING_BADLY : (os.path.join(rootdir,
'NEEDS_UNPLUGGING_BADLY.ogg'), 1),
400 SoundRequest.NEEDS_PLUGGING_BADLY : (os.path.join(rootdir,
'NEEDS_PLUGGING_BADLY.ogg'), 1),
408 sub = rospy.Subscriber(
"robotsound", SoundRequest, self.
callback)
416 while not rospy.is_shutdown():
417 while not rospy.is_shutdown():
427 rospy.loginfo(
'Exception in idle_loop: %s'%sys.exc_info()[0])
441 rospy.loginfo(
'sound_play node is ready to play sound')
445 rospy.sleep(duration)
446 except rospy.exceptions.ROSInterruptException:
453 and not rospy.is_shutdown():
460 if __name__ ==
'__main__':
def cleanupdict(self, dict)
def sleep(self, duration)
def diagnostics(self, state)
def execute_cb(self, data)
def select_sound(self, data)
def __init__(self, file, device, volume=1.0)