Music Control Demo

music_control_demo.py
1"""
2If Python and Arcade are installed, this example can be run from the command line with:
3python -m arcade.examples.music_control_demo
4"""
5import arcade
6import arcade.gui
7import arcade.gui.widgets.buttons
8import arcade.gui.widgets.layout
9
10
11class GameView(arcade.View):
12 def __init__(self):
13 super().__init__()
14
15 self.media_player = None
16 self.paused = True
17 self.songs = [":resources:music/funkyrobot.mp3",
18 ":resources:music/1918.mp3"]
19 self.cur_song_index = 0
20
21 self.my_music = arcade.load_sound(self.songs[self.cur_song_index])
22
23 # This creates a "manager" for all our UI elements
24 self.ui_manager = arcade.gui.UIManager(self.window)
25
26 box = arcade.gui.widgets.layout.UIBoxLayout(vertical=False, space_between=20)
27
28 # --- Start button
29 normal_texture = arcade.load_texture(
30 ":resources:onscreen_controls/flat_dark/sound_off.png"
31 )
32 hover_texture = arcade.load_texture(
33 ":resources:onscreen_controls/shaded_dark/sound_off.png"
34 )
35 press_texture = arcade.load_texture(
36 ":resources:onscreen_controls/shaded_dark/sound_off.png"
37 )
38
39 # Create our button
40 self.start_button = arcade.gui.widgets.buttons.UITextureButton(
41 texture=normal_texture,
42 texture_hovered=hover_texture,
43 texture_pressed=press_texture,
44 )
45
46 # Map that button's on_click method to this view's on_button_click method.
47 self.start_button.on_click = self.start_button_clicked # type: ignore
48
49 # Add in our element.
50 box.add(self.start_button)
51
52 # --- Down button
53 press_texture = arcade.load_texture(
54 ":resources:onscreen_controls/shaded_dark/down.png"
55 )
56 normal_texture = arcade.load_texture(
57 ":resources:onscreen_controls/flat_dark/down.png"
58 )
59 hover_texture = arcade.load_texture(
60 ":resources:onscreen_controls/shaded_dark/down.png"
61 )
62
63 # Create our button
64 self.down_button = arcade.gui.widgets.buttons.UITextureButton(
65 texture=normal_texture,
66 texture_hovered=hover_texture,
67 texture_pressed=press_texture,
68 )
69
70 # Map that button's on_click method to this view's on_button_click method.
71 self.down_button.on_click = self.volume_down # type: ignore
72 self.down_button.scale(0.5)
73
74 # Add in our element.
75 box.add(self.down_button)
76
77 # --- Up button
78 press_texture = arcade.load_texture(
79 ":resources:onscreen_controls/shaded_dark/up.png"
80 )
81 normal_texture = arcade.load_texture(
82 ":resources:onscreen_controls/flat_dark/up.png"
83 )
84 hover_texture = arcade.load_texture(
85 ":resources:onscreen_controls/shaded_dark/up.png"
86 )
87
88 # Create our button
89 self.up_button = arcade.gui.widgets.buttons.UITextureButton(
90 texture=normal_texture,
91 texture_hovered=hover_texture,
92 texture_pressed=press_texture,
93 )
94
95 # Map that button's on_click method to this view's on_button_click method.
96 self.up_button.on_click = self.volume_up # type: ignore
97 self.up_button.scale(0.5)
98
99 # Add in our element.
100 box.add(self.up_button)
101
102 # --- Right button
103 press_texture = arcade.load_texture(
104 ":resources:onscreen_controls/shaded_dark/right.png"
105 )
106 normal_texture = arcade.load_texture(
107 ":resources:onscreen_controls/flat_dark/right.png"
108 )
109 hover_texture = arcade.load_texture(
110 ":resources:onscreen_controls/shaded_dark/right.png"
111 )
112
113 # Create our button
114 self.right_button = arcade.gui.widgets.buttons.UITextureButton(
115 texture=normal_texture,
116 texture_hovered=hover_texture,
117 texture_pressed=press_texture,
118 )
119
120 # Map that button's on_click method to this view's on_button_click method.
121 self.right_button.on_click = self.forward # type: ignore
122 self.right_button.scale(0.5)
123
124 # Add in our element.
125 box.add(self.right_button)
126
127 # Place buttons in the center of the screen using
128 # an UIAnchorWidget with default values
129 self.ui_manager.add(
130 arcade.gui.widgets.layout.UIAnchorLayout(children=[box])
131 )
132
133 def music_over(self):
134 self.media_player.pop_handlers()
135 self.media_player = None
136 self.sound_button_off()
137 self.cur_song_index += 1
138 if self.cur_song_index >= len(self.songs):
139 self.cur_song_index = 0
140 self.my_music = arcade.load_sound(self.songs[self.cur_song_index])
141 self.media_player = self.my_music.play()
142 self.media_player.push_handlers(on_eos=self.music_over)
143
144 def volume_down(self, *_):
145 if self.media_player and self.media_player.volume > 0.2:
146 self.media_player.volume -= 0.2
147
148 def volume_up(self, *_):
149 if self.media_player and self.media_player.volume < 1.0:
150 self.media_player.volume += 0.2
151
152 def forward(self, *_):
153 skip_time = 10
154
155 if self.media_player:
156 if self.media_player.time < self.my_music.get_length() - skip_time:
157 self.media_player.seek(self.media_player.time + 10)
158
159 def sound_button_on(self):
160 self.start_button.texture_pressed = \
161 arcade.load_texture(":resources:onscreen_controls/shaded_dark/sound_on.png")
162 self.start_button.texture = \
163 arcade.load_texture(":resources:onscreen_controls/flat_dark/sound_on.png")
164 self.start_button.texture_hovered = \
165 arcade.load_texture(":resources:onscreen_controls/shaded_dark/sound_on.png")
166
167 def sound_button_off(self):
168 self.start_button.texture_pressed = \
169 arcade.load_texture(":resources:onscreen_controls/shaded_dark/sound_off.png")
170 self.start_button.texture = \
171 arcade.load_texture(":resources:onscreen_controls/flat_dark/sound_off.png")
172 self.start_button.texture_hovered = \
173 arcade.load_texture(":resources:onscreen_controls/shaded_dark/sound_off.png")
174
175 def start_button_clicked(self, *_):
176 self.paused = False
177 if not self.media_player:
178 # Play button has been hit, and we need to start playing from the beginning.
179 self.media_player = self.my_music.play()
180 self.media_player.push_handlers(on_eos=self.music_over)
181 self.sound_button_on()
182 elif not self.media_player.playing:
183 # Play button hit, and we need to un-pause our playing.
184 self.media_player.play()
185 self.sound_button_on()
186 elif self.media_player.playing:
187 # We are playing music, so pause.
188 self.media_player.pause()
189 self.sound_button_off()
190
191 def on_draw(self):
192 self.clear()
193
194 # This draws our UI elements
195 self.ui_manager.draw()
196 arcade.draw_text("Music Demo",
197 x=0, y=self.window.height - 55,
198 width=self.window.width,
199 font_size=40,
200 align="center",
201 color=arcade.color.BLACK)
202
203 if self.media_player:
204 seconds = self.media_player.time
205 minutes = int(seconds // 60)
206 seconds = int(seconds % 60)
207 arcade.draw_text(f"Time: {minutes}:{seconds:02}",
208 x=10, y=10, color=arcade.color.BLACK, font_size=24)
209 volume = self.media_player.volume
210 arcade.draw_text(f"Volume: {volume:3.1f}",
211 x=10, y=50, color=arcade.color.BLACK, font_size=24)
212
213 def on_show_view(self):
214 self.window.background_color = arcade.color.ALMOND
215
216 # Registers handlers for GUI button clicks, etc.
217 # We don't really use them in this example.
218 self.ui_manager.enable()
219
220 def on_hide_view(self):
221 # This unregisters the manager's UI handlers,
222 # Handlers respond to GUI button clicks, etc.
223 self.ui_manager.disable()
224
225
226def main():
227 """ Main function """
228 # Create a window class. This is what actually shows up on screen
229 window = arcade.Window(title="Arcade Music Control Demo")
230
231 # Create the GameView
232 game = GameView()
233
234 # Show GameView on screen
235 window.show_view(game)
236
237 # Start the arcade game loop
238 arcade.run()
239
240
241if __name__ == "__main__":
242 main()