class_name MusicPlayer extends Control ## The bar that plays the songs, with play, restart, progress and volume. Whether a song ## repeats is a quiz setting ([code]Settings.auto_repeat_song[/code]). signal update_song_list signal play_next_song var play_icon: Texture = preload("res://icons/play_icon_light.svg") var pause_icon: Texture = preload("res://icons/pause_icon_light.svg") var is_changing: bool = false var playback_position: float var stream: AudioStream var song_finished: bool = false @onready var play_button: TextureButton = %PlayTextureButton @onready var restart_button: TextureButton = %RestartTextureButton @onready var audio_player: AudioStreamPlayer = $AudioStreamPlayer @onready var sound_player: AudioStreamPlayer = $AudioSoundPlayer @onready var sound_effect_player: AudioStreamPlayer = $AudioSoundEffectPlayer @onready var progress_slider: HSlider = %MusicPlayerSlider @onready var volume_slider: VolumeSlider = %VolumeSlider @onready var music_time_label: Label = %MusicTimeLabel func _ready() -> void: play_button.pressed.connect(play_or_pause) restart_button.pressed.connect(restart) progress_slider.drag_started.connect(_on_drag_started) progress_slider.drag_ended.connect(_on_drag_ended) audio_player.finished.connect(_on_finished) func _process(_delta: float) -> void: if audio_player.has_stream_playback() && !is_changing && !audio_player.stream_paused: if !Settings.hide_beginning \ || audio_player.get_playback_position() > Settings.hide_for_seconds: progress_slider.value = audio_player.get_playback_position() if stream != null: music_time_label.text = format_text(progress_slider.value, stream.get_length()) else: music_time_label.text = format_text(progress_slider.value, 0.0) func format_time(time: float) -> String: var total_seconds: int = roundi(time) @warning_ignore("integer_division") return "%02d:%02d" % [total_seconds / 60, total_seconds % 60] func format_text(part: float, total: float) -> String: if (Settings.hide_beginning && part < Settings.hide_for_seconds) && Settings.hide_length: return "??:?? / ??:??" elif Settings.hide_length: return format_time(part) + " / ??:??" elif Settings.hide_beginning && part < Settings.hide_for_seconds: return "??:?? / " + format_time(total) else: return format_time(part) + " / " + format_time(total) func play_or_pause() -> void: if song_finished: restart() elif audio_player.stream_paused: play_button.texture_normal = pause_icon audio_player.stream_paused = false song_finished = false audio_player.seek(playback_position) GameLog.debug("continue") progress_slider.max_value = round(stream.get_length()) if Settings.hide_ticks: progress_slider.tick_count = 0 else: progress_slider.tick_count = round(stream.get_length() / 60) else: pause() func pause() -> void: audio_player.stream_paused = true playback_position = audio_player.get_playback_position() play_button.texture_normal = play_icon func restart() -> void: audio_player.stop() audio_player.stream_paused = false song_finished = false progress_slider.value = 0 playback_position = audio_player.get_playback_position() audio_player.seek(playback_position) play_button.texture_normal = pause_icon audio_player.play() func _on_finished() -> void: play_button.texture_normal = play_icon song_finished = true if !Settings.stop_after_current: play_next_song.emit() if Settings.auto_repeat_song: restart() func _on_drag_started() -> void: is_changing = true func _on_drag_ended(_changed: bool) -> void: audio_player.seek(progress_slider.value) playback_position = progress_slider.value is_changing = false func seek(new_position: float) -> void: progress_slider.value += new_position is_changing = true audio_player.seek(progress_slider.value) playback_position = progress_slider.value is_changing = false func change_volume(value: float) -> void: volume_slider.value += value volume_slider.change_volume(volume_slider.value) func _on_point_triggered(point: String) -> void: if point == "first": var value: int = randi_range(0, 10) if value == 0: play_sound(preload("res://sounds/sound1.mp3")) elif value < 5: play_sound(preload("res://sounds/intro_long.mp3")) else: play_sound(preload("res://sounds/intro_short.mp3")) elif point == "match": play_sound(preload("res://sounds/sound0.mp3")) func play_sound_effect(sound_effect_name: AudioStream) -> void: sound_effect_player.stream = sound_effect_name sound_effect_player.play() func play_sound(sound_name: AudioStream) -> void: sound_player.stream = sound_name audio_player.stop() sound_player.play() song_finished = true play_button.texture_normal = play_icon progress_slider.value = 0 func play_song(song: AudioStream) -> void: audio_player.stream = song audio_player.play() sound_player.stop() song_finished = false play_button.texture_normal = pause_icon stream = audio_player.stream progress_slider.value = 0 progress_slider.max_value = round(stream.get_length()) if Settings.hide_ticks: progress_slider.tick_count = 0 else: progress_slider.tick_count = round(stream.get_length() / 60) music_time_label.text = format_text(progress_slider.value, stream.get_length()) func play_song_object(song_object_no: int) -> void: GameLog.debug("play_song_object") if audio_player.is_playing(): audio_player.stop() await get_tree().create_timer(0.5).timeout audio_player.stream = Playlist.get_song(song_object_no) sound_player.stop() audio_player.play() song_finished = false play_button.texture_normal = pause_icon stream = audio_player.stream progress_slider.value = 0 progress_slider.max_value = round(stream.get_length()) if Settings.hide_ticks: progress_slider.tick_count = 0 else: progress_slider.tick_count = round(stream.get_length() / 60) music_time_label.text = format_text(progress_slider.value, stream.get_length()) Playlist.set_currently_playing_song(song_object_no) Playlist.unset_is_playing() if !Settings.hide_next_track: GameLog.debug("Show answer now!!") Playlist.song_is_answered(song_object_no) Playlist.song_has_played(song_object_no) Playlist.song_is_playing(song_object_no) update_song_list.emit() ## Plays a song to test the sound: one from the server, or a song that comes with the ## game when playing from a music folder. func get_sound_test_song() -> void: if Settings.is_offline(): sound_test_local() return var test_sound: Callable = func test_sound(body: PackedByteArray) -> void: var sound: AudioStream = AudioStreamMP3.new() sound.data = body play_song(sound) MusicServerClient.fetch_sound_test_song(test_sound) # The sound test without a server: a song that comes with the game func sound_test_local() -> void: play_song(preload("res://sounds/01. Opening.mp3"))