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