3
3
# =============================================================================
4
4
# >> FORWARD IMPORTS
5
5
# =============================================================================
6
+ # Python Imports
7
+ # Inspect
8
+ from inspect import getmodule
9
+ from inspect import stack
10
+
6
11
# Source.Python Imports
12
+ from core import AutoUnload
7
13
# Engines
8
14
from _engines import EngineSound
9
15
from _engines import Channels
21
27
from _engines import PITCH_HIGH
22
28
from _engines import SOUND_FROM_LOCAL_PLAYER
23
29
from _engines import SOUND_FROM_WORLD
30
+ # Filters
31
+ from filters .recipients import RecipientFilter
32
+ # Mathlib
33
+ from mathlib import NULL_VECTOR
34
+ # Paths
35
+ from paths import PLUGIN_PATH
36
+ # Stringtables
37
+ from stringtables .downloads import Downloadables
24
38
25
39
26
40
# =============================================================================
32
46
'EngineSound' ,
33
47
'SOUND_FROM_LOCAL_PLAYER' ,
34
48
'SOUND_FROM_WORLD' ,
49
+ 'Sound' ,
35
50
'SoundFlags' ,
36
51
'VOL_NORM' ,
37
52
]
43
58
class Attenuations (object ):
44
59
'''Attenuation values wrapper enumerator.
45
60
46
- TODO: Inherit of "enum.IntEnum" once we have upgraded to Python 3.4+.
47
- '''
61
+ TODO: Inherit of "enum.IntEnum" once we have upgraded to Python 3.4+.
62
+ '''
48
63
NONE = ATTN_NONE
49
64
NORMAL = ATTN_NORM
50
65
IDLE = ATTN_IDLE
@@ -57,8 +72,130 @@ class Attenuations(object):
57
72
class PitchTypes (object ):
58
73
'''Pitch values wrapper enumerator.
59
74
60
- TODO: Inherit of "enum.IntEnum" once we have upgraded to Python 3.4+.
61
- '''
75
+ TODO: Inherit of "enum.IntEnum" once we have upgraded to Python 3.4+.
76
+ '''
62
77
NORMAL = PITCH_NORM
63
78
LOW = PITCH_LOW
64
79
HIGH = PITCH_HIGH
80
+
81
+
82
+ class Sound (AutoUnload ):
83
+ '''Class used to interact with a specific sound file'''
84
+
85
+ # Set the base _downloads attribute to know whether
86
+ # or not the sample was added to the downloadables
87
+ _downloads = None
88
+
89
+ def __init__ (
90
+ self , recipients , index , sample , volume = VOL_NORM ,
91
+ attenuation = Attenuations .NONE , channel = Channels .AUTO ,
92
+ flags = 0 , pitch = PitchTypes .HIGH , origin = NULL_VECTOR ,
93
+ direction = NULL_VECTOR , origins = (), update_positions = True ,
94
+ sound_time = 0.0 , speaker_entity = - 1 , download = False ):
95
+ '''Store all the given attributes and set the module for unloading'''
96
+
97
+ # Get the file that called
98
+ caller = getmodule (stack ()[1 ][0 ])
99
+
100
+ # Is the calling file in a plugin?
101
+ if PLUGIN_PATH in caller .__file__ :
102
+
103
+ # Set the module to the plugin's module so that
104
+ # _unload_instance will fire when the plugin is unloaded
105
+ self .__module__ = caller .__name__
106
+
107
+ # Set sample as a private attribute, since it should never change
108
+ self ._sample = sample
109
+
110
+ # Set all the base attributes
111
+ self .recipients = recipients
112
+ self .index = index
113
+ self .volume = volume
114
+ self .attenuation = attenuation
115
+ self .channel = channel
116
+ self .flags = flags
117
+ self .pitch = pitch
118
+ self .origin = origin
119
+ self .direction = direction
120
+ self .origins = origins
121
+ self .update_positions = update_positions
122
+ self .sound_time = sound_time
123
+ self .speaker_entity = speaker_entity
124
+
125
+ # Should the sample be downloaded by clients?
126
+ if download :
127
+
128
+ # Get the file that called
129
+ caller = getmodule (stack ()[1 ][0 ])
130
+
131
+ # Is the calling file in a plugin?
132
+ if PLUGIN_PATH in caller .__file__ :
133
+
134
+ # Set the module to the plugin's module so that
135
+ # _unload_instance will fire when the plugin is unloaded
136
+ self .__module__ = caller .__name__
137
+
138
+ # Add the sample to Downloadables
139
+ self ._downloads = Downloadables ()
140
+ self ._downloads .add ('sound/{0}' .format (self .sample ))
141
+
142
+ def play (self , * recipients ):
143
+ '''Plays the sound using either the given
144
+ recipients or the instance's recipients'''
145
+
146
+ # Get the recipients to play the sound to
147
+ recipients = RecipientFilter (* (recipients or self .recipients ))
148
+
149
+ # Is the sound precached?
150
+ if not self .is_precached ():
151
+
152
+ # Precache the sound
153
+ self .precache ()
154
+
155
+ # Play the sound
156
+ EngineSound .emit_sound (
157
+ recipients , self .index , self .channel , self .sample ,
158
+ self .volume , self .attenuation , self .flags , self .pitch ,
159
+ self .origin , self .direction , self .origins ,
160
+ self .update_positions , self .sound_time , self .speaker_entity )
161
+
162
+ def stop (self , index = None , channel = None ):
163
+ '''Stops a sound from being played'''
164
+
165
+ # Was an index passed in?
166
+ if index is None :
167
+
168
+ # Use the instance's index
169
+ index = self .index
170
+
171
+ # Was a channel passed in?
172
+ if channel is None :
173
+
174
+ # Use the instance's index
175
+ channel = self .channel
176
+
177
+ # Stop the sound
178
+ EngineSound .stop_sound (index , channel , self .sample )
179
+
180
+ def precache (self ):
181
+ '''Precaches the sample'''
182
+ EngineSound .precache_sound (self .sample )
183
+
184
+ def is_precached (self ):
185
+ '''Returns whether or not the sample is precached'''
186
+ return EngineSound .is_sound_precached (self .sample )
187
+
188
+ @property
189
+ def sample (self ):
190
+ '''Returns the sample (filename) of the Sound instance'''
191
+ return self ._sample
192
+
193
+ @property
194
+ def duration (self ):
195
+ '''Returns the duration of the sample'''
196
+ return EngineSound .get_sound_duration (self .sample )
197
+
198
+ def _unload_instance (self ):
199
+ '''Removes the sample from the downloads list'''
200
+ if not self ._downloads is None :
201
+ self ._downloads ._unload_instance ()
0 commit comments