- A Quiz settings button under the player bar opens a small card above it with the quiz settings, including Auto repeat, which moves there from under the player bar. The card does not dim the quiz, so it can be changed during a song, and grows to fit its rows. - A Settings button in the top bar opens the application settings: server, fullscreen and songs to download ahead. Quick sync is gone, as the server no longer has it, and the server list is in Settings. - Labels use sentence case, and seconds to hide show as whole numbers. - Debug builds switch to the local server and a low winning score in the Settings autoload, before any scene asks the server for anything. The DEBUG label moves to the top bar, so it shows on every tab. - Search moves from the top bar back to the quiz toolbar, as the Statistics tab has its own search.
230 lines
7.0 KiB
GDScript
230 lines
7.0 KiB
GDScript
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 songs: Array = []
|
|
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()
|
|
|
|
|
|
func get_sound_test_song() -> void:
|
|
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)
|
|
|
|
##### LOCAL
|
|
var local_path: String = '/Users/sebastian/ResilioSync/Sorterat_test/Metal Gear Solid 4 - Guns of the Patriots/2-16 Metal Gear Saga.mp3'
|
|
|
|
|
|
func load_mp3(_path: String) -> AudioStream:
|
|
var file: FileAccess = FileAccess.open(_path, FileAccess.READ)
|
|
var sound: AudioStream = AudioStreamMP3.new()
|
|
sound.data = file.get_buffer(file.get_length())
|
|
return sound
|
|
|
|
|
|
func play_local_song() -> void:
|
|
if songs:
|
|
local_path = songs[0]
|
|
GameLog.debug(local_path)
|
|
GameLog.debug(FileAccess.file_exists(local_path))
|
|
play_sound(load_mp3(local_path))
|
|
|
|
|
|
func sound_test_local() -> void:
|
|
play_sound(preload("res://sounds/01. Opening.mp3"))
|