1# Copyright 2004-2021 Tom Rothamel <pytom@bishoujo.us>
2#
3# Permission is hereby granted, free of charge, to any person
4# obtaining a copy of this software and associated documentation files
5# (the "Software"), to deal in the Software without restriction,
6# including without limitation the rights to use, copy, modify, merge,
7# publish, distribute, sublicense, and/or sell copies of the Software,
8# and to permit persons to whom the Software is furnished to do so,
9# subject to the following conditions:
10#
11# The above copyright notice and this permission notice shall be
12# included in all copies or substantial portions of the Software.
13#
14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22init -1500 python:
23
24    ##########################################################################
25    # Audio actions.
26
27    @renpy.pure
28    class Play(Action, FieldEquality):
29        """
30         :doc: audio_action
31
32         Causes an audio file to be played on a given channel.
33
34         `channel`
35             The channel to play the sound on.
36         `file`
37             The file to play.
38         `selected`
39             If True, buttons using this action will be marked as selected
40             if the file is playing on the channel. If False, this action
41             will not cause the button to start playing. If None, the button
42             is marked selected if the channel is a music channel, and not
43             otherwise.
44
45         Any other keyword arguments are passed to :func:`renpy.music.play`.
46         """
47
48        equality_fields = ["channel", "file", "kwargs", "can_be_selected" ]
49
50        can_be_selected = False
51
52        def __init__(self, channel, file, selected=None, **kwargs):
53            self.channel = channel
54            self.file = file
55            self.kwargs = kwargs
56
57            if selected is None:
58                selected = renpy.music.is_music(channel)
59
60            self.can_be_selected = selected
61            self.get_selected()
62
63        def __call__(self):
64            renpy.music.play(self.file, channel=self.channel, **self.kwargs)
65            renpy.restart_interaction()
66
67        def get_selected(self):
68            if not self.can_be_selected:
69                self.selected = False
70                return False
71
72            self.selected = (renpy.music.get_playing(self.channel) == self.file)
73            return self.selected
74
75        def periodic(self, st):
76            if not self.can_be_selected:
77                return None
78
79            if self.selected != (renpy.music.get_playing(self.channel) == self.file):
80                renpy.restart_interaction()
81
82            return .1
83
84
85    @renpy.pure
86    class Queue(Action, DictEquality):
87        """
88         :doc: audio_action
89
90         Causes an audio file to be queued on a given channel.
91
92         `channel`
93             The channel to play the sound on.
94         `file`
95             The file to play.
96
97         Any keyword arguments are passed to :func:`renpy.music.queue`
98         """
99
100        def __init__(self, channel, file, **kwargs):
101            self.channel = channel
102            self.file = file
103            self.kwargs = kwargs
104
105        def __call__(self):
106            renpy.music.queue(self.file, channel=self.channel, **self.kwargs)
107            renpy.restart_interaction()
108
109    @renpy.pure
110    class Stop(Action, DictEquality):
111        """
112         :doc: audio_action
113
114         Causes an audio channel to be stopped.
115
116         `channel`
117             The channel to stop the sound on.
118
119         Any keyword arguments are passed to :func:`renpy.music.stop`
120         """
121
122        def __init__(self, channel, **kwargs):
123            self.channel = channel
124            self.kwargs = kwargs
125
126        def __call__(self):
127            renpy.music.stop(channel=self.channel, **self.kwargs)
128            renpy.restart_interaction()
129
130    @renpy.pure
131    class SetMixer(Action, DictEquality):
132        """
133        :doc: audio_action
134
135        Sets the volume of `mixer` to `value`.
136
137        `mixer`
138            The mixer to set the volume of. A string, usually one of
139            "music", "sfx", or "voice".
140        `value`
141            The value to set the volume to. A number between 0.0 and 1.0,
142            inclusive.
143        """
144
145        def __init__(self, mixer, volume):
146            self.mixer = mixer
147            self.volume = volume
148
149        def __call__(self):
150            _preferences.set_volume(self.mixer, self.volume)
151            renpy.restart_interaction()
152
153        def get_selected(self):
154            return _preferences.get_volume(self.mixer) == self.volume
155
156    @renpy.pure
157    class SetMute(Action, DictEquality):
158        """
159        :doc: audio_action
160
161        Sets the mute status of one or more mixers. When a mixer is muted,
162        audio channels associated with that mixer will stop playing audio.
163
164        `mixer`
165            Either a single string giving a mixer name, or a list of strings
166            giving a list of mixers. The strings should be mixer names, usually
167            "music", "sfx", or "voice".
168
169        `mute`
170            True to mute the mixer, False to ummute it.
171        """
172
173
174        def __init__(self, mixer, mute):
175            if isinstance(mixer, basestring):
176                mixer = [ mixer ]
177
178            self.mixers = mixer
179            self.mute = mute
180
181        def __call__(self):
182            for i in self.mixers:
183                _preferences.set_mute(i, self.mute)
184
185            renpy.restart_interaction()
186
187        def get_selected(self):
188            for i in self.mixers:
189                if _preferences.get_mute(i) != self.mute:
190                    return False
191
192            return True
193
194    @renpy.pure
195    class ToggleMute(Action, DictEquality):
196        """
197        :doc: audio_action
198
199        Toggles the mute status of one or more mixers.
200
201        `mixer`
202            Either a single string giving a mixer name, or a list of strings
203            giving a list of mixers. The strings should be mixer names, usually
204            "music", "sfx", or "voice".
205        """
206
207
208        def __init__(self, mixer):
209            if isinstance(mixer, basestring):
210                mixer = [ mixer ]
211
212            self.mixers = mixer
213
214        def __call__(self):
215            mute = not self.get_selected()
216
217            for i in self.mixers:
218                _preferences.set_mute(i, mute)
219
220            renpy.restart_interaction()
221
222        def get_selected(self):
223            for i in self.mixers:
224                if not _preferences.get_mute(i):
225                    return False
226
227            return True
228
229
230    @renpy.pure
231    class PauseAudio(Action, DictEquality):
232        """
233        :doc: audio_action
234
235        Sets the pause flag for `channel`.
236
237        If `value` is True, the channel is paused. If False, the channel is
238        unpaused. If "toggle", the pause flag will be toggled.
239        """
240
241
242        def __init__(self, channel, value=True):
243            self.channel = channel
244            self.value = value
245
246        def __call__(self):
247            if self.value == "toggle":
248                renpy.music.set_pause(not renpy.music.get_pause(self.channel), channel=self.channel)
249            else:
250                renpy.music.set_pause(self.value, channel=self.channel)
251
252            renpy.restart_interaction()
253
254        def get_selected(self):
255            rv = renpy.music.get_pause(channel=self.channel)
256
257            if not self.value:
258                rv = not rv
259
260            return rv
261
262