libsoundplay.py
Go to the documentation of this file.
1 #***********************************************************
2 #* Software License Agreement (BSD License)
3 #*
4 #* Copyright (c) 2009, Willow Garage, Inc.
5 #* All rights reserved.
6 #*
7 #* Redistribution and use in source and binary forms, with or without
8 #* modification, are permitted provided that the following conditions
9 #* are met:
10 #*
11 #* * Redistributions of source code must retain the above copyright
12 #* notice, this list of conditions and the following disclaimer.
13 #* * Redistributions in binary form must reproduce the above
14 #* copyright notice, this list of conditions and the following
15 #* disclaimer in the documentation and/or other materials provided
16 #* with the distribution.
17 #* * Neither the name of the Willow Garage nor the names of its
18 #* contributors may be used to endorse or promote products derived
19 #* from this software without specific prior written permission.
20 #*
21 #* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 #* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 #* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 #* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 #* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 #* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 #* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 #* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 #* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 #* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 #* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 #* POSSIBILITY OF SUCH DAMAGE.
33 #***********************************************************
34 
35 # Author: Blaise Gassend
36 
37 import rospy
38 import roslib
39 import actionlib
40 import os, sys
41 from sound_play.msg import SoundRequest
42 from sound_play.msg import SoundRequestGoal
43 from sound_play.msg import SoundRequestAction
44 
45 ## \brief Class that publishes messages to the sound_play node.
46 
55 
56 class Sound(object):
57  def __init__(self, client, snd, arg, volume=1.0):
58  self.client = client
59  self.snd = snd
60  self.arg = arg
61  self.vol = volume
62 
63 ## \brief Play the Sound.
64 
66 
67  def play(self, **kwargs):
68  self.client.sendMsg(self.snd, SoundRequest.PLAY_ONCE, self.arg,
69  vol=self.vol, **kwargs)
70 
71 ## \brief Play the Sound repeatedly.
72 
75 
76  def repeat(self, **kwargs):
77  self.client.sendMsg(self.snd, SoundRequest.PLAY_START, self.arg,
78  vol=self.vol, **kwargs)
79 
80 ## \brief Stop Sound playback.
81 
83 
84  def stop(self):
85  self.client.sendMsg(self.snd, SoundRequest.PLAY_STOP, self.arg)
86 
87 ## This class is a helper class for communicating with the sound_play node
88 ## via the \ref sound_play.SoundRequest message. There is a one-to-one mapping
89 ## between methods and invocations of the \ref sound_play.SoundRequest message.
90 
91 class SoundClient(object):
92 
93  def __init__(self, blocking=False, sound_action='sound_play', sound_topic='robotsound'):
94  """
95 
96  The SoundClient can send SoundRequests in two modes: non-blocking mode
97  (by publishing a message to the soundplay_node directly) which will
98  return as soon as the sound request has been sent, or blocking mode (by
99  using the actionlib interface) which will wait until the sound has
100  finished playing completely.
101 
102  The blocking parameter here is the standard behavior, but can be
103  over-ridden. Each say/play/start/repeat method can take in an optional
104  `blocking=True|False` argument that will over-ride the class-wide
105  behavior. See soundclient_example.py for an example of this behavior.
106 
107  :param blocking: Used as the default behavior unless over-ridden,
108  (default = false)
109 
110  :param sound_action: Namespace of actionlib to play sound. The actionlib interface is used
111  only if blocking parameter is True. (default='sound_play')
112 
113  :param sound_topic: Topic name to play sound. The topic interface is used only if blocking
114  parameter is False. (default='robotsound')
115  """
116 
117  self._blocking = blocking
118 
119  # NOTE: only one of these will be used at once, but we need to create
120  # both the publisher and actionlib client here.
122  sound_action, SoundRequestAction)
123  self.pub = rospy.Publisher(sound_topic, SoundRequest, queue_size=5)
124 
125 ## \brief Create a voice Sound.
126 
130 
131  def voiceSound(self, s, volume=1.0):
132  return Sound(self, SoundRequest.SAY, s, volume=volume)
133 
134 ## \brief Create a wave Sound.
135 
140  def waveSound(self, sound, volume=1.0):
141  if sound[0] != "/":
142  rootdir = os.path.join(roslib.packages.get_pkg_dir('sound_play'),'sounds')
143  sound = rootdir + "/" + sound
144  return Sound(self, SoundRequest.PLAY_FILE, sound, volume=volume)
145 
146 ## \brief Create a builtin Sound.
147 
151 
152  def builtinSound(self, id, volume=1.0):
153  return Sound(self, id, "", volume)
154 
155 ## \brief Say a string
156 
161 
162  def say(self,text, voice='', volume=1.0, **kwargs):
163  self.sendMsg(SoundRequest.SAY, SoundRequest.PLAY_ONCE, text, voice,
164  volume, **kwargs)
165 
166 ## \brief Say a string repeatedly
167 
171 
172  def repeat(self,text, volume=1.0, **kwargs):
173  self.sendMsg(SoundRequest.SAY, SoundRequest.PLAY_START, text,
174  vol=volume, **kwargs)
175 
176 ## \brief Stop saying a string
177 
182 
183  def stopSaying(self,text):
184  self.sendMsg(SoundRequest.SAY, SoundRequest.PLAY_STOP, text)
185 
186 ## \brief Plays a WAV or OGG file
187 
193 
194  def playWave(self, sound, volume=1.0, **kwargs):
195  if sound[0] != "/":
196  rootdir = os.path.join(roslib.packages.get_pkg_dir('sound_play'),'sounds')
197  sound = rootdir + "/" + sound
198  self.sendMsg(SoundRequest.PLAY_FILE, SoundRequest.PLAY_ONCE, sound,
199  vol=volume, **kwargs)
200 
201 ## \brief Plays a WAV or OGG file repeatedly
202 
207 
208  def startWave(self, sound, volume=1.0, **kwargs):
209  if sound[0] != "/":
210  rootdir = os.path.join(roslib.packages.get_pkg_dir('sound_play'),'sounds')
211  sound = rootdir + "/" + sound
212  self.sendMsg(SoundRequest.PLAY_FILE, SoundRequest.PLAY_START, sound,
213  vol=volume, **kwargs)
214 
215 ## \brief Stop playing a WAV or OGG file
216 
221 
222  def stopWave(self,sound):
223  if sound[0] != "/":
224  rootdir = os.path.join(roslib.package.get_pkg_dir('sound_play'),'sounds')
225  sound = rootdir + "/" + sound
226  self.sendMsg(SoundRequest.PLAY_FILE, SoundRequest.PLAY_STOP, sound)
227 
228 ## \brief Plays a WAV or OGG file
229 
236 
237  def playWaveFromPkg(self, package, sound, volume=1.0, **kwargs):
238  self.sendMsg(SoundRequest.PLAY_FILE, SoundRequest.PLAY_ONCE, sound, package,
239  volume, **kwargs)
240 
241 ## \brief Plays a WAV or OGG file repeatedly
242 
248 
249  def startWaveFromPkg(self, package, sound, volume=1.0, **kwargs):
250  self.sendMsg(SoundRequest.PLAY_FILE, SoundRequest.PLAY_START, sound,
251  package, volume, **kwargs)
252 
253 ## \brief Stop playing a WAV or OGG file
254 
261 
262  def stopWaveFromPkg(self,sound, package):
263  self.sendMsg(SoundRequest.PLAY_FILE, SoundRequest.PLAY_STOP, sound, package)
264 
265 ## \brief Play a buildin sound
266 
271 
272  def play(self,sound, volume=1.0, **kwargs):
273  self.sendMsg(sound, SoundRequest.PLAY_ONCE, "", vol=volume, **kwargs)
274 
275 ## \brief Play a buildin sound repeatedly
276 
281 
282  def start(self,sound, volume=1.0, **kwargs):
283  self.sendMsg(sound, SoundRequest.PLAY_START, "", vol=volume, **kwargs)
284 
285 ## \brief Stop playing a built-in sound
286 
290 
291  def stop(self,sound):
292  self.sendMsg(sound, SoundRequest.PLAY_STOP, "")
293 
294 ## \brief Stop all currently playing sounds
295 
297 
298  def stopAll(self):
299  self.stop(SoundRequest.ALL)
300 
301  def sendMsg(self, snd, cmd, s, arg2="", vol=1.0, **kwargs):
302  """
303  Internal method that publishes the sound request, either directly as a
304  SoundRequest to the soundplay_node or through the actionlib interface
305  (which blocks until the sound has finished playing).
306 
307  The blocking behavior is nominally the class-wide setting unless it has
308  been explicitly specified in the play call.
309  """
310 
311  # Use the passed-in argument if it exists, otherwise fall back to the
312  # class-wide setting.
313  blocking = kwargs.get('blocking', self._blocking)
314 
315  msg = SoundRequest()
316  msg.sound = snd
317  # Threshold volume between 0 and 1.
318  msg.volume = max(0, min(1, vol))
319  msg.command = cmd
320  msg.arg = s
321  msg.arg2 = arg2
322 
323  rospy.logdebug('Sending sound request with volume = {}'
324  ' and blocking = {}'.format(msg.volume, blocking))
325 
326  # Defensive check for the existence of the correct communicator.
327  if not blocking and not self.pub:
328  rospy.logerr('Publisher for SoundRequest must exist')
329  return
330  if blocking and not self.actionclient:
331  rospy.logerr('Action client for SoundRequest does not exist.')
332  return
333 
334  if not blocking: # Publish message directly and return immediately
335  self.pub.publish(msg)
336  if self.pub.get_num_connections() < 1:
337  rospy.logwarn("Sound command issued, but no node is subscribed"
338  " to the topic. Perhaps you forgot to run"
339  " soundplay_node.py?")
340  else: # Block until result comes back.
341  assert self.actionclient, 'Actionclient must exist'
342  rospy.logdebug('Sending action client sound request [blocking]')
343  self.actionclient.wait_for_server()
344  goal = SoundRequestGoal()
345  goal.sound_request = msg
346  self.actionclient.send_goal(goal)
347  self.actionclient.wait_for_result()
348  rospy.logdebug('sound request response received')
349 
350  return
def start(self, sound, volume=1.0, kwargs)
Play a buildin sound repeatedly.
def repeat(self, kwargs)
Play the Sound repeatedly.
Definition: libsoundplay.py:76
def waveSound(self, sound, volume=1.0)
Create a wave Sound.
def say(self, text, voice='', volume=1.0, kwargs)
Say a string.
def startWave(self, sound, volume=1.0, kwargs)
Plays a WAV or OGG file repeatedly.
def stopWave(self, sound)
Stop playing a WAV or OGG file.
def stopWaveFromPkg(self, sound, package)
Stop playing a WAV or OGG file.
def __init__(self, client, snd, arg, volume=1.0)
Definition: libsoundplay.py:57
def startWaveFromPkg(self, package, sound, volume=1.0, kwargs)
Plays a WAV or OGG file repeatedly.
def stop(self)
Stop Sound playback.
Definition: libsoundplay.py:84
def __init__(self, blocking=False, sound_action='sound_play', sound_topic='robotsound')
Definition: libsoundplay.py:93
def sendMsg(self, snd, cmd, s, arg2="", vol=1.0, kwargs)
def voiceSound(self, s, volume=1.0)
Create a voice Sound.
def builtinSound(self, id, volume=1.0)
Create a builtin Sound.
def stopAll(self)
Stop all currently playing sounds.
def playWaveFromPkg(self, package, sound, volume=1.0, kwargs)
Plays a WAV or OGG file.
def play(self, kwargs)
Play the Sound.
Definition: libsoundplay.py:67
def playWave(self, sound, volume=1.0, kwargs)
Plays a WAV or OGG file.
def stopSaying(self, text)
Stop saying a string.
This class is a helper class for communicating with the sound_play node via the sound_play.SoundRequest message.
Definition: libsoundplay.py:91
Class that publishes messages to the sound_play node.
Definition: libsoundplay.py:56


sound_play
Author(s): Blaise Gassend
autogenerated on Fri Nov 6 2020 03:42:10