├── .gitignore ├── API ├── Global.gd ├── Player.gd └── Tag.gd ├── Assets ├── CozetteVector.ttf ├── MainControls │ ├── MainControls.ase │ ├── loop.png │ ├── loop.png.import │ ├── pause.png │ ├── pause.png.import │ ├── play.png │ ├── play.png.import │ ├── shuffle.png │ ├── shuffle.png.import │ ├── skip_left.png │ ├── skip_left.png.import │ ├── skip_right.png │ └── skip_right.png.import ├── Pixel Shuba Duck Dance [h-8L9SDDGkE].webm ├── cross.png ├── cross.png.import ├── duck.webm ├── slider_grabber.ase ├── slider_grabber.png ├── slider_grabber.png.import ├── slider_grabber_disabled.png ├── slider_grabber_disabled.png.import ├── slider_grabber_highlight.png ├── slider_grabber_highlight.png.import ├── tick.png └── tick.png.import ├── Main.tscn ├── README.md ├── Resources ├── AlbumFile.gd ├── LibraryFile.gd └── TrackFile.gd ├── Scenes ├── LeftBarEntry.tscn ├── QueueEntry.tscn └── TrackPanelEntry.tscn ├── Scripts ├── BottomBar.gd ├── LeftBar.gd ├── QueueSideBar.gd ├── TopBar.gd └── TrackPanel.gd ├── build ├── PMP.7z └── PMP │ ├── PMP.pck │ └── PMP.x86_64 ├── concept.lorien ├── default_env.tres ├── export_presets.cfg ├── icon.png ├── icon.png.import ├── project.godot └── roadmap.md /.gitignore: -------------------------------------------------------------------------------- 1 | .import 2 | -------------------------------------------------------------------------------- /API/Global.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | # TODO: DOCS 3 | 4 | # ------------------------------------------------------------------------------ 5 | export(String, DIR) var library_path setget _library_path_changed 6 | var library: LibraryFile 7 | # ------------------------------------------------------------------------------ 8 | 9 | # Main Control Node of the software 10 | onready var main: Control = get_tree().get_root().get_node("Control") 11 | 12 | # ------------------------------------------------------------------------------ 13 | 14 | signal library_path_changed 15 | 16 | # ------------------------------------------------------------------------------ 17 | 18 | func _library_path_changed(path: String) -> void: 19 | library_path = path 20 | 21 | var files := _find_files(path) 22 | emit_signal("library_path_changed", files) 23 | 24 | # ------------------------------------------------------------------------------ 25 | # Returns an array with all subdirectories of the directory 26 | func _find_files(path: String) -> Array: 27 | var dir := Directory.new() 28 | var files := [] 29 | 30 | if dir.open(path) == OK: 31 | dir.list_dir_begin(true) 32 | 33 | var file_name = dir.get_next() 34 | while file_name != "": 35 | if dir.current_is_dir(): 36 | files.append_array(_find_files(path + "/" + file_name)) 37 | else: 38 | files.append(path + "/" + file_name) 39 | file_name = dir.get_next() 40 | return files 41 | -------------------------------------------------------------------------------- /API/Player.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | # This is the main player API for the music player 3 | # This script contains code for actually playing the music 4 | 5 | # ------------------------------------------------------------------------------ 6 | onready var Player: AudioStreamPlayer = Global.main.find_node("MainPlayer") 7 | onready var Forward: ToolButton = Global.main.find_node("Forward") 8 | onready var Back: ToolButton = Global.main.find_node("Back") 9 | # ------------------------------------------------------------------------------ 10 | var queue: Array = [] 11 | var history: Array = [] 12 | 13 | var loop: bool = false 14 | var shuffle: bool = false 15 | 16 | # ------------------------------------------------------------------------------ 17 | signal finished 18 | signal queue_updated 19 | signal pause_changed 20 | 21 | # ------------------------------------------------------------------------------ 22 | 23 | func _ready(): 24 | Player.connect("finished", self, "_finished") 25 | 26 | # ------------------------------------------------------------------------------ 27 | 28 | func add_to_queue(track: TrackFile) -> void: 29 | queue.append(track) 30 | emit_signal("queue_updated") 31 | if not Player.playing: 32 | _play(queue[0].path) 33 | 34 | # internal function please use "skip" 35 | func _play_next() -> void: 36 | if queue.size() > 0: 37 | _play(queue[0].path) 38 | 39 | func _play(file_path: String) -> void: 40 | var file := File.new() 41 | file.open(file_path, File.READ) 42 | var size := file.get_len() 43 | var bytes := file.get_buffer(size) 44 | 45 | var stream := AudioStreamMP3.new() 46 | stream.data = bytes 47 | Player.stream = stream 48 | Player.playing = true 49 | Player.pause_mode = false 50 | emit_signal("playback_started") 51 | 52 | func _stop() -> void: 53 | Player.stream = null 54 | Player.playing = false 55 | 56 | # Returns the new pause state 57 | func toggle_pause() -> bool: 58 | Player.stream_paused = !Player.stream_paused 59 | emit_signal("pause_changed") 60 | return Player.stream_paused 61 | 62 | func skip() -> void: 63 | queue.pop_front() 64 | emit_signal("queue_updated") 65 | _stop() 66 | _play_next() 67 | 68 | func remove_from_queue(index: int) -> void: 69 | if index == 0: 70 | skip() 71 | else: 72 | queue.pop_at(index) 73 | emit_signal("queue_updated") 74 | 75 | func _get_duration() -> float: 76 | if Player.stream != null: 77 | return Player.stream.get_length() 78 | return 0.0 79 | 80 | func _get_position(): 81 | return Player.get_playback_position() 82 | 83 | func _seek(time: float) -> void: 84 | Player.seek(time) 85 | 86 | # ------------------------------------------------------------------------------ 87 | 88 | func _finished() -> void: 89 | emit_signal("finished") 90 | skip() 91 | -------------------------------------------------------------------------------- /API/Tag.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | # Improve the reading of this 4 | 5 | func read_ID3(file_path: String) -> TrackFile: 6 | var result := TrackFile.new() 7 | result.path = file_path 8 | var file = File.new() 9 | file.open(file_path, File.READ) 10 | 11 | # Check if file contains ID3 12 | if file.get_buffer(3) != PoolByteArray([73, 68, 51]): 13 | print("The file doesn't contain a ID3 header.") 14 | return result 15 | 16 | # Get version 17 | if file.get_buffer(2) != PoolByteArray([4, 0]): 18 | print(file_path) 19 | return result 20 | 21 | file.get_buffer(1) 22 | 23 | # size of the header 24 | var total_size := _sync_safe_to_int(file.get_buffer(4)) 25 | #print(total_size) 26 | 27 | # frames 28 | while total_size > 0: 29 | var frame_id: String = file.get_buffer(4).get_string_from_utf8() 30 | var size: int = _sync_safe_to_int(file.get_buffer(4)) 31 | var flags: PoolByteArray = file.get_buffer(2) 32 | total_size -= 10 33 | #print("Registerd frame %s with size %s with flags %s" % [frame_id, str(size), flags]) 34 | match frame_id: 35 | "TIT2": 36 | if file.get_8() != 3: 37 | print("This text encoding format is unsupported!") 38 | result.title = file.get_buffer(size-1).get_string_from_utf8() 39 | "TPE1": 40 | if file.get_8() != 3: 41 | print("This text encoding format is unsupported!") 42 | result.artist = file.get_buffer(size-1).get_string_from_utf8() 43 | "TRCK": 44 | if file.get_8() != 3: 45 | print("This text encoding format is unsupported!") 46 | result.index = file.get_buffer(size-1).get_string_from_utf8() 47 | "TALB": 48 | if file.get_8() != 3: 49 | print("This text encoding format is unsupported!") 50 | result.album = file.get_buffer(size-1).get_string_from_utf8() 51 | "TDRC": 52 | if file.get_8() != 3: 53 | print("This text encoding format is unsupported!") 54 | result.year = file.get_buffer(size-1).get_string_from_utf8() 55 | _: 56 | file.get_buffer(size) 57 | 58 | total_size -= size 59 | 60 | file.close() 61 | return result 62 | 63 | func _size_to_int(bytes: PoolByteArray) -> int: 64 | var sum := 0 65 | for byte in bytes: 66 | sum += byte 67 | return sum 68 | 69 | # i'm just as confused as you are 70 | func _sync_safe_to_int(bytes: PoolByteArray) -> int: 71 | var byte0: int = bytes[0] 72 | var byte1: int = bytes[1] 73 | var byte2: int = bytes[2] 74 | var byte3: int = bytes[3] 75 | return byte0 << 21 | byte1 << 14 | byte2 << 2 | byte3 76 | -------------------------------------------------------------------------------- /Assets/CozetteVector.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/CozetteVector.ttf -------------------------------------------------------------------------------- /Assets/MainControls/MainControls.ase: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/MainControls/MainControls.ase -------------------------------------------------------------------------------- /Assets/MainControls/loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/MainControls/loop.png -------------------------------------------------------------------------------- /Assets/MainControls/loop.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/loop.png-eeea7ba67ca542007d28041434f22410.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Assets/MainControls/loop.png" 13 | dest_files=[ "res://.import/loop.png-eeea7ba67ca542007d28041434f22410.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=false 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=false 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /Assets/MainControls/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/MainControls/pause.png -------------------------------------------------------------------------------- /Assets/MainControls/pause.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/pause.png-baa3737019a7c11008b9a691af663229.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Assets/MainControls/pause.png" 13 | dest_files=[ "res://.import/pause.png-baa3737019a7c11008b9a691af663229.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=false 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=false 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /Assets/MainControls/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/MainControls/play.png -------------------------------------------------------------------------------- /Assets/MainControls/play.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/play.png-faf06eb46cc1e360c142c1a55f2b0027.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Assets/MainControls/play.png" 13 | dest_files=[ "res://.import/play.png-faf06eb46cc1e360c142c1a55f2b0027.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=false 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=false 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /Assets/MainControls/shuffle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/MainControls/shuffle.png -------------------------------------------------------------------------------- /Assets/MainControls/shuffle.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/shuffle.png-7544df376aa3a6d348917c0281970a83.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Assets/MainControls/shuffle.png" 13 | dest_files=[ "res://.import/shuffle.png-7544df376aa3a6d348917c0281970a83.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=false 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=false 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /Assets/MainControls/skip_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/MainControls/skip_left.png -------------------------------------------------------------------------------- /Assets/MainControls/skip_left.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/skip_left.png-0940cb301fa2bf6afa983b0575478061.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Assets/MainControls/skip_left.png" 13 | dest_files=[ "res://.import/skip_left.png-0940cb301fa2bf6afa983b0575478061.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=false 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=false 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /Assets/MainControls/skip_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/MainControls/skip_right.png -------------------------------------------------------------------------------- /Assets/MainControls/skip_right.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/skip_right.png-0f5e7b4507ec3af2a44deb2b1a008097.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Assets/MainControls/skip_right.png" 13 | dest_files=[ "res://.import/skip_right.png-0f5e7b4507ec3af2a44deb2b1a008097.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=false 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=false 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /Assets/Pixel Shuba Duck Dance [h-8L9SDDGkE].webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/Pixel Shuba Duck Dance [h-8L9SDDGkE].webm -------------------------------------------------------------------------------- /Assets/cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/cross.png -------------------------------------------------------------------------------- /Assets/cross.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/cross.png-4499963432517842f8cd445c9598d7e4.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Assets/cross.png" 13 | dest_files=[ "res://.import/cross.png-4499963432517842f8cd445c9598d7e4.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=false 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=false 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /Assets/duck.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/duck.webm -------------------------------------------------------------------------------- /Assets/slider_grabber.ase: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/slider_grabber.ase -------------------------------------------------------------------------------- /Assets/slider_grabber.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/slider_grabber.png -------------------------------------------------------------------------------- /Assets/slider_grabber.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/slider_grabber.png-b7f7fd629dbc334bb9afb0e1c162a781.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Assets/slider_grabber.png" 13 | dest_files=[ "res://.import/slider_grabber.png-b7f7fd629dbc334bb9afb0e1c162a781.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=false 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=false 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /Assets/slider_grabber_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/slider_grabber_disabled.png -------------------------------------------------------------------------------- /Assets/slider_grabber_disabled.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/slider_grabber_disabled.png-9659e49830f2324c363db078fa74bc4d.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Assets/slider_grabber_disabled.png" 13 | dest_files=[ "res://.import/slider_grabber_disabled.png-9659e49830f2324c363db078fa74bc4d.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=false 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=false 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /Assets/slider_grabber_highlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/slider_grabber_highlight.png -------------------------------------------------------------------------------- /Assets/slider_grabber_highlight.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/slider_grabber_highlight.png-58ee7ba645a9a14871c3762b2813ba96.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Assets/slider_grabber_highlight.png" 13 | dest_files=[ "res://.import/slider_grabber_highlight.png-58ee7ba645a9a14871c3762b2813ba96.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=false 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=false 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /Assets/tick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/Assets/tick.png -------------------------------------------------------------------------------- /Assets/tick.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tick.png-12f391eb5e8b6573b42986d3a1108218.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Assets/tick.png" 13 | dest_files=[ "res://.import/tick.png-12f391eb5e8b6573b42986d3a1108218.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=false 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=false 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /Main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=9 format=2] 2 | 3 | [ext_resource path="res://Scripts/TopBar.gd" type="Script" id=1] 4 | [ext_resource path="res://Scripts/LeftBar.gd" type="Script" id=2] 5 | [ext_resource path="res://Scripts/BottomBar.gd" type="Script" id=3] 6 | [ext_resource path="res://Assets/MainControls/pause.png" type="Texture" id=4] 7 | [ext_resource path="res://Assets/MainControls/skip_left.png" type="Texture" id=5] 8 | [ext_resource path="res://Assets/MainControls/skip_right.png" type="Texture" id=6] 9 | [ext_resource path="res://Scripts/QueueSideBar.gd" type="Script" id=7] 10 | [ext_resource path="res://Scripts/TrackPanel.gd" type="Script" id=8] 11 | 12 | [node name="Control" type="Control"] 13 | anchor_right = 1.0 14 | anchor_bottom = 1.0 15 | 16 | [node name="BackGroundSafetyNet" type="Panel" parent="."] 17 | margin_right = 1024.0 18 | margin_bottom = 576.0 19 | 20 | [node name="TrackPanel" type="Panel" parent="."] 21 | anchor_left = 0.25 22 | anchor_top = 0.056 23 | anchor_right = 0.812 24 | anchor_bottom = 0.889 25 | margin_top = -0.256001 26 | margin_right = 0.511963 27 | margin_bottom = -0.0640259 28 | script = ExtResource( 8 ) 29 | 30 | [node name="TrackPanelScroll" type="ScrollContainer" parent="TrackPanel"] 31 | anchor_right = 1.0 32 | anchor_bottom = 1.0 33 | 34 | [node name="GroupList" type="VBoxContainer" parent="TrackPanel/TrackPanelScroll"] 35 | 36 | [node name="QueueSideBar" type="Panel" parent="."] 37 | anchor_left = 0.812 38 | anchor_right = 1.0 39 | anchor_bottom = 1.0 40 | margin_left = 0.511963 41 | script = ExtResource( 7 ) 42 | __meta__ = { 43 | "_edit_group_": true 44 | } 45 | 46 | [node name="ScrollContainer" type="ScrollContainer" parent="QueueSideBar"] 47 | anchor_top = 0.056 48 | anchor_right = 1.0 49 | anchor_bottom = 0.889 50 | margin_top = -0.256001 51 | margin_bottom = -0.0640259 52 | 53 | [node name="QueueList" type="VBoxContainer" parent="QueueSideBar/ScrollContainer"] 54 | 55 | [node name="TopBar" type="Panel" parent="."] 56 | anchor_right = 1.0 57 | anchor_bottom = 0.053 58 | margin_bottom = 0.199999 59 | script = ExtResource( 1 ) 60 | __meta__ = { 61 | "_edit_group_": true 62 | } 63 | 64 | [node name="Container" type="HBoxContainer" parent="TopBar"] 65 | anchor_right = 1.0 66 | anchor_bottom = 1.0 67 | 68 | [node name="File" type="MenuButton" parent="TopBar/Container"] 69 | margin_right = 35.0 70 | margin_bottom = 30.0 71 | text = "File" 72 | switch_on_hover = true 73 | 74 | [node name="LeftBar" type="Panel" parent="."] 75 | anchor_top = 0.056 76 | anchor_right = 0.25 77 | anchor_bottom = 0.889 78 | margin_top = -0.256001 79 | margin_bottom = 0.935974 80 | script = ExtResource( 2 ) 81 | __meta__ = { 82 | "_edit_group_": true 83 | } 84 | 85 | [node name="LibraryControls" type="HBoxContainer" parent="LeftBar"] 86 | anchor_right = 1.0 87 | anchor_bottom = 0.056 88 | margin_bottom = 0.191999 89 | 90 | [node name="GroupAlbum" type="ToolButton" parent="LeftBar/LibraryControls"] 91 | margin_right = 34.0 92 | margin_bottom = 27.0 93 | text = "gba" 94 | 95 | [node name="GroupArtist" type="ToolButton" parent="LeftBar/LibraryControls"] 96 | margin_left = 38.0 97 | margin_right = 77.0 98 | margin_bottom = 27.0 99 | text = "gbar" 100 | 101 | [node name="ListScrollContainer" type="ScrollContainer" parent="LeftBar"] 102 | anchor_top = 0.069 103 | anchor_right = 1.0 104 | anchor_bottom = 1.0 105 | margin_top = -0.189003 106 | 107 | [node name="MainList" type="VBoxContainer" parent="LeftBar/ListScrollContainer"] 108 | 109 | [node name="BottomBar" type="Panel" parent="."] 110 | anchor_top = 0.889 111 | anchor_right = 1.0 112 | anchor_bottom = 1.0 113 | margin_top = -0.0640259 114 | script = ExtResource( 3 ) 115 | 116 | [node name="MainControls" type="HBoxContainer" parent="BottomBar"] 117 | anchor_left = 0.375 118 | anchor_right = 0.562 119 | anchor_bottom = 1.0 120 | margin_left = -3.05176e-05 121 | margin_right = 0.511963 122 | alignment = 1 123 | 124 | [node name="Shuffle" type="ToolButton" parent="BottomBar/MainControls"] 125 | margin_right = 55.0 126 | margin_bottom = 64.0 127 | text = "shuffle" 128 | 129 | [node name="Back" type="ToolButton" parent="BottomBar/MainControls"] 130 | margin_left = 59.0 131 | margin_right = 103.0 132 | margin_bottom = 64.0 133 | icon = ExtResource( 5 ) 134 | 135 | [node name="PlayPause" type="ToolButton" parent="BottomBar/MainControls"] 136 | margin_left = 107.0 137 | margin_right = 151.0 138 | margin_bottom = 64.0 139 | icon = ExtResource( 4 ) 140 | 141 | [node name="Forward" type="ToolButton" parent="BottomBar/MainControls"] 142 | margin_left = 155.0 143 | margin_right = 199.0 144 | margin_bottom = 64.0 145 | icon = ExtResource( 6 ) 146 | 147 | [node name="Loop" type="ToolButton" parent="BottomBar/MainControls"] 148 | margin_left = 203.0 149 | margin_right = 243.0 150 | margin_bottom = 64.0 151 | text = "loop" 152 | 153 | [node name="VolumeSlider" type="HSlider" parent="BottomBar"] 154 | anchor_left = 0.875 155 | anchor_right = 1.0 156 | anchor_bottom = 1.0 157 | margin_left = -6.10352e-05 158 | min_value = -80.0 159 | max_value = 24.0 160 | 161 | [node name="DurationBar" type="HSlider" parent="BottomBar"] 162 | anchor_left = 0.031 163 | anchor_top = 0.25 164 | anchor_right = 0.219 165 | anchor_bottom = 0.75 166 | margin_left = 0.255999 167 | margin_right = -0.256012 168 | margin_bottom = -3.8147e-06 169 | editable = false 170 | 171 | [node name="PopUps" type="Control" parent="."] 172 | anchor_left = 0.25 173 | anchor_top = 0.213 174 | anchor_right = 0.75 175 | anchor_bottom = 0.747 176 | margin_left = 256.0 177 | margin_top = 172.2 178 | margin_right = -256.0 179 | margin_bottom = -148.2 180 | 181 | [node name="FileDialog" type="FileDialog" parent="PopUps"] 182 | anchor_left = 0.5 183 | anchor_top = 0.5 184 | anchor_right = 0.5 185 | anchor_bottom = 0.5 186 | margin_left = -256.0 187 | margin_top = -172.0 188 | margin_right = 256.0 189 | margin_bottom = 148.0 190 | window_title = "Open a Directory" 191 | resizable = true 192 | dialog_text = "Choose your music libary" 193 | mode = 2 194 | access = 2 195 | current_dir = "/home/molten/Documents/GMP" 196 | current_path = "/home/molten/Documents/GMP/" 197 | 198 | [node name="MainPlayer" type="AudioStreamPlayer" parent="."] 199 | 200 | [connection signal="pressed" from="LeftBar/LibraryControls/GroupAlbum" to="LeftBar" method="_on_GroupAlbum_pressed"] 201 | [connection signal="pressed" from="LeftBar/LibraryControls/GroupArtist" to="LeftBar" method="_on_GroupArtist_pressed"] 202 | [connection signal="pressed" from="BottomBar/MainControls/PlayPause" to="BottomBar" method="_on_PlayPause_pressed"] 203 | [connection signal="pressed" from="BottomBar/MainControls/Forward" to="BottomBar" method="_on_Forward_pressed"] 204 | [connection signal="value_changed" from="BottomBar/VolumeSlider" to="BottomBar" method="_on_VolumeSlider_value_changed"] 205 | [connection signal="dir_selected" from="PopUps/FileDialog" to="TopBar" method="_file_dialog_dir_selected"] 206 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pixel Music Player 2 | A working .mp3 file player made entirely in Godot Game Engine! 3 | 4 | # Features 5 | - Sorting by album / artist 6 | - Looping 7 | - Play Queue 8 | -------------------------------------------------------------------------------- /Resources/AlbumFile.gd: -------------------------------------------------------------------------------- 1 | extends Resource 2 | class_name AlbumFile 3 | 4 | export(String) var name 5 | export(Array, String) var songs = [] 6 | -------------------------------------------------------------------------------- /Resources/LibraryFile.gd: -------------------------------------------------------------------------------- 1 | extends Resource 2 | class_name LibraryFile 3 | 4 | export(Array, Resource) var tracks := [] 5 | export(Dictionary) var albums = {} 6 | export(Dictionary) var artists = {} 7 | -------------------------------------------------------------------------------- /Resources/TrackFile.gd: -------------------------------------------------------------------------------- 1 | extends Resource 2 | class_name TrackFile 3 | # TODO: DOCS 4 | 5 | export(String) var path: String 6 | export(String) var title: String 7 | export(String) var artist: String 8 | export(String) var index: String 9 | export(String) var album: String 10 | export(String) var year: String 11 | export(String) var genre: String 12 | -------------------------------------------------------------------------------- /Scenes/LeftBarEntry.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [sub_resource type="GDScript" id=1] 4 | script/source = "extends Button 5 | 6 | export(String) var album_title setget _set_title 7 | export(Array, Resource) var tracks 8 | 9 | onready var TrackPanel: Panel = Global.main.get_node(\"TrackPanel\") 10 | 11 | signal album_pressed 12 | 13 | func _ready(): 14 | self.connect(\"album_pressed\", TrackPanel, \"view_album\") 15 | 16 | func _set_title(new_value): 17 | album_title = new_value 18 | self.text = album_title 19 | 20 | func _on_Track_pressed(): 21 | emit_signal(\"album_pressed\", album_title, tracks) 22 | " 23 | 24 | [node name="Track" type="Button"] 25 | margin_right = 12.0 26 | margin_bottom = 20.0 27 | flat = true 28 | align = 0 29 | script = SubResource( 1 ) 30 | 31 | [connection signal="pressed" from="." to="." method="_on_Track_pressed"] 32 | -------------------------------------------------------------------------------- /Scenes/QueueEntry.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://Assets/cross.png" type="Texture" id=1] 4 | 5 | [sub_resource type="GDScript" id=1] 6 | script/source = "extends ToolButton 7 | 8 | export(Resource) var track setget _set_track_file 9 | export(int) var index: int 10 | 11 | func _set_track_file(new_track: Resource) -> void: 12 | track = new_track 13 | if index: 14 | text = \"%s. %s\" % [index, track.title] 15 | else: 16 | text = track.title 17 | 18 | func _on_QueueEntry_pressed(): 19 | Player.remove_from_queue(index) 20 | " 21 | 22 | [node name="QueueEntry" type="ToolButton"] 23 | anchor_right = 0.125 24 | anchor_bottom = 0.056 25 | margin_bottom = -0.256001 26 | text = "track" 27 | icon = ExtResource( 1 ) 28 | align = 0 29 | script = SubResource( 1 ) 30 | 31 | [connection signal="pressed" from="." to="." method="_on_QueueEntry_pressed"] 32 | -------------------------------------------------------------------------------- /Scenes/TrackPanelEntry.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [sub_resource type="GDScript" id=1] 4 | script/source = "extends Button 5 | 6 | export(Resource) var track setget _set_track 7 | 8 | func _set_track(new_value): 9 | track = new_value 10 | self.text = \"%s - %s\" % [track.artist, track.title] 11 | 12 | func _on_Track_pressed(): 13 | Player.add_to_queue(track) 14 | " 15 | 16 | [node name="Track" type="Button"] 17 | anchor_right = 0.187 18 | anchor_bottom = 0.056 19 | margin_right = 0.511993 20 | margin_bottom = -0.256001 21 | flat = true 22 | align = 0 23 | script = SubResource( 1 ) 24 | 25 | [connection signal="pressed" from="." to="." method="_on_Track_pressed"] 26 | -------------------------------------------------------------------------------- /Scripts/BottomBar.gd: -------------------------------------------------------------------------------- 1 | extends Panel 2 | 3 | # ------------------------------------------------------------------------------ 4 | onready var PlayPause: ToolButton = $MainControls/PlayPause 5 | onready var MainPlayer: AudioStreamPlayer = Global.main.find_node("MainPlayer") 6 | onready var VolumeSlider: HSlider = $VolumeSlider 7 | onready var DurationBar: HSlider = $DurationBar 8 | # ------------------------------------------------------------------------------ 9 | onready var PlayIcon: Texture = preload("res://Assets/MainControls/play.png") 10 | onready var PauseIcon: Texture = preload("res://Assets/MainControls/pause.png") 11 | # ------------------------------------------------------------------------------ 12 | var thread: Thread 13 | # ------------------------------------------------------------------------------ 14 | 15 | func _ready() -> void: 16 | thread = Thread.new() 17 | thread.start(self, "_position_updater") 18 | Player.connect("playback_started", self, "_update_progress") 19 | Player.connect("playback_started", self, "_update_playpause_icon") 20 | Player.connect("pause_changed", self, "_update_playpause_icon") 21 | 22 | func _exit_tree(): 23 | thread.wait_to_finish() 24 | 25 | # ------------------------------------------------------------------------------ 26 | 27 | func _update_progress() -> void: 28 | DurationBar.max_value = Player._get_duration() 29 | 30 | func _position_updater(): 31 | while true: 32 | DurationBar.value = Player._get_position() 33 | yield(get_tree().create_timer(1), "timeout") 34 | 35 | func _update_playpause_icon() -> void: 36 | if Player.Player.stream_paused == true: 37 | PlayPause.icon = PlayIcon 38 | else: 39 | PlayPause.icon = PauseIcon 40 | # ------------------------------------------------------------------------------ 41 | 42 | func _on_VolumeSlider_value_changed(value) -> void: 43 | MainPlayer.volume_db = value 44 | 45 | # ------------------------------------------------------------------------------ 46 | 47 | func _on_Queue_pressed(): 48 | $Queue/QueuePanel.visible = !$Queue/QueuePanel.visible 49 | 50 | func _on_Forward_pressed(): 51 | Player.skip() 52 | 53 | 54 | func _on_PlayPause_pressed(): 55 | Player.toggle_pause() 56 | -------------------------------------------------------------------------------- /Scripts/LeftBar.gd: -------------------------------------------------------------------------------- 1 | extends Panel 2 | # TODO: DOCS 3 | 4 | # ------------------------------------------------------------------------------ 5 | onready var LeftBarEntry: PackedScene = preload("res://Scenes/LeftBarEntry.tscn") 6 | onready var List: VBoxContainer = $ListScrollContainer/MainList 7 | onready var TrackPanel: Panel = Global.main.find_node("TrackPanel") 8 | # ------------------------------------------------------------------------------ 9 | 10 | func _ready() -> void: 11 | Global.connect("library_path_changed", self, "_reimport_library") 12 | var dir := Directory.new() 13 | if dir.file_exists("user://Library.tres"): 14 | var lib := load("user://Library.tres") 15 | Global.library = lib 16 | group_by_album() 17 | 18 | # ------------------------------------------------------------------------------ 19 | 20 | # TODO sorting 21 | 22 | # ------------------------------------------------------------------------------ 23 | 24 | func _clear() -> void: 25 | var items := List.get_children() 26 | for item in items: 27 | item.queue_free() 28 | if not Global.library: 29 | print("can't find library") 30 | return 31 | 32 | func group_by_album() -> void: 33 | _clear() 34 | for album in Global.library.albums: 35 | var list_item := LeftBarEntry.instance() 36 | list_item.album_title = album 37 | list_item.tracks = Global.library.albums[album] 38 | List.add_child(list_item) 39 | 40 | func group_by_artist() -> void: 41 | _clear() 42 | for artist in Global.library.artists: 43 | var list_item := LeftBarEntry.instance() 44 | list_item.album_title = artist 45 | list_item.tracks = Global.library.artists[artist] 46 | List.add_child(list_item) 47 | 48 | func _reimport_library(files: Array) -> void: 49 | var lib := LibraryFile.new() 50 | for path in files: 51 | if not path.ends_with(".mp3"): 52 | continue 53 | var track := TrackFile.new() 54 | # parse track 55 | track = Tag.read_ID3(path) 56 | if track.title == "": 57 | print("failed to parse tags, falling back to %s" % path) 58 | track.title = path 59 | lib.tracks.append(track) 60 | Global.library = lib 61 | ResourceSaver.save("user://Library.tres", lib) 62 | _get_albums() 63 | group_by_album() 64 | 65 | func _get_albums() -> void: 66 | var lib := Global.library 67 | var albums = {} 68 | for track in lib.tracks: 69 | if track.album == "": 70 | continue 71 | 72 | if albums.keys().has(track.album): 73 | albums[track.album].append(track) 74 | else: 75 | albums[track.album] = [] 76 | albums[track.album].append(track) 77 | lib.albums = albums 78 | Global.library = lib 79 | ResourceSaver.save("user://Library.tres", lib) 80 | _get_artists() 81 | 82 | func _get_artists() -> void: 83 | var lib := Global.library 84 | var artists = {} 85 | for track in lib.tracks: 86 | if track.artist == "": 87 | continue 88 | 89 | if artists.keys().has(track.artist): 90 | artists[track.artist].append(track) 91 | else: 92 | artists[track.artist] = [] 93 | artists[track.artist].append(track) 94 | lib.artists = artists 95 | Global.library = lib 96 | ResourceSaver.save("user://Library.tres", lib) 97 | 98 | 99 | func _on_GroupArtist_pressed(): 100 | group_by_artist() 101 | 102 | func _on_GroupAlbum_pressed(): 103 | group_by_album() 104 | -------------------------------------------------------------------------------- /Scripts/QueueSideBar.gd: -------------------------------------------------------------------------------- 1 | extends Panel 2 | 3 | # ------------------------------------------------------------------------------ 4 | onready var List: VBoxContainer = $ScrollContainer/QueueList 5 | onready var Entry: PackedScene = preload("res://Scenes/QueueEntry.tscn") 6 | # ------------------------------------------------------------------------------ 7 | 8 | func _ready() -> void: 9 | Player.connect("queue_updated", self, "_update_list") 10 | 11 | func _update_list() -> void: 12 | for entry in List.get_children(): 13 | entry.queue_free() 14 | var i := 0 15 | for track in Player.queue: 16 | var entry := Entry.instance() 17 | entry.index = i 18 | entry.track = track 19 | List.add_child(entry) 20 | i += 1 21 | 22 | # ------------------------------------------------------------------------------ 23 | -------------------------------------------------------------------------------- /Scripts/TopBar.gd: -------------------------------------------------------------------------------- 1 | extends Panel 2 | # TODO: DOCS 3 | 4 | # ------------------------------------------------------------------------------ 5 | onready var file_menu: MenuButton = $Container/File 6 | onready var file_dialog: FileDialog = Global.main.find_node("FileDialog") 7 | # ------------------------------------------------------------------------------ 8 | 9 | func _ready() -> void: 10 | _setup_file_menu(file_menu) 11 | 12 | # ------------------------------------------------------------------------------ 13 | # This section contains setup functions for the FILE menu 14 | 15 | func _setup_file_menu(menu: MenuButton) -> void: 16 | var popup := menu.get_popup() 17 | var entries := [ 18 | "Import Library" 19 | ] 20 | 21 | var i := 0 22 | for item in entries: 23 | popup.add_item(item, i) 24 | i += 1 25 | popup.connect("id_pressed", self, "_file_menu_pressed") 26 | 27 | func _file_menu_pressed(id: int) -> void: 28 | match id: 29 | 0: 30 | import_library() 31 | 32 | # ------------------------------------------------------------------------------ 33 | # This section contains utility functions for the FILE menu 34 | 35 | func import_library() -> void: 36 | file_dialog.popup() 37 | 38 | func _file_dialog_dir_selected(dir): 39 | Global.library_path = dir 40 | 41 | # ------------------------------------------------------------------------------ 42 | -------------------------------------------------------------------------------- /Scripts/TrackPanel.gd: -------------------------------------------------------------------------------- 1 | extends Panel 2 | 3 | onready var List: VBoxContainer = $TrackPanelScroll/GroupList 4 | onready var Entry: PackedScene = load("res://Scenes/TrackPanelEntry.tscn") 5 | func view_album(album_title: String, tracks: Array) -> void: 6 | _clear() 7 | for track in tracks: 8 | var entry := Entry.instance() 9 | entry.track = track 10 | List.add_child(entry) 11 | 12 | func _clear() -> void: 13 | var children := List.get_children() 14 | for child in children: 15 | child.queue_free() 16 | -------------------------------------------------------------------------------- /build/PMP.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/build/PMP.7z -------------------------------------------------------------------------------- /build/PMP/PMP.pck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/build/PMP/PMP.pck -------------------------------------------------------------------------------- /build/PMP/PMP.x86_64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/build/PMP/PMP.x86_64 -------------------------------------------------------------------------------- /concept.lorien: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/concept.lorien -------------------------------------------------------------------------------- /default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=2] 2 | 3 | [sub_resource type="ProceduralSky" id=1] 4 | 5 | [resource] 6 | background_mode = 2 7 | background_sky = SubResource( 1 ) 8 | background_color = Color( 0.831373, 0.223529, 0.223529, 1 ) 9 | -------------------------------------------------------------------------------- /export_presets.cfg: -------------------------------------------------------------------------------- 1 | [preset.0] 2 | 3 | name="Linux/X11" 4 | platform="Linux/X11" 5 | runnable=true 6 | custom_features="" 7 | export_filter="all_resources" 8 | include_filter="" 9 | exclude_filter="" 10 | export_path="build/PMP.x86_64" 11 | script_export_mode=1 12 | script_encryption_key="" 13 | 14 | [preset.0.options] 15 | 16 | custom_template/debug="" 17 | custom_template/release="" 18 | binary_format/64_bits=true 19 | binary_format/embed_pck=false 20 | texture_format/bptc=false 21 | texture_format/s3tc=true 22 | texture_format/etc=false 23 | texture_format/etc2=false 24 | texture_format/no_bptc_fallbacks=true 25 | 26 | [preset.1] 27 | 28 | name="Windows Desktop" 29 | platform="Windows Desktop" 30 | runnable=true 31 | custom_features="" 32 | export_filter="all_resources" 33 | include_filter="" 34 | exclude_filter="" 35 | export_path="build/PMP.exe" 36 | script_export_mode=1 37 | script_encryption_key="" 38 | 39 | [preset.1.options] 40 | 41 | custom_template/debug="" 42 | custom_template/release="" 43 | binary_format/64_bits=true 44 | binary_format/embed_pck=false 45 | texture_format/bptc=false 46 | texture_format/s3tc=true 47 | texture_format/etc=false 48 | texture_format/etc2=false 49 | texture_format/no_bptc_fallbacks=true 50 | codesign/enable=false 51 | codesign/identity="" 52 | codesign/password="" 53 | codesign/timestamp=true 54 | codesign/timestamp_server_url="" 55 | codesign/digest_algorithm=1 56 | codesign/description="" 57 | codesign/custom_options=PoolStringArray( ) 58 | application/icon="" 59 | application/file_version="" 60 | application/product_version="" 61 | application/company_name="" 62 | application/product_name="" 63 | application/file_description="" 64 | application/copyright="" 65 | application/trademarks="" 66 | 67 | [preset.2] 68 | 69 | name="Android" 70 | platform="Android" 71 | runnable=true 72 | custom_features="" 73 | export_filter="all_resources" 74 | include_filter="" 75 | exclude_filter="" 76 | export_path="" 77 | script_export_mode=1 78 | script_encryption_key="" 79 | 80 | [preset.2.options] 81 | 82 | custom_template/debug="" 83 | custom_template/release="" 84 | custom_template/use_custom_build=false 85 | custom_template/export_format=0 86 | architectures/armeabi-v7a=true 87 | architectures/arm64-v8a=true 88 | architectures/x86=false 89 | architectures/x86_64=false 90 | keystore/debug="" 91 | keystore/debug_user="" 92 | keystore/debug_password="" 93 | keystore/release="" 94 | keystore/release_user="" 95 | keystore/release_password="" 96 | one_click_deploy/clear_previous_install=false 97 | version/code=1 98 | version/name="1.0" 99 | version/min_sdk=19 100 | version/target_sdk=30 101 | package/unique_name="org.godotengine.$genname" 102 | package/name="" 103 | package/signed=true 104 | package/classify_as_game=true 105 | package/retain_data_on_uninstall=false 106 | package/exclude_from_recents=false 107 | launcher_icons/main_192x192="" 108 | launcher_icons/adaptive_foreground_432x432="" 109 | launcher_icons/adaptive_background_432x432="" 110 | graphics/32_bits_framebuffer=true 111 | graphics/opengl_debug=false 112 | xr_features/xr_mode=0 113 | xr_features/hand_tracking=0 114 | xr_features/hand_tracking_frequency=0 115 | xr_features/passthrough=0 116 | screen/immersive_mode=true 117 | screen/support_small=true 118 | screen/support_normal=true 119 | screen/support_large=true 120 | screen/support_xlarge=true 121 | user_data_backup/allow=false 122 | command_line/extra_args="" 123 | apk_expansion/enable=false 124 | apk_expansion/SALT="" 125 | apk_expansion/public_key="" 126 | permissions/custom_permissions=PoolStringArray( ) 127 | permissions/access_checkin_properties=false 128 | permissions/access_coarse_location=false 129 | permissions/access_fine_location=false 130 | permissions/access_location_extra_commands=false 131 | permissions/access_mock_location=false 132 | permissions/access_network_state=false 133 | permissions/access_surface_flinger=false 134 | permissions/access_wifi_state=false 135 | permissions/account_manager=false 136 | permissions/add_voicemail=false 137 | permissions/authenticate_accounts=false 138 | permissions/battery_stats=false 139 | permissions/bind_accessibility_service=false 140 | permissions/bind_appwidget=false 141 | permissions/bind_device_admin=false 142 | permissions/bind_input_method=false 143 | permissions/bind_nfc_service=false 144 | permissions/bind_notification_listener_service=false 145 | permissions/bind_print_service=false 146 | permissions/bind_remoteviews=false 147 | permissions/bind_text_service=false 148 | permissions/bind_vpn_service=false 149 | permissions/bind_wallpaper=false 150 | permissions/bluetooth=false 151 | permissions/bluetooth_admin=false 152 | permissions/bluetooth_privileged=false 153 | permissions/brick=false 154 | permissions/broadcast_package_removed=false 155 | permissions/broadcast_sms=false 156 | permissions/broadcast_sticky=false 157 | permissions/broadcast_wap_push=false 158 | permissions/call_phone=false 159 | permissions/call_privileged=false 160 | permissions/camera=false 161 | permissions/capture_audio_output=false 162 | permissions/capture_secure_video_output=false 163 | permissions/capture_video_output=false 164 | permissions/change_component_enabled_state=false 165 | permissions/change_configuration=false 166 | permissions/change_network_state=false 167 | permissions/change_wifi_multicast_state=false 168 | permissions/change_wifi_state=false 169 | permissions/clear_app_cache=false 170 | permissions/clear_app_user_data=false 171 | permissions/control_location_updates=false 172 | permissions/delete_cache_files=false 173 | permissions/delete_packages=false 174 | permissions/device_power=false 175 | permissions/diagnostic=false 176 | permissions/disable_keyguard=false 177 | permissions/dump=false 178 | permissions/expand_status_bar=false 179 | permissions/factory_test=false 180 | permissions/flashlight=false 181 | permissions/force_back=false 182 | permissions/get_accounts=false 183 | permissions/get_package_size=false 184 | permissions/get_tasks=false 185 | permissions/get_top_activity_info=false 186 | permissions/global_search=false 187 | permissions/hardware_test=false 188 | permissions/inject_events=false 189 | permissions/install_location_provider=false 190 | permissions/install_packages=false 191 | permissions/install_shortcut=false 192 | permissions/internal_system_window=false 193 | permissions/internet=false 194 | permissions/kill_background_processes=false 195 | permissions/location_hardware=false 196 | permissions/manage_accounts=false 197 | permissions/manage_app_tokens=false 198 | permissions/manage_documents=false 199 | permissions/master_clear=false 200 | permissions/media_content_control=false 201 | permissions/modify_audio_settings=false 202 | permissions/modify_phone_state=false 203 | permissions/mount_format_filesystems=false 204 | permissions/mount_unmount_filesystems=false 205 | permissions/nfc=false 206 | permissions/persistent_activity=false 207 | permissions/process_outgoing_calls=false 208 | permissions/read_calendar=false 209 | permissions/read_call_log=false 210 | permissions/read_contacts=false 211 | permissions/read_external_storage=false 212 | permissions/read_frame_buffer=false 213 | permissions/read_history_bookmarks=false 214 | permissions/read_input_state=false 215 | permissions/read_logs=false 216 | permissions/read_phone_state=false 217 | permissions/read_profile=false 218 | permissions/read_sms=false 219 | permissions/read_social_stream=false 220 | permissions/read_sync_settings=false 221 | permissions/read_sync_stats=false 222 | permissions/read_user_dictionary=false 223 | permissions/reboot=false 224 | permissions/receive_boot_completed=false 225 | permissions/receive_mms=false 226 | permissions/receive_sms=false 227 | permissions/receive_wap_push=false 228 | permissions/record_audio=false 229 | permissions/reorder_tasks=false 230 | permissions/restart_packages=false 231 | permissions/send_respond_via_message=false 232 | permissions/send_sms=false 233 | permissions/set_activity_watcher=false 234 | permissions/set_alarm=false 235 | permissions/set_always_finish=false 236 | permissions/set_animation_scale=false 237 | permissions/set_debug_app=false 238 | permissions/set_orientation=false 239 | permissions/set_pointer_speed=false 240 | permissions/set_preferred_applications=false 241 | permissions/set_process_limit=false 242 | permissions/set_time=false 243 | permissions/set_time_zone=false 244 | permissions/set_wallpaper=false 245 | permissions/set_wallpaper_hints=false 246 | permissions/signal_persistent_processes=false 247 | permissions/status_bar=false 248 | permissions/subscribed_feeds_read=false 249 | permissions/subscribed_feeds_write=false 250 | permissions/system_alert_window=false 251 | permissions/transmit_ir=false 252 | permissions/uninstall_shortcut=false 253 | permissions/update_device_stats=false 254 | permissions/use_credentials=false 255 | permissions/use_sip=false 256 | permissions/vibrate=false 257 | permissions/wake_lock=false 258 | permissions/write_apn_settings=false 259 | permissions/write_calendar=false 260 | permissions/write_call_log=false 261 | permissions/write_contacts=false 262 | permissions/write_external_storage=false 263 | permissions/write_gservices=false 264 | permissions/write_history_bookmarks=false 265 | permissions/write_profile=false 266 | permissions/write_secure_settings=false 267 | permissions/write_settings=false 268 | permissions/write_sms=false 269 | permissions/write_social_stream=false 270 | permissions/write_sync_settings=false 271 | permissions/write_user_dictionary=false 272 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoltenCoreDev/PixelMusicPlayer/c023bf37688725751a731dbacd779f665b3d58da/icon.png -------------------------------------------------------------------------------- /icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://icon.png" 13 | dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=true 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=4 10 | 11 | _global_script_classes=[ { 12 | "base": "Resource", 13 | "class": "AlbumFile", 14 | "language": "GDScript", 15 | "path": "res://Resources/AlbumFile.gd" 16 | }, { 17 | "base": "Resource", 18 | "class": "LibraryFile", 19 | "language": "GDScript", 20 | "path": "res://Resources/LibraryFile.gd" 21 | }, { 22 | "base": "Resource", 23 | "class": "TrackFile", 24 | "language": "GDScript", 25 | "path": "res://Resources/TrackFile.gd" 26 | } ] 27 | _global_script_class_icons={ 28 | "AlbumFile": "", 29 | "LibraryFile": "", 30 | "TrackFile": "" 31 | } 32 | 33 | [application] 34 | 35 | config/name="Pixel Music Player" 36 | run/main_scene="res://Main.tscn" 37 | config/icon="res://icon.png" 38 | 39 | [autoload] 40 | 41 | Global="*res://API/Global.gd" 42 | Player="*res://API/Player.gd" 43 | Tag="*res://API/Tag.gd" 44 | 45 | [display] 46 | 47 | window/size/height=576 48 | 49 | [importer_defaults] 50 | 51 | mp3={ 52 | "loop": false, 53 | "loop_offset": 0 54 | } 55 | texture={ 56 | "compress/bptc_ldr": 0, 57 | "compress/hdr_mode": 0, 58 | "compress/lossy_quality": 0.7, 59 | "compress/mode": 0, 60 | "compress/normal_map": 0, 61 | "detect_3d": false, 62 | "flags/anisotropic": false, 63 | "flags/filter": false, 64 | "flags/mipmaps": false, 65 | "flags/repeat": 0, 66 | "flags/srgb": 2, 67 | "process/HDR_as_SRGB": false, 68 | "process/fix_alpha_border": true, 69 | "process/invert_color": false, 70 | "process/normal_map_invert_y": false, 71 | "process/premult_alpha": false, 72 | "size_limit": 0, 73 | "stream": false, 74 | "svg/scale": 1.0 75 | } 76 | 77 | [physics] 78 | 79 | common/enable_pause_aware_picking=true 80 | 81 | [rendering] 82 | 83 | environment/default_environment="res://default_env.tres" 84 | -------------------------------------------------------------------------------- /roadmap.md: -------------------------------------------------------------------------------- 1 | # godot music player (name subject to change) 2 | 3 | ## 0.0 4 | 5 | - [x] top bar 6 | - [x] library save system 7 | 8 | ## 0.1 9 | - [x] bottom bar (play/pause/stop/next/previous/volume/repeat/shuffle) 10 | - [x] actual music playback (supprt for mp3) 11 | - [x] queue system! 12 | 13 | ## 0.2 14 | - [ ] list view by album, author, etc. (mp3 tags) 15 | 16 | ## 0.3 17 | - [ ] support for wav, ogg, flac 18 | 19 | ## 0.4 20 | - [ ] support for m4a 21 | - [ ] fully fledged tag editor 22 | 23 | ## considered goals / not included for a release yet 24 | - tag editor 25 | - lyrics viewer 26 | - last.fm scrobbling 27 | - exstension support 28 | - theming 29 | 30 | ## name ideas: 31 | - Delton 32 | - Soundwave System 33 | - Decibelius 34 | - Linux Musicbox 35 | - Pixel Music Player <3 36 | --------------------------------------------------------------------------------