Files
MusicPlayer/music_player.gd
T
Sansan 674604425f Reach nodes by unique name instead of long paths
Nodes a script uses through a path of several nodes are marked unique in their
scene and found with %Name. The search list is renamed SearchResults, and the
player row's nodes get their real types.
2026-10-06 11:44:47 +02:00

238 lines
7.3 KiB
GDScript

class_name MusicPlayer
extends Control
## The bar that plays the songs, with play, restart, progress and volume, and the
## auto repeat switch under it.
# LOC 20/1-24: 136
# LOC 12/6-24: 170
@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
@onready
var auto_repeat_button: CheckButton = $RepeatSongCheckButton
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
signal update_song_list
signal play_next_song
# Called when the node enters the scene tree for the first time.
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)
auto_repeat_button.pressed.connect(_on_auto_repeat_pressed)
func _on_auto_repeat_pressed() -> void:
Settings.auto_repeat_song = !Settings.auto_repeat_song
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
#if stream != null:
# music_time_label.text = format_text(progress_slider.value, stream.get_length())
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"))