├── icon.ico
├── icon.png
├── splash.png
├── assets
├── fonts
│ ├── wqy-MicroHei.ttf
│ ├── IBMPlexMono-Bold.ttf
│ ├── IBMPlexSans-Light.ttf
│ ├── IBMPlexMono-Regular.ttf
│ └── IBMPlexSans-Regular.ttf
├── logo.svg.import
├── ic_help.svg.import
├── ic_info.svg.import
├── ic_logo.svg.import
├── ic_loop.svg.import
├── ic_note.svg.import
├── ic_play.svg.import
├── ic_stop.svg.import
├── ic_clear.svg.import
├── ic_folder.svg.import
├── ic_autoplay.svg.import
├── ic_favorite.svg.import
├── ic_unfavorite.svg.import
├── ic_folder_full.svg.import
├── ic_direction_down.svg.import
├── ic_direction_right.svg.import
├── ic_play.svg
├── ic_direction_down.svg
├── ic_direction_right.svg
├── ic_clear.svg
├── ic_folder_full.svg
├── ic_folder.svg
├── ic_autoplay.svg
├── ic_favorite.svg
├── ic_loop.svg
├── ic_logo.svg
├── ic_note.svg
├── ic_stop.svg
├── ic_unfavorite.svg
├── ic_info.svg
├── ic_help.svg
├── logo.svg
└── ui_theme.tres
├── locale
├── locales.en.translation
├── locales.csv.import
└── locales.csv
├── src
├── InfoPlaylist.gd
├── MessageBox.gd
├── HelpPanel.gd
├── InfoBox.gd
├── AnalizeThread.gd
├── Config.gd
├── ItemContainer.gd
├── Export.gd
├── Main.gd
├── Playback.gd
├── DirectoryBrowser.gd
├── Playlist.gd
└── GDScriptAudioImport.gd
├── .gitignore
├── default_env.tres
├── icon.png.import
├── splash.png.import
├── LICENSE
├── project.godot
├── README.md
├── ItemContainer.tscn
└── Main.tscn
/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelriot/SFX-Browser/HEAD/icon.ico
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelriot/SFX-Browser/HEAD/icon.png
--------------------------------------------------------------------------------
/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelriot/SFX-Browser/HEAD/splash.png
--------------------------------------------------------------------------------
/assets/fonts/wqy-MicroHei.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelriot/SFX-Browser/HEAD/assets/fonts/wqy-MicroHei.ttf
--------------------------------------------------------------------------------
/locale/locales.en.translation:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelriot/SFX-Browser/HEAD/locale/locales.en.translation
--------------------------------------------------------------------------------
/assets/fonts/IBMPlexMono-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelriot/SFX-Browser/HEAD/assets/fonts/IBMPlexMono-Bold.ttf
--------------------------------------------------------------------------------
/assets/fonts/IBMPlexSans-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelriot/SFX-Browser/HEAD/assets/fonts/IBMPlexSans-Light.ttf
--------------------------------------------------------------------------------
/assets/fonts/IBMPlexMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelriot/SFX-Browser/HEAD/assets/fonts/IBMPlexMono-Regular.ttf
--------------------------------------------------------------------------------
/assets/fonts/IBMPlexSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelriot/SFX-Browser/HEAD/assets/fonts/IBMPlexSans-Regular.ttf
--------------------------------------------------------------------------------
/src/InfoPlaylist.gd:
--------------------------------------------------------------------------------
1 | extends HBoxContainer
2 | """
3 | InfoPlaylist
4 | """
5 |
6 |
7 |
8 |
9 | func hide(_path=null) -> void:
10 | .hide()
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Godot-specific ignores
3 | .import/
4 | export.cfg
5 | export_presets.cfg
6 | exports
7 |
8 | # Mono-specific ignores
9 | .mono/
10 | data_*/
11 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/locale/locales.csv.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="csv_translation"
4 | type="Translation"
5 |
6 | [deps]
7 |
8 | files=[ "res://locale/locales.en.translation" ]
9 |
10 | source_file="res://locale/locales.csv"
11 | dest_files=[ "res://locale/locales.en.translation" ]
12 |
13 | [params]
14 |
15 | compress=true
16 | delimiter=0
17 |
--------------------------------------------------------------------------------
/src/MessageBox.gd:
--------------------------------------------------------------------------------
1 | extends Control
2 | """
3 | Message Box
4 | """
5 |
6 | func _ready() -> void:
7 | modulate.a = 1
8 | hide()
9 |
10 |
11 | func display_message(_text:String, _color:Color=Config.THEME_COLOR_RED) -> void:
12 | modulate.a = 1
13 | show()
14 | get("custom_styles/panel").bg_color = _color
15 | $MarginContainer/HBoxContainer/Label.text = _text
16 | $Timer.start()
17 |
18 |
19 | func _on_Timer_timeout() -> void:
20 | $AnimationPlayer.play("hide")
21 |
22 |
23 | func _on_Close_pressed() -> void:
24 | $Timer.stop()
25 | _on_Timer_timeout()
26 |
--------------------------------------------------------------------------------
/src/HelpPanel.gd:
--------------------------------------------------------------------------------
1 | extends PanelContainer
2 | """
3 | Help Panels
4 | """
5 |
6 | func _ready() -> void:
7 | for label in $MarginContainer/HBoxContainer.get_children():
8 | if label is Label:
9 | label.text = tr(label.name.to_upper())
10 | if Config.CONFIGDATA["main"]["folder_path"]:
11 | hide()
12 | else:
13 | show()
14 |
15 |
16 | func close(_path=null) -> void:
17 | _on_Close_pressed()
18 |
19 |
20 | func _on_Close_pressed() -> void:
21 | $AnimationPlayer.play("hide")
22 |
23 |
24 | func show() -> void:
25 | modulate.a = 1
26 | .show()
27 |
28 |
29 |
--------------------------------------------------------------------------------
/locale/locales.csv:
--------------------------------------------------------------------------------
1 | id,en
2 | APP_TITLE,Sample Browser
3 | APP_INFO,Version %s \nDeveloped by Monolith of Minds
4 | LOAD,Library
5 | LOAD_POPUP,Select sample library folder
6 | INFOBROWSER,ctrl + o \n\nStart by selecting which folder you want to rummage through.
7 | INFO0,↑ & ↓ \n\nQuickly move though your library.
8 | INFO1,Space or LMB \n\nPlay the selected sample. \nRMB to Stop playback.
9 | INFO2,F \n\nMark the selected sample as a favourite.
10 | INFO3,abc... \n\nEnter a new name for the sample after export.
11 | CLEAR,clear all
12 | EXPORT,Export
13 | EXPORT_POPUP,Select export directory
14 | NO_EXPORT_FILES,"Nothing to export. Enter new export file names for the files you wish to export."
15 | EXPORT_INFO,%s file(s) exported to %s
16 |
--------------------------------------------------------------------------------
/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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/splash.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/splash.png-929ed8a00b89ba36c51789452f874c77.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://splash.png"
13 | dest_files=[ "res://.import/splash.png-929ed8a00b89ba36c51789452f874c77.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/logo.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/logo.svg-01597fe4b7eb446be26a49e8a22b6f42.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/logo.svg"
13 | dest_files=[ "res://.import/logo.svg-01597fe4b7eb446be26a49e8a22b6f42.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/src/InfoBox.gd:
--------------------------------------------------------------------------------
1 | extends PanelContainer
2 | """
3 | Info Box
4 | """
5 |
6 | func _ready() -> void:
7 | var version = ProjectSettings["application/config/version"]
8 | var _text = ""
9 | _text += tr("APP_INFO") % [version] + "\n"
10 | _text += "[url=https://github.com/pixelriot/SFX-Browser]" + "Visit us on Github" + "[/url]" + "\n"
11 |
12 | $MarginContainer/HBoxContainer/RichTextLabel.bbcode_enabled = true
13 | $MarginContainer/HBoxContainer/RichTextLabel.bbcode_text = _text
14 | hide()
15 |
16 |
17 | func close(_path=null) -> void:
18 | _on_Close_pressed()
19 |
20 |
21 | func _on_Close_pressed() -> void:
22 | $AnimationPlayer.play("hide")
23 |
24 |
25 | func show() -> void:
26 | modulate.a = 1
27 | .show()
28 |
29 |
30 | func _on_RichTextLabel_meta_clicked(meta) -> void:
31 | OS.shell_open(meta)
32 |
--------------------------------------------------------------------------------
/assets/ic_help.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_help.svg-457a991545389554bc9c59bbb421cb7a.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_help.svg"
13 | dest_files=[ "res://.import/ic_help.svg-457a991545389554bc9c59bbb421cb7a.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/ic_info.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_info.svg-59f7ced217781e851eabc5db1d7034f0.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_info.svg"
13 | dest_files=[ "res://.import/ic_info.svg-59f7ced217781e851eabc5db1d7034f0.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/ic_logo.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_logo.svg-778a3f21ae113f22fce2622c6527dad3.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_logo.svg"
13 | dest_files=[ "res://.import/ic_logo.svg-778a3f21ae113f22fce2622c6527dad3.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/ic_loop.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_loop.svg-932d7f8438d3b65cbabfb484d9b292ea.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_loop.svg"
13 | dest_files=[ "res://.import/ic_loop.svg-932d7f8438d3b65cbabfb484d9b292ea.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/ic_note.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_note.svg-d6678e311e88a8f00f7cad7d7a71a6b0.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_note.svg"
13 | dest_files=[ "res://.import/ic_note.svg-d6678e311e88a8f00f7cad7d7a71a6b0.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/ic_play.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_play.svg-196841356150a3abc9cf15fb31332047.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_play.svg"
13 | dest_files=[ "res://.import/ic_play.svg-196841356150a3abc9cf15fb31332047.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/ic_stop.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_stop.svg-f8cd9033b2d74858b28c6479ed337622.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_stop.svg"
13 | dest_files=[ "res://.import/ic_stop.svg-f8cd9033b2d74858b28c6479ed337622.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/ic_clear.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_clear.svg-4a1d07859e0d5848b82a7e3890c2e13d.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_clear.svg"
13 | dest_files=[ "res://.import/ic_clear.svg-4a1d07859e0d5848b82a7e3890c2e13d.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/ic_folder.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_folder.svg-b838b4ed680d0e6fa39987f926b50064.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_folder.svg"
13 | dest_files=[ "res://.import/ic_folder.svg-b838b4ed680d0e6fa39987f926b50064.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/ic_autoplay.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_autoplay.svg-ed81d88702bff6f65acd8b235bd84f9f.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_autoplay.svg"
13 | dest_files=[ "res://.import/ic_autoplay.svg-ed81d88702bff6f65acd8b235bd84f9f.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/ic_favorite.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_favorite.svg-ce5fb6048012041e169142b1e623e428.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_favorite.svg"
13 | dest_files=[ "res://.import/ic_favorite.svg-ce5fb6048012041e169142b1e623e428.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/src/AnalizeThread.gd:
--------------------------------------------------------------------------------
1 | extends Node
2 | """
3 | Analyze Audio Samples
4 | """
5 | var analysis_finished = false
6 | var _thread
7 | var lengths = []
8 |
9 | func analyze_files(file_paths=[]) -> void:
10 | if _thread:
11 | var _t = _thread.wait_to_finish()
12 | _thread = Thread.new()
13 | _thread.start(self, "_analyze", file_paths)
14 |
15 |
16 | func _analyze(file_paths=[]) -> void:
17 | print("analysis files ...")
18 | analysis_finished = false
19 | lengths.clear()
20 | for path in file_paths:
21 | var stream = AudioImport.loadfile(path)
22 | if stream:
23 | lengths.append(stream.get_length())
24 | analysis_finished = true
25 | print("... finished")
26 |
27 |
28 | func get_data()-> Array:
29 | analysis_finished = false
30 | return lengths
31 |
32 |
33 | func _exit_tree():
34 | if _thread:
35 | _thread.wait_to_finish()
36 |
--------------------------------------------------------------------------------
/assets/ic_unfavorite.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_unfavorite.svg-22c180c87ef3a149adc9109a0b702d10.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_unfavorite.svg"
13 | dest_files=[ "res://.import/ic_unfavorite.svg-22c180c87ef3a149adc9109a0b702d10.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/ic_folder_full.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_folder_full.svg-fcffcebf1440bd37abba92cf4bb8dba0.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_folder_full.svg"
13 | dest_files=[ "res://.import/ic_folder_full.svg-fcffcebf1440bd37abba92cf4bb8dba0.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/ic_direction_down.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_direction_down.svg-83c1c1233d3a77e3c442e1e4b800a676.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_direction_down.svg"
13 | dest_files=[ "res://.import/ic_direction_down.svg-83c1c1233d3a77e3c442e1e4b800a676.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/assets/ic_direction_right.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/ic_direction_right.svg-7f1d9c03e219f0d81f7a3550decd8c95.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://assets/ic_direction_right.svg"
13 | dest_files=[ "res://.import/ic_direction_right.svg-7f1d9c03e219f0d81f7a3550decd8c95.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 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Richi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/assets/ic_play.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/src/Config.gd:
--------------------------------------------------------------------------------
1 | extends Node
2 | """
3 | Config
4 | """
5 | var CONFIG_PATH = OS.get_user_data_dir() + "/config.cfg"
6 | var CONFIGDATA = { "main":{
7 | "folder_path": "",
8 | "export_path": ""
9 | }}
10 | var FAVOURITES = []
11 |
12 | const THEME_COLOR_GREEN = Color("ceeac7")
13 | const THEME_COLOR_BLUE = Color("bbd2d1")
14 | const THEME_COLOR_RED = Color("d67788")
15 | const THEME_COLOR_BG = Color("464655")
16 |
17 |
18 | func _init() -> void:
19 | print("SFX Browser starting")
20 | print("OS \t" + OS.get_name())
21 | connect("tree_exiting", self, "save_config")
22 | load_config()
23 |
24 |
25 | func load_config() -> void:
26 | var c = ConfigFile.new()
27 | var err = c.load(CONFIG_PATH)
28 | if err == OK:
29 | for i in CONFIGDATA:
30 | print("" + str(i))
31 | for j in CONFIGDATA[i]:
32 | if c.has_section_key(i, j):
33 | CONFIGDATA[i][j] = c.get_value(i, j)
34 | print("--" + str(j) + " = " + str(CONFIGDATA[i][j]))
35 | FAVOURITES = c.get_value("main", "favourites", [])
36 |
37 |
38 | func save_config():
39 | CONFIGDATA["main"]["favourites"] = FAVOURITES
40 |
41 | var c = ConfigFile.new()
42 | c.load(CONFIG_PATH)
43 | for i in CONFIGDATA:
44 | for j in CONFIGDATA[i]:
45 | c.set_value(i, j, CONFIGDATA[i][j])
46 | c.save(CONFIG_PATH)
47 |
48 |
49 |
--------------------------------------------------------------------------------
/assets/ic_direction_down.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/assets/ic_direction_right.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/assets/ic_clear.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/assets/ic_folder_full.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/assets/ic_folder.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/assets/ic_autoplay.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/assets/ic_favorite.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/assets/ic_loop.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/src/ItemContainer.gd:
--------------------------------------------------------------------------------
1 | extends HBoxContainer
2 | """
3 | Item Container
4 | """
5 | var file_path : String
6 |
7 | func set_data(idx:String, _file_path:String) -> void:
8 | file_path = _file_path
9 | $Idx.text = idx
10 | $File.text = file_path.get_file()
11 | $File.hint_tooltip = _file_path
12 | if file_path in Config.FAVOURITES:
13 | $Favourite.pressed = true
14 | unfocus()
15 |
16 |
17 | func set_additional_data(length:float) -> void:
18 | var minutes = int(length)/60
19 | if minutes > 0:
20 | var seconds = length - minutes * 60
21 | $Length.text = ( str(minutes) + ":" + str(seconds).pad_decimals(2) )
22 | else:
23 | $Length.text = ( str(length).pad_decimals(2) )
24 |
25 |
26 | func get_file_path() -> String:
27 | return file_path
28 |
29 |
30 | func get_export_name() -> String:
31 | return $ExportName.text
32 |
33 |
34 | func clear_export() -> void:
35 | $ExportName.text = ""
36 |
37 |
38 | func _on_ItemContainer_focus_entered() -> void:
39 | modulate.a = 1
40 | $Icon.modulate.a = 1
41 |
42 |
43 | func unfocus() -> void:
44 | modulate.a = 0.9
45 | $Icon.modulate.a = 0
46 |
47 |
48 | func _on_Favourite_toggled(button_pressed: bool) -> void:
49 | if button_pressed:
50 | if not file_path in Config.FAVOURITES:
51 | Config.FAVOURITES.append(file_path)
52 | else:
53 | if file_path in Config.FAVOURITES:
54 | Config.FAVOURITES.erase(file_path)
55 |
56 |
57 | func toggle_favourite() -> void:
58 | $Favourite.pressed = not $Favourite.pressed
59 |
60 |
61 |
--------------------------------------------------------------------------------
/assets/ic_logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/assets/ic_note.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/src/Export.gd:
--------------------------------------------------------------------------------
1 | extends HBoxContainer
2 | """
3 | Export
4 | """
5 | signal export_files(path)
6 | signal display_message(message)
7 | signal clear_export
8 | onready var Export := $Export
9 | onready var FolderPath := $FolderPath
10 | onready var FileDialog := $FileDialog
11 | var export_path : String
12 |
13 | func _ready() -> void:
14 | $Clear.text = tr("CLEAR")
15 | Export.text = tr("EXPORT")
16 |
17 | if Config.CONFIGDATA["main"]["export_path"]:
18 | export_path = Config.CONFIGDATA["main"]["export_path"]
19 | FolderPath.text = export_path
20 |
21 |
22 | func _on_Clear_pressed() -> void:
23 | emit_signal("clear_export")
24 |
25 |
26 | func _on_ExportPath_pressed() -> void:
27 | FileDialog.window_title = tr("EXPORT_POPUP")
28 | var popup_size = Vector2(800, 400)
29 | var popup_position = OS.window_size/2 - popup_size/2
30 | FileDialog.popup(Rect2(popup_position, popup_size))
31 |
32 |
33 | func _on_FileDialog_dir_selected(dir: String) -> void:
34 | export_path = dir
35 | FolderPath.text = export_path
36 | Config.CONFIGDATA["main"]["export_path"] = export_path
37 | Config.save_config()
38 |
39 |
40 | func _on_Export_pressed():
41 | if export_path == "":
42 | _on_ExportPath_pressed()
43 | else:
44 | emit_signal("export_files", export_path)
45 |
46 |
47 | func export_finished(amount:int) -> void:
48 | if amount == 0:
49 | emit_signal("display_message", tr("NO_EXPORT_FILES"))
50 | else:
51 | emit_signal("display_message", tr("EXPORT_INFO") % [str(amount), export_path], Config.THEME_COLOR_GREEN)
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/Main.gd:
--------------------------------------------------------------------------------
1 | extends Control
2 | """
3 | Godot audio sample manager
4 | """
5 | onready var DirectoryBrowser := $PanelContainer/MarginContainer/DirectoryBrowser
6 | onready var Playback := $MarginContainer/Workbench/Playback
7 | onready var Playlist := $MarginContainer/Workbench/Playlist
8 | onready var Export := $MarginContainer/Workbench/Export
9 | onready var BrowserHelp := $PanelContainer/MarginContainer/DirectoryBrowser/BrowserHelp
10 | onready var PlaybackHelp := $MarginContainer/Workbench/PlaybackHelp
11 | onready var InfoBox := $MarginContainer/Workbench/InfoBox
12 | onready var MessageBox := $MarginContainer/Workbench/MessageBox
13 |
14 | func _ready() -> void:
15 | VisualServer.set_default_clear_color(Config.THEME_COLOR_BG)
16 |
17 | DirectoryBrowser.connect("directory_changed", Playlist, "load_files_from_folder")
18 | DirectoryBrowser.connect("directory_changed", Playback, "directory_changed")
19 | DirectoryBrowser.connect("directory_changed", PlaybackHelp, "close")
20 |
21 | Playback.connect("show_help", BrowserHelp, "show")
22 | Playback.connect("show_help", PlaybackHelp, "show")
23 | Playback.connect("show_info", InfoBox, "show")
24 |
25 | Playlist.connect("play_audio", Playback, "play_audio")
26 | Playlist.connect("stop_audio", Playback, "stop_audio")
27 | Playlist.connect("export_finished", Export, "export_finished")
28 |
29 | Export.connect("export_files", Playlist, "export_files")
30 | Export.connect("clear_export", Playlist, "clear_export")
31 | Export.connect("display_message", MessageBox, "display_message")
32 |
33 |
34 |
--------------------------------------------------------------------------------
/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 | [application]
12 |
13 | config/name="SFX Browser"
14 | run/main_scene="res://Main.tscn"
15 | boot_splash/image="res://splash.png"
16 | config/icon="res://icon.png"
17 | config/windows_native_icon="res://icon.ico"
18 | config/version="0.9.3"
19 |
20 | [autoload]
21 |
22 | Config="*res://src/Config.gd"
23 | AudioImport="*res://src/GDScriptAudioImport.gd"
24 |
25 | [input]
26 |
27 | ui_accept={
28 | "deadzone": 0.5,
29 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777221,"unicode":0,"echo":false,"script":null)
30 | , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777222,"unicode":0,"echo":false,"script":null)
31 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
32 | ]
33 | }
34 |
35 | [locale]
36 |
37 | translations=PoolStringArray( "res://locale/locales.en.translation" )
38 |
39 | [rendering]
40 |
41 | environment/default_environment="res://default_env.tres"
42 |
--------------------------------------------------------------------------------
/assets/ic_stop.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/assets/ic_unfavorite.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SFX Browser
2 |
3 | SFX Browser is a fast and simple utility to browse through vast audio libraries and extract only the tracks you need. You can scan multiple sample folders, quickly navigate and listen to the track-lists, like, rename, and export what you need to a new folder.
4 |
5 | 
6 |
7 | ## Features
8 | - Scan any folder for audio files
9 | - Quickly navigate and play the track-list via arrow keys
10 | - Mark favorites
11 | - Rename the sample you want to extract
12 | - Export all selected tracks into a clean new folder
13 |
14 |
15 | https://user-images.githubusercontent.com/21098503/124129058-af322b80-da7d-11eb-94e0-b44edf688c25.mp4
16 |
17 | SFX Browser works great when picking the right sounds for your video game or software project, or just to rename a poorly labeled library.
18 |
19 | SFX Browser is build with the [Godot engine](https://github.com/godotengine/godot), runs under Windows, Max OS and Linux and uses Giannino Clemente's awesome [GDScriptAudioImport](https://github.com/Gianclgar/GDScriptAudioImport) for audio file processing. It’s free and open source for everybody to download, change and contribute to the project as one pleases.
20 |
21 | ---
22 |
23 | SFX Browser is developed by [Monolith of Minds](https://monolithofminds.com/) and you. Let us know what we can improve, or jump right in and contribute.
24 |
25 | We make video games. If you feel like supporting us, consider buying [Resolutiion](https://monolithofminds.com/resolutiion.html) or visit our latest project: [Lila’s Sky Ark](https://monolithofminds.com/lilasskyark.html).
26 | Thank you.
27 |
--------------------------------------------------------------------------------
/assets/ic_info.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/assets/ic_help.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/src/Playback.gd:
--------------------------------------------------------------------------------
1 | extends HBoxContainer
2 | """
3 | Playback
4 | """
5 | signal show_help
6 | signal show_info
7 | var is_looping = false
8 | onready var AudioPlayer := $AudioStreamPlayer
9 |
10 |
11 | func _on_Play_pressed() -> void:
12 | if AudioPlayer.playing:
13 | AudioPlayer.stop()
14 | elif AudioPlayer.stream:
15 | AudioPlayer.play()
16 | set_play_icon()
17 |
18 |
19 | func _on_Loop_toggled(button_pressed: bool) -> void:
20 | is_looping = button_pressed
21 |
22 | if AudioPlayer.playing:
23 | AudioPlayer.stop()
24 | if (AudioPlayer.stream is AudioStreamOGGVorbis
25 | or AudioPlayer.stream is AudioStreamMP3):
26 | AudioPlayer.stream.loop = button_pressed
27 | elif AudioPlayer.stream is AudioStreamSample:
28 | AudioPlayer.stream.loop_mode = 1 if button_pressed else 0
29 | AudioPlayer.play()
30 |
31 |
32 | func _on_Info_pressed() -> void:
33 | emit_signal("show_info")
34 |
35 |
36 | func _on_Help_pressed() -> void:
37 | emit_signal("show_help")
38 |
39 |
40 | func _on_AudioStreamPlayer_finished() -> void:
41 | set_play_icon()
42 |
43 |
44 | func play_audio(file_path:String="") -> void:
45 | if file_path:
46 | var stream = AudioImport.loadfile(file_path, is_looping)
47 |
48 | # var new_path = copy_file_to_user_folder(file_path)
49 | # yield(get_tree(), "idle_frame")
50 | # yield(get_tree(), "idle_frame")
51 | # yield(get_tree(), "idle_frame")
52 | # var s = load(new_path)
53 | # var stream = s
54 |
55 | if stream:
56 | AudioPlayer.stream = stream
57 | AudioPlayer.play()
58 | set_play_icon()
59 |
60 |
61 | #func copy_file_to_user_folder(file_path:String="") -> String:
62 | # var dir = Directory.new()
63 | # var new_file_name = OS.get_user_data_dir() + "/" + file_path.get_file()
64 | # dir.copy(file_path, new_file_name)
65 | # return new_file_name
66 |
67 |
68 | func stop_audio() -> void:
69 | AudioPlayer.stop()
70 | set_play_icon()
71 |
72 |
73 | func set_play_icon() -> void:
74 | if AudioPlayer.playing:
75 | $Play.icon = load("res://assets/ic_stop.svg")
76 | elif AudioPlayer.stream:
77 | $Play.icon = load("res://assets/ic_autoplay.svg")
78 |
79 |
80 | func directory_changed(_folder_path:String) -> void:
81 | AudioPlayer.stop()
82 | AudioPlayer.stream = null
83 | set_play_icon()
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
64 |
--------------------------------------------------------------------------------
/src/DirectoryBrowser.gd:
--------------------------------------------------------------------------------
1 | extends VBoxContainer
2 | """
3 | Directory Browser
4 | """
5 | signal directory_changed(new_directory)
6 | var current_directory : String
7 | onready var Tree := $Tree
8 | onready var FileDialog := $FileDialog
9 | onready var BrowserHelp := $BrowserHelp
10 |
11 | func _ready() -> void:
12 | $Load.text = tr("LOAD")
13 |
14 | yield(get_tree().current_scene, "ready")
15 | if Config.CONFIGDATA["main"]["folder_path"]:
16 | Tree.show()
17 | BrowserHelp.hide()
18 | current_directory = Config.CONFIGDATA["main"]["folder_path"]
19 | add_tree_items(current_directory)
20 | emit_signal("directory_changed", current_directory)
21 | else:
22 | Tree.hide()
23 |
24 |
25 | func _on_FileDialog_dir_selected(dir: String) -> void:
26 | Tree.show()
27 | BrowserHelp.hide()
28 | current_directory = dir
29 | Tree.clear()
30 | add_tree_items(dir)
31 |
32 | Config.CONFIGDATA["main"]["folder_path"] = current_directory
33 | Config.save_config()
34 | emit_signal("directory_changed", current_directory)
35 |
36 |
37 | func _on_Load_pressed():
38 | FileDialog.current_dir = current_directory
39 | FileDialog.window_title = tr("LOAD_POPUP")
40 | var popup_size = Vector2(800, 400)
41 | var popup_position = OS.window_size/2 - popup_size/2
42 | FileDialog.popup(Rect2(popup_position, popup_size))
43 |
44 |
45 | func _on_Tree_item_selected() -> void:
46 | var item = Tree.get_selected()
47 | var path = current_directory + item.get_meta("path_in_tree")
48 | emit_signal("directory_changed", path)
49 | call_deferred("add_tree_items", path, item)
50 |
51 |
52 | func add_tree_items(path:String, _root=null) -> void:
53 | var files = get_subdirectories(path.replace("//", "/"))
54 | var path_in_tree : String
55 | if not _root:
56 | _root = Tree.create_item()
57 | else:
58 | path_in_tree = _root.get_meta("path_in_tree")
59 |
60 | var item_children = get_tree_item_children(_root)
61 | for i in files:
62 | if i in item_children:
63 | continue
64 | var item = Tree.create_item(_root)
65 | item.set_text(0, i)
66 | item.set_meta("path_in_tree", path_in_tree + "/" + i)
67 |
68 |
69 | func get_tree_item_children(root:TreeItem) -> Array:
70 | var item_children = []
71 | var ti = root.get_children()
72 | while ti:
73 | item_children.append(ti.get_text(0))
74 | ti = ti.get_next()
75 | return item_children
76 |
77 |
78 | func get_subdirectories(path:String) -> Array:
79 | var directories = []
80 |
81 | var dir = Directory.new()
82 | if dir.open(path) == OK:
83 | dir.list_dir_begin()
84 | var file_name = dir.get_next()
85 | while file_name != "":
86 | if (dir.current_is_dir()
87 | and not file_name.begins_with(".")):
88 | directories.append(file_name)
89 | file_name = dir.get_next()
90 | dir.list_dir_end()
91 |
92 | directories.sort()
93 | return directories
94 |
95 |
--------------------------------------------------------------------------------
/src/Playlist.gd:
--------------------------------------------------------------------------------
1 | extends ScrollContainer
2 | """
3 | Playlist
4 | """
5 | signal play_audio(file_path)
6 | signal stop_audio()
7 | signal export_finished(amount)
8 | var file_list = []
9 | var current_item = null
10 | const ITEM = preload("res://ItemContainer.tscn")
11 | onready var List = $VBoxContainer
12 | onready var AnalizeThread = $AnalizeThread
13 |
14 | func _ready() -> void:
15 | set_process(false)
16 |
17 |
18 | func _unhandled_key_input(event: InputEventKey) -> void:
19 | if event.scancode == KEY_F and event.pressed and not event.is_echo():
20 | if current_item:
21 | current_item.toggle_favourite()
22 |
23 |
24 | func _process(_delta: float) -> void:
25 | if AnalizeThread.analysis_finished:
26 | set_process(false)
27 | var data = AnalizeThread.get_data()
28 | for i in List.get_child_count():
29 | List.get_child(i).set_additional_data(data[i])
30 |
31 |
32 | func load_files_from_folder(_folder_path:String) -> void:
33 | current_item = null
34 | file_list.clear()
35 | file_list = _get_files_from_directory(_folder_path)
36 |
37 | #clear list
38 | for i in List.get_children():
39 | i.queue_free()
40 |
41 | #create new list items
42 | var index_size = str(file_list.size()).length()
43 | for j in file_list.size():
44 | var item = ITEM.instance()
45 | item.set_data(str(j).pad_zeros(index_size), file_list[j])
46 | List.add_child(item)
47 | item.connect("focus_entered", self, "_on_item_selected", [item])
48 | item.connect("gui_input", self, "_on_item_input", [item])
49 |
50 | scroll_vertical = 0
51 |
52 | #start analyze thread
53 | AnalizeThread.call_deferred("analyze_files", file_list)
54 | set_process(true)
55 |
56 |
57 | func _get_files_from_directory(_folder_path:String) -> Array:
58 | var _file_list = []
59 | var d = Directory.new()
60 | d.open(_folder_path)
61 | d.list_dir_begin()
62 | var f = d.get_next()
63 | while (f != ""):
64 | if f.get_extension() in ["wav", "ogg", "mp3"]:
65 | _file_list.append(_folder_path + "/" + f)
66 | f = d.get_next()
67 | d.list_dir_end()
68 |
69 | _file_list.sort()
70 | return _file_list
71 |
72 |
73 | func _on_item_selected(item) -> void:
74 | if current_item:
75 | current_item.unfocus()
76 | current_item = item
77 | #playback is handled in Playback node
78 | emit_signal("play_audio", item.get_file_path())
79 |
80 |
81 | func _on_item_input(event:InputEvent, item:Control) -> void:
82 | if event is InputEventMouseButton and event.pressed and not event.is_echo():
83 | if item == current_item:
84 | if event.button_index == BUTTON_LEFT:
85 | #restart playback
86 | emit_signal("play_audio", item.get_file_path())
87 | elif event.button_index == BUTTON_RIGHT:
88 | #stop playback
89 | emit_signal("stop_audio")
90 |
91 |
92 | func clear_export() -> void:
93 | for i in List.get_children():
94 | if i.get_export_name() != "":
95 | i.clear_export()
96 |
97 |
98 | func export_files(export_dir:String) -> void:
99 | var dir = Directory.new()
100 | var amount = 0
101 | for i in List.get_children():
102 | var export_name = i.get_export_name()
103 | if export_name:
104 | var extention = i.get_file_path().get_extension()
105 | dir.copy(i.get_file_path(), export_dir + "/" + export_name + "." + extention)
106 | amount += 1
107 | emit_signal("export_finished", amount)
108 |
109 |
--------------------------------------------------------------------------------
/ItemContainer.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=9 format=2]
2 |
3 | [ext_resource path="res://src/ItemContainer.gd" type="Script" id=1]
4 | [ext_resource path="res://assets/ic_note.svg" type="Texture" id=2]
5 | [ext_resource path="res://assets/ui_theme.tres" type="Theme" id=3]
6 | [ext_resource path="res://assets/ic_favorite.svg" type="Texture" id=4]
7 | [ext_resource path="res://assets/ic_unfavorite.svg" type="Texture" id=5]
8 | [ext_resource path="res://assets/ic_clear.svg" type="Texture" id=6]
9 | [ext_resource path="res://assets/fonts/IBMPlexMono-Regular.ttf" type="DynamicFontData" id=7]
10 |
11 | [sub_resource type="DynamicFont" id=1]
12 | size = 14
13 | font_data = ExtResource( 7 )
14 |
15 | [node name="ItemContainer" type="HBoxContainer"]
16 | anchor_right = 1.0
17 | anchor_bottom = 1.0
18 | margin_right = -144.0
19 | margin_bottom = -576.0
20 | rect_min_size = Vector2( 0, 30 )
21 | focus_mode = 2
22 | mouse_filter = 0
23 | size_flags_horizontal = 7
24 | theme = ExtResource( 3 )
25 | custom_constants/separation = 10
26 | script = ExtResource( 1 )
27 | __meta__ = {
28 | "_edit_use_anchors_": false
29 | }
30 |
31 | [node name="Icon" type="TextureRect" parent="."]
32 | modulate = Color( 0.807843, 0.917647, 0.780392, 1 )
33 | margin_right = 24.0
34 | margin_bottom = 30.0
35 | texture = ExtResource( 2 )
36 | stretch_mode = 4
37 |
38 | [node name="Idx" type="Label" parent="."]
39 | margin_left = 34.0
40 | margin_right = 58.0
41 | margin_bottom = 30.0
42 | size_flags_vertical = 5
43 | custom_fonts/font = SubResource( 1 )
44 | text = "idx"
45 | align = 2
46 | valign = 1
47 |
48 | [node name="File" type="Label" parent="."]
49 | margin_left = 68.0
50 | margin_right = 508.0
51 | margin_bottom = 30.0
52 | mouse_filter = 1
53 | size_flags_horizontal = 15
54 | size_flags_vertical = 3
55 | text = "filename"
56 | valign = 1
57 | clip_text = true
58 |
59 | [node name="VSeparator" type="VSeparator" parent="."]
60 | margin_left = 518.0
61 | margin_right = 538.0
62 | margin_bottom = 30.0
63 | custom_constants/separation = 20
64 |
65 | [node name="Length" type="Label" parent="."]
66 | margin_left = 548.0
67 | margin_right = 580.0
68 | margin_bottom = 30.0
69 | rect_min_size = Vector2( 20, 0 )
70 | size_flags_vertical = 3
71 | custom_fonts/font = SubResource( 1 )
72 | text = "-:--"
73 | valign = 1
74 |
75 | [node name="VSeparator2" type="VSeparator" parent="."]
76 | margin_left = 590.0
77 | margin_right = 610.0
78 | margin_bottom = 30.0
79 | custom_constants/separation = 20
80 |
81 | [node name="Favourite" type="TextureButton" parent="."]
82 | modulate = Color( 0.839216, 0.466667, 0.533333, 1 )
83 | margin_left = 620.0
84 | margin_right = 650.0
85 | margin_bottom = 30.0
86 | rect_min_size = Vector2( 30, 0 )
87 | toggle_mode = true
88 | texture_normal = ExtResource( 5 )
89 | texture_pressed = ExtResource( 4 )
90 | texture_hover = ExtResource( 5 )
91 | texture_disabled = ExtResource( 5 )
92 | texture_focused = ExtResource( 5 )
93 | expand = true
94 | stretch_mode = 3
95 |
96 | [node name="ExportName" type="LineEdit" parent="."]
97 | margin_left = 660.0
98 | margin_right = 860.0
99 | margin_bottom = 26.0
100 | rect_min_size = Vector2( 200, 0 )
101 | size_flags_horizontal = 13
102 | size_flags_vertical = 0
103 | custom_icons/clear = ExtResource( 6 )
104 | clear_button_enabled = true
105 | placeholder_text = "export file name"
106 | placeholder_alpha = 0.25
107 |
108 | [node name="VSeparator3" type="VSeparator" parent="."]
109 | margin_left = 870.0
110 | margin_right = 880.0
111 | margin_bottom = 30.0
112 | custom_constants/separation = 10
113 |
114 | [connection signal="focus_entered" from="." to="." method="_on_ItemContainer_focus_entered"]
115 | [connection signal="toggled" from="Favourite" to="." method="_on_Favourite_toggled"]
116 |
--------------------------------------------------------------------------------
/assets/ui_theme.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Theme" load_steps=28 format=2]
2 |
3 | [ext_resource path="res://assets/fonts/IBMPlexMono-Regular.ttf" type="DynamicFontData" id=1]
4 | [ext_resource path="res://assets/fonts/IBMPlexSans-Regular.ttf" type="DynamicFontData" id=2]
5 | [ext_resource path="res://assets/ic_direction_right.svg" type="Texture" id=3]
6 | [ext_resource path="res://assets/ic_direction_down.svg" type="Texture" id=4]
7 | [ext_resource path="res://assets/ic_clear.svg" type="Texture" id=5]
8 | [ext_resource path="res://assets/fonts/wqy-MicroHei.ttf" type="DynamicFontData" id=6]
9 |
10 | [sub_resource type="DynamicFont" id=1]
11 | size = 18
12 | font_data = ExtResource( 1 )
13 |
14 | [sub_resource type="StyleBoxEmpty" id=2]
15 |
16 | [sub_resource type="StyleBoxFlat" id=3]
17 | bg_color = Color( 0.180392, 0.14902, 0.2, 0 )
18 | border_color = Color( 0.937255, 1, 0.803922, 1 )
19 |
20 | [sub_resource type="StyleBoxFlat" id=4]
21 | bg_color = Color( 0.180392, 0.14902, 0.2, 0 )
22 | border_width_bottom = 1
23 | border_color = Color( 0.937255, 1, 0.803922, 0 )
24 |
25 | [sub_resource type="StyleBoxFlat" id=5]
26 | bg_color = Color( 0.807843, 0.917647, 0.780392, 1 )
27 |
28 | [sub_resource type="StyleBoxFlat" id=6]
29 |
30 | [sub_resource type="StyleBoxEmpty" id=7]
31 |
32 | [sub_resource type="StyleBoxFlat" id=8]
33 | bg_color = Color( 0.6, 0.6, 0.6, 0 )
34 | border_width_bottom = 2
35 | border_color = Color( 0.215686, 0.215686, 0.27451, 1 )
36 |
37 | [sub_resource type="StyleBoxFlat" id=9]
38 | bg_color = Color( 0.215686, 0.215686, 0.27451, 1 )
39 |
40 | [sub_resource type="StyleBoxFlat" id=10]
41 | bg_color = Color( 0.27451, 0.27451, 0.333333, 1 )
42 |
43 | [sub_resource type="StyleBoxEmpty" id=11]
44 |
45 | [sub_resource type="StyleBoxEmpty" id=12]
46 |
47 | [sub_resource type="StyleBoxEmpty" id=13]
48 |
49 | [sub_resource type="StyleBoxEmpty" id=14]
50 |
51 | [sub_resource type="StyleBoxFlat" id=15]
52 | bg_color = Color( 0.733333, 0.823529, 0.819608, 1 )
53 |
54 | [sub_resource type="StyleBoxFlat" id=16]
55 | bg_color = Color( 0.807843, 0.917647, 0.780392, 1 )
56 |
57 | [sub_resource type="StyleBoxFlat" id=17]
58 |
59 | [sub_resource type="StyleBoxLine" id=18]
60 | color = Color( 0.215686, 0.215686, 0.27451, 1 )
61 | thickness = 4
62 | vertical = true
63 |
64 | [sub_resource type="StyleBoxEmpty" id=19]
65 |
66 | [sub_resource type="StyleBoxFlat" id=20]
67 | bg_color = Color( 0.27451, 0.27451, 0.333333, 1 )
68 | border_width_left = 2
69 | border_width_top = 2
70 | border_width_right = 2
71 | border_width_bottom = 2
72 | border_color = Color( 0.733333, 0.823529, 0.819608, 1 )
73 | expand_margin_right = 9.0
74 | expand_margin_top = 24.0
75 |
76 | [sub_resource type="DynamicFont" id=21]
77 | size = 18
78 | font_data = ExtResource( 2 )
79 | fallback/0 = ExtResource( 6 )
80 |
81 | [resource]
82 | default_font = SubResource( 21 )
83 | Button/colors/font_color = Color( 0.733333, 0.823529, 0.819608, 1 )
84 | Button/colors/font_color_disabled = Color( 0.45098, 0.45098, 0.509804, 1 )
85 | Button/colors/font_color_hover = Color( 0.807843, 0.917647, 0.780392, 1 )
86 | Button/colors/font_color_pressed = Color( 0.215686, 0.215686, 0.27451, 1 )
87 | Button/constants/hseparation = 15
88 | Button/fonts/font = SubResource( 1 )
89 | Button/styles/disabled = SubResource( 2 )
90 | Button/styles/focus = SubResource( 3 )
91 | Button/styles/hover = SubResource( 3 )
92 | Button/styles/normal = SubResource( 4 )
93 | Button/styles/pressed = SubResource( 5 )
94 | Dialogs/constants/button_margin = 32
95 | Dialogs/constants/margin = 8
96 | FileDialog/colors/file_icon_modulate = Color( 1, 1, 1, 1 )
97 | FileDialog/colors/files_disabled = Color( 0, 0, 0, 0.784314 )
98 | FileDialog/colors/folder_icon_modulate = Color( 1, 1, 1, 1 )
99 | FileDialog/icons/file = null
100 | FileDialog/icons/folder = null
101 | FileDialog/icons/parent_folder = null
102 | FileDialog/icons/reload = null
103 | FileDialog/icons/toggle_hidden = null
104 | HSeparator/constants/separation = 10
105 | HSeparator/styles/separator = SubResource( 6 )
106 | Label/colors/font_color = Color( 0.733333, 0.823529, 0.819608, 1 )
107 | Label/colors/font_color_shadow = Color( 0, 0, 0, 0 )
108 | Label/colors/font_outline_modulate = Color( 1, 1, 1, 1 )
109 | Label/constants/line_spacing = 3
110 | Label/constants/shadow_as_outline = 0
111 | Label/constants/shadow_offset_x = 1
112 | Label/constants/shadow_offset_y = 1
113 | Label/fonts/font = null
114 | Label/styles/normal = null
115 | LineEdit/colors/clear_button_color = Color( 0.733333, 0.823529, 0.819608, 1 )
116 | LineEdit/colors/clear_button_color_pressed = Color( 0.807843, 0.917647, 0.780392, 1 )
117 | LineEdit/colors/cursor_color = Color( 0.807843, 0.917647, 0.780392, 1 )
118 | LineEdit/colors/font_color = Color( 0.733333, 0.823529, 0.819608, 1 )
119 | LineEdit/colors/font_color_selected = Color( 0, 0, 0, 1 )
120 | LineEdit/colors/font_color_uneditable = Color( 0.45098, 0.45098, 0.509804, 1 )
121 | LineEdit/colors/selection_color = Color( 0.839216, 0.466667, 0.533333, 1 )
122 | LineEdit/constants/minimum_spaces = 12
123 | LineEdit/fonts/font = null
124 | LineEdit/icons/clear = null
125 | LineEdit/styles/focus = SubResource( 7 )
126 | LineEdit/styles/normal = SubResource( 8 )
127 | LineEdit/styles/read_only = null
128 | MarginContainer/constants/margin_bottom = 20
129 | MarginContainer/constants/margin_left = 20
130 | MarginContainer/constants/margin_right = 20
131 | MarginContainer/constants/margin_top = 20
132 | PanelContainer/styles/panel = SubResource( 9 )
133 | PopupMenu/colors/font_color = Color( 1, 1, 1, 1 )
134 | PopupMenu/colors/font_color_accel = Color( 0.7, 0.7, 0.7, 0.8 )
135 | PopupMenu/colors/font_color_disabled = Color( 0.4, 0.4, 0.4, 0.8 )
136 | PopupMenu/colors/font_color_hover = Color( 0.88, 0.88, 0.88, 1 )
137 | PopupMenu/colors/font_color_separator = Color( 0.88, 0.88, 0.88, 1 )
138 | PopupMenu/constants/hseparation = 4
139 | PopupMenu/constants/vseparation = 4
140 | PopupMenu/fonts/font = null
141 | PopupMenu/icons/checked = null
142 | PopupMenu/icons/radio_checked = null
143 | PopupMenu/icons/radio_unchecked = null
144 | PopupMenu/icons/submenu = null
145 | PopupMenu/icons/unchecked = null
146 | PopupMenu/styles/hover = SubResource( 10 )
147 | PopupMenu/styles/labeled_separator_left = SubResource( 10 )
148 | PopupMenu/styles/labeled_separator_right = SubResource( 10 )
149 | PopupMenu/styles/panel = SubResource( 10 )
150 | PopupMenu/styles/panel_disabled = SubResource( 10 )
151 | PopupMenu/styles/separator = SubResource( 10 )
152 | Tree/colors/custom_button_font_highlight = Color( 0.807843, 0.917647, 0.780392, 1 )
153 | Tree/colors/drop_position_color = Color( 1, 0.3, 0.2, 1 )
154 | Tree/colors/font_color = Color( 0.733333, 0.823529, 0.819608, 1 )
155 | Tree/colors/font_color_selected = Color( 0.807843, 0.917647, 0.780392, 1 )
156 | Tree/colors/guide_color = Color( 0, 0, 0, 0.1 )
157 | Tree/colors/relationship_line_color = Color( 0.270588, 0.270588, 0.270588, 0 )
158 | Tree/colors/title_button_color = Color( 0.88, 0.88, 0.88, 1 )
159 | Tree/constants/button_margin = 0
160 | Tree/constants/draw_guides = 0
161 | Tree/constants/draw_relationship_lines = 0
162 | Tree/constants/hseparation = 0
163 | Tree/constants/item_margin = 24
164 | Tree/constants/scroll_border = 4
165 | Tree/constants/scroll_speed = 12
166 | Tree/constants/vseparation = 6
167 | Tree/fonts/font = null
168 | Tree/fonts/title_button_font = null
169 | Tree/icons/arrow = ExtResource( 4 )
170 | Tree/icons/arrow_collapsed = ExtResource( 3 )
171 | Tree/icons/checked = null
172 | Tree/icons/select_arrow = null
173 | Tree/icons/unchecked = null
174 | Tree/icons/updown = null
175 | Tree/styles/bg = SubResource( 11 )
176 | Tree/styles/bg_focus = null
177 | Tree/styles/button_pressed = SubResource( 12 )
178 | Tree/styles/cursor = null
179 | Tree/styles/cursor_unfocused = null
180 | Tree/styles/custom_button = null
181 | Tree/styles/custom_button_hover = null
182 | Tree/styles/custom_button_pressed = null
183 | Tree/styles/selected = SubResource( 13 )
184 | Tree/styles/selected_focus = SubResource( 14 )
185 | Tree/styles/title_button_hover = null
186 | Tree/styles/title_button_normal = null
187 | Tree/styles/title_button_pressed = null
188 | VScrollBar/icons/decrement = null
189 | VScrollBar/icons/decrement_highlight = null
190 | VScrollBar/icons/increment = null
191 | VScrollBar/icons/increment_highlight = null
192 | VScrollBar/styles/grabber = SubResource( 15 )
193 | VScrollBar/styles/grabber_highlight = SubResource( 16 )
194 | VScrollBar/styles/grabber_pressed = SubResource( 17 )
195 | VScrollBar/styles/scroll = SubResource( 18 )
196 | VScrollBar/styles/scroll_focus = null
197 | VSeparator/constants/separation = 40
198 | VSeparator/styles/separator = SubResource( 19 )
199 | WindowDialog/colors/title_color = Color( 0.807843, 0.917647, 0.780392, 1 )
200 | WindowDialog/constants/close_h_ofs = 18
201 | WindowDialog/constants/close_v_ofs = 18
202 | WindowDialog/constants/scaleborder_size = 4
203 | WindowDialog/constants/title_height = 20
204 | WindowDialog/fonts/title_font = null
205 | WindowDialog/icons/close = ExtResource( 5 )
206 | WindowDialog/icons/close_highlight = ExtResource( 5 )
207 | WindowDialog/styles/panel = SubResource( 20 )
208 |
--------------------------------------------------------------------------------
/src/GDScriptAudioImport.gd:
--------------------------------------------------------------------------------
1 | #GDScriptAudioImport v0.1
2 |
3 | #MIT License
4 | #
5 | #Copyright (c) 2020 Gianclgar (Giannino Clemente) gianclgar@gmail.com
6 | #
7 | #Permission is hereby granted, free of charge, to any person obtaining a copy
8 | #of this software and associated documentation files (the "Software"), to deal
9 | #in the Software without restriction, including without limitation the rights
10 | #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | #copies of the Software, and to permit persons to whom the Software is
12 | #furnished to do so, subject to the following conditions:
13 | #
14 | #The above copyright notice and this permission notice shall be included in all
15 | #copies or substantial portions of the Software.
16 | #
17 | #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | #SOFTWARE.
24 |
25 | #I honestly don't care that much, Kopimi ftw, but it's my little baby and I want it to look nice :3
26 |
27 | extends Node
28 |
29 | func report_errors(err, filepath):
30 | # See: https://docs.godotengine.org/en/latest/classes/class_@globalscope.html#enum-globalscope-error
31 | var result_hash = {
32 | ERR_FILE_NOT_FOUND: "File: not found",
33 | ERR_FILE_BAD_DRIVE: "File: Bad drive error",
34 | ERR_FILE_BAD_PATH: "File: Bad path error.",
35 | ERR_FILE_NO_PERMISSION: "File: No permission error.",
36 | ERR_FILE_ALREADY_IN_USE: "File: Already in use error.",
37 | ERR_FILE_CANT_OPEN: "File: Can't open error.",
38 | ERR_FILE_CANT_WRITE: "File: Can't write error.",
39 | ERR_FILE_CANT_READ: "File: Can't read error.",
40 | ERR_FILE_UNRECOGNIZED: "File: Unrecognized error.",
41 | ERR_FILE_CORRUPT: "File: Corrupt error.",
42 | ERR_FILE_MISSING_DEPENDENCIES: "File: Missing dependencies error.",
43 | ERR_FILE_EOF: "File: End of file (EOF) error."
44 | }
45 | if err in result_hash:
46 | print("Error: ", result_hash[err], " ", filepath)
47 | else:
48 | print("Unknown error with file ", filepath, " error code: ", err)
49 |
50 | func loadfile(filepath, _loop = false):
51 | var file = File.new()
52 | var err = file.open(filepath, File.READ)
53 | if err != OK:
54 | report_errors(err, filepath)
55 | file.close()
56 | return AudioStreamSample.new()
57 |
58 | var bytes = file.get_buffer(file.get_len())
59 | # if File is wav
60 | if filepath.ends_with(".wav"):
61 | var newstream = AudioStreamSample.new()
62 |
63 | #---------------------------
64 | #parrrrseeeeee!!! :D
65 | print ("---")
66 |
67 | var bits_per_sample = 0
68 |
69 | for i in range(0, 100):
70 | var those4bytes = str(char(bytes[i])+char(bytes[i+1])+char(bytes[i+2])+char(bytes[i+3]))
71 |
72 | if those4bytes == "RIFF":
73 | print ("RIFF OK at bytes " + str(i) + "-" + str(i+3))
74 | #RIP bytes 4-7 integer for now
75 |
76 | if those4bytes == "WAVE":
77 | print ("WAVE OK at bytes " + str(i) + "-" + str(i+3))
78 |
79 | if those4bytes == "fmt ":
80 | print ("fmt OK at bytes " + str(i) + "-" + str(i+3))
81 |
82 | #get format subchunk size, 4 bytes next to "fmt " are an int32
83 | var formatsubchunksize = bytes[i+4] + (bytes[i+5] << 8) + (bytes[i+6] << 16) + (bytes[i+7] << 24)
84 | print ("Format subchunk size: " + str(formatsubchunksize))
85 |
86 | #using formatsubchunk index so it's easier to understand what's going on
87 | var fsc0 = i+8 #fsc0 is byte 8 after start of "fmt "
88 |
89 | #get format code [Bytes 0-1]
90 | var format_code = bytes[fsc0] + (bytes[fsc0+1] << 8)
91 | var format_name
92 | if format_code == 0: format_name = "8_BITS"
93 | elif format_code == 1: format_name = "16_BITS"
94 | elif format_code == 2: format_name = "IMA_ADPCM"
95 | else:
96 | format_name = "UNKNOWN (trying to interpret as 16_BITS)"
97 | format_code = 1
98 | print ("Format: " + str(format_code) + " " + format_name)
99 | #assign format to our AudioStreamSample
100 | newstream.format = format_code
101 |
102 | #get channel num [Bytes 2-3]
103 | var channel_num = bytes[fsc0+2] + (bytes[fsc0+3] << 8)
104 | print ("Number of channels: " + str(channel_num))
105 | #set our AudioStreamSample to stereo if needed
106 | if channel_num == 2: newstream.stereo = true
107 |
108 | #get sample rate [Bytes 4-7]
109 | var sample_rate = bytes[fsc0+4] + (bytes[fsc0+5] << 8) + (bytes[fsc0+6] << 16) + (bytes[fsc0+7] << 24)
110 | print ("Sample rate: " + str(sample_rate))
111 | #set our AudioStreamSample mixrate
112 | newstream.mix_rate = sample_rate
113 |
114 | #get byte_rate [Bytes 8-11] because we can
115 | var byte_rate = bytes[fsc0+8] + (bytes[fsc0+9] << 8) + (bytes[fsc0+10] << 16) + (bytes[fsc0+11] << 24)
116 | print ("Byte rate: " + str(byte_rate))
117 |
118 | #same with bits*sample*channel [Bytes 12-13]
119 | var bits_sample_channel = bytes[fsc0+12] + (bytes[fsc0+13] << 8)
120 | print ("BitsPerSample * Channel / 8: " + str(bits_sample_channel))
121 |
122 | #aaaand bits per sample/bitrate [Bytes 14-15]
123 | bits_per_sample = bytes[fsc0+14] + (bytes[fsc0+15] << 8)
124 | print ("Bits per sample: " + str(bits_per_sample))
125 |
126 | if those4bytes == "data":
127 | assert(bits_per_sample != 0)
128 |
129 | var audio_data_size = bytes[i+4] + (bytes[i+5] << 8) + (bytes[i+6] << 16) + (bytes[i+7] << 24)
130 | print ("Audio data/stream size is " + str(audio_data_size) + " bytes")
131 |
132 | var data_entry_point = (i+8)
133 | print ("Audio data starts at byte " + str(data_entry_point))
134 |
135 | var data = bytes.subarray(data_entry_point, data_entry_point+audio_data_size-1)
136 |
137 | if bits_per_sample in [24, 32]:
138 | newstream.data = convert_to_16bit(data, bits_per_sample)
139 | else:
140 | newstream.data = data
141 | # end of parsing
142 | #---------------------------
143 |
144 | #get samples and set loop end
145 | var samplenum = newstream.data.size() / 4
146 | newstream.loop_end = samplenum
147 | newstream.loop_mode = 1 if _loop else 0 #change to 0 or delete this line if you don't want loop, also check out modes 2 and 3 in the docs
148 | return newstream #:D
149 |
150 | #if file is ogg
151 | elif filepath.ends_with(".ogg"):
152 | var newstream = AudioStreamOGGVorbis.new()
153 | newstream.loop = _loop #set to false or delete this line if you don't want to loop
154 | newstream.data = bytes
155 | return newstream
156 |
157 | #if file is mp3
158 | elif filepath.ends_with(".mp3"):
159 | var newstream = AudioStreamMP3.new()
160 | newstream.loop = _loop #set to false or delete this line if you don't want to loop
161 | newstream.data = bytes
162 | return newstream
163 |
164 | else:
165 | print ("ERROR: Wrong filetype or format")
166 | file.close()
167 |
168 | # Converts .wav data from 24 or 32 bits to 16
169 | #
170 | # These conversions are SLOW in GDScript
171 | # on my one test song, 32 -> 16 was around 3x slower than 24 -> 16
172 | #
173 | # I couldn't get threads to help very much
174 | # They made the 24bit case about 2x faster in my test file
175 | # And the 32bit case abour 50% slower
176 | # I don't wanna risk it always being slower on other files
177 | # And really, the solution would be to handle it in a low-level language
178 | func convert_to_16bit(data: PoolByteArray, from: int) -> PoolByteArray:
179 | print("converting to 16-bit from %d" % from)
180 | var time = OS.get_ticks_msec()
181 | # 24 bit .wav's are typically stored as integers
182 | # so we just grab the 2 most significant bytes and ignore the other
183 | if from == 24:
184 | var j = 0
185 | for i in range(0, data.size(), 3):
186 | data[j] = data[i+1]
187 | data[j+1] = data[i+2]
188 | j += 2
189 | data.resize(data.size() * 2 / 3)
190 | # 32 bit .wav's are typically stored as floating point numbers
191 | # so we need to grab all 4 bytes and interpret them as a float first
192 | if from == 32:
193 | var spb := StreamPeerBuffer.new()
194 | var single_float: float
195 | var value: int
196 | for i in range(0, data.size(), 4):
197 | spb.data_array = data.subarray(i, i+3)
198 | single_float = spb.get_float()
199 | value = single_float * 32768
200 | data[i/2] = value
201 | data[i/2+1] = value >> 8
202 | data.resize(data.size() / 2)
203 | print("Took %f seconds for slow conversion" % ((OS.get_ticks_msec() - time) / 1000.0))
204 | return data
205 |
206 |
207 | # ---------- REFERENCE ---------------
208 | # note: typical values doesn't always match
209 |
210 | #Positions Typical Value Description
211 | #
212 | #1 - 4 "RIFF" Marks the file as a RIFF multimedia file.
213 | # Characters are each 1 byte long.
214 | #
215 | #5 - 8 (integer) The overall file size in bytes (32-bit integer)
216 | # minus 8 bytes. Typically, you'd fill this in after
217 | # file creation is complete.
218 | #
219 | #9 - 12 "WAVE" RIFF file format header. For our purposes, it
220 | # always equals "WAVE".
221 | #
222 | #13-16 "fmt " Format sub-chunk marker. Includes trailing null.
223 | #
224 | #17-20 16 Length of the rest of the format sub-chunk below.
225 | #
226 | #21-22 1 Audio format code, a 2 byte (16 bit) integer.
227 | # 1 = PCM (pulse code modulation).
228 | #
229 | #23-24 2 Number of channels as a 2 byte (16 bit) integer.
230 | # 1 = mono, 2 = stereo, etc.
231 | #
232 | #25-28 44100 Sample rate as a 4 byte (32 bit) integer. Common
233 | # values are 44100 (CD), 48000 (DAT). Sample rate =
234 | # number of samples per second, or Hertz.
235 | #
236 | #29-32 176400 (SampleRate * BitsPerSample * Channels) / 8
237 | # This is the Byte rate.
238 | #
239 | #33-34 4 (BitsPerSample * Channels) / 8
240 | # 1 = 8 bit mono, 2 = 8 bit stereo or 16 bit mono, 4
241 | # = 16 bit stereo.
242 | #
243 | #35-36 16 Bits per sample.
244 | #
245 | #37-40 "data" Data sub-chunk header. Marks the beginning of the
246 | # raw data section.
247 | #
248 | #41-44 (integer) The number of bytes of the data section below this
249 | # point. Also equal to (#ofSamples * #ofChannels *
250 | # BitsPerSample) / 8
251 | #
252 | #45+ The raw audio data.
253 |
--------------------------------------------------------------------------------
/Main.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=32 format=2]
2 |
3 | [ext_resource path="res://src/Main.gd" type="Script" id=1]
4 | [ext_resource path="res://assets/logo.svg" type="Texture" id=2]
5 | [ext_resource path="res://assets/ic_folder.svg" type="Texture" id=3]
6 | [ext_resource path="res://assets/ui_theme.tres" type="Theme" id=4]
7 | [ext_resource path="res://assets/ic_loop.svg" type="Texture" id=5]
8 | [ext_resource path="res://assets/ic_stop.svg" type="Texture" id=6]
9 | [ext_resource path="res://src/AnalizeThread.gd" type="Script" id=7]
10 | [ext_resource path="res://src/DirectoryBrowser.gd" type="Script" id=8]
11 | [ext_resource path="res://src/Playlist.gd" type="Script" id=9]
12 | [ext_resource path="res://src/Playback.gd" type="Script" id=10]
13 | [ext_resource path="res://src/Export.gd" type="Script" id=11]
14 | [ext_resource path="res://assets/ic_clear.svg" type="Texture" id=12]
15 | [ext_resource path="res://src/MessageBox.gd" type="Script" id=13]
16 | [ext_resource path="res://assets/ic_info.svg" type="Texture" id=14]
17 | [ext_resource path="res://assets/ic_help.svg" type="Texture" id=15]
18 | [ext_resource path="res://src/HelpPanel.gd" type="Script" id=16]
19 | [ext_resource path="res://src/InfoBox.gd" type="Script" id=17]
20 |
21 | [sub_resource type="InputEventKey" id=1]
22 | control = true
23 | command = true
24 | scancode = 79
25 |
26 | [sub_resource type="ShortCut" id=2]
27 | shortcut = SubResource( 1 )
28 |
29 | [sub_resource type="StyleBoxFlat" id=3]
30 | bg_color = Color( 0.733333, 0.823529, 0.819608, 1 )
31 |
32 | [sub_resource type="Animation" id=4]
33 | resource_name = "hide"
34 | length = 0.3
35 | tracks/0/type = "value"
36 | tracks/0/path = NodePath(".:modulate")
37 | tracks/0/interp = 1
38 | tracks/0/loop_wrap = true
39 | tracks/0/imported = false
40 | tracks/0/enabled = true
41 | tracks/0/keys = {
42 | "times": PoolRealArray( 0.3 ),
43 | "transitions": PoolRealArray( 1 ),
44 | "update": 3,
45 | "values": [ Color( 1, 1, 1, 0 ) ]
46 | }
47 | tracks/1/type = "method"
48 | tracks/1/path = NodePath(".")
49 | tracks/1/interp = 1
50 | tracks/1/loop_wrap = true
51 | tracks/1/imported = false
52 | tracks/1/enabled = true
53 | tracks/1/keys = {
54 | "times": PoolRealArray( 0.3 ),
55 | "transitions": PoolRealArray( 1 ),
56 | "values": [ {
57 | "args": [ ],
58 | "method": "hide"
59 | } ]
60 | }
61 |
62 | [sub_resource type="StyleBoxEmpty" id=5]
63 |
64 | [sub_resource type="InputEventKey" id=6]
65 | scancode = 32
66 |
67 | [sub_resource type="ShortCut" id=7]
68 | shortcut = SubResource( 6 )
69 |
70 | [sub_resource type="InputEventKey" id=8]
71 | scancode = 76
72 |
73 | [sub_resource type="ShortCut" id=9]
74 | shortcut = SubResource( 8 )
75 |
76 | [sub_resource type="StyleBoxFlat" id=10]
77 | bg_color = Color( 0.807843, 0.917647, 0.780392, 1 )
78 |
79 | [sub_resource type="Animation" id=11]
80 | length = 0.3
81 | tracks/0/type = "value"
82 | tracks/0/path = NodePath(".:modulate")
83 | tracks/0/interp = 1
84 | tracks/0/loop_wrap = true
85 | tracks/0/imported = false
86 | tracks/0/enabled = true
87 | tracks/0/keys = {
88 | "times": PoolRealArray( 0.3 ),
89 | "transitions": PoolRealArray( 1 ),
90 | "update": 3,
91 | "values": [ Color( 1, 1, 1, 0 ) ]
92 | }
93 | tracks/1/type = "method"
94 | tracks/1/path = NodePath(".")
95 | tracks/1/interp = 1
96 | tracks/1/loop_wrap = true
97 | tracks/1/imported = false
98 | tracks/1/enabled = true
99 | tracks/1/keys = {
100 | "times": PoolRealArray( 0.3 ),
101 | "transitions": PoolRealArray( 1 ),
102 | "values": [ {
103 | "args": [ ],
104 | "method": "hide"
105 | } ]
106 | }
107 |
108 | [sub_resource type="Animation" id=12]
109 | length = 0.3
110 | tracks/0/type = "value"
111 | tracks/0/path = NodePath(".:modulate")
112 | tracks/0/interp = 1
113 | tracks/0/loop_wrap = true
114 | tracks/0/imported = false
115 | tracks/0/enabled = true
116 | tracks/0/keys = {
117 | "times": PoolRealArray( 0.3 ),
118 | "transitions": PoolRealArray( 1 ),
119 | "update": 3,
120 | "values": [ Color( 1, 1, 1, 0 ) ]
121 | }
122 | tracks/1/type = "method"
123 | tracks/1/path = NodePath(".")
124 | tracks/1/interp = 1
125 | tracks/1/loop_wrap = true
126 | tracks/1/imported = false
127 | tracks/1/enabled = true
128 | tracks/1/keys = {
129 | "times": PoolRealArray( 0.3 ),
130 | "transitions": PoolRealArray( 1 ),
131 | "values": [ {
132 | "args": [ ],
133 | "method": "hide"
134 | } ]
135 | }
136 |
137 | [sub_resource type="StyleBoxFlat" id=13]
138 | bg_color = Color( 0.839216, 0.466667, 0.533333, 1 )
139 |
140 | [sub_resource type="Animation" id=14]
141 | length = 0.3
142 | tracks/0/type = "value"
143 | tracks/0/path = NodePath(".:modulate")
144 | tracks/0/interp = 1
145 | tracks/0/loop_wrap = true
146 | tracks/0/imported = false
147 | tracks/0/enabled = true
148 | tracks/0/keys = {
149 | "times": PoolRealArray( 0.3 ),
150 | "transitions": PoolRealArray( 1 ),
151 | "update": 3,
152 | "values": [ Color( 1, 1, 1, 0 ) ]
153 | }
154 | tracks/1/type = "method"
155 | tracks/1/path = NodePath(".")
156 | tracks/1/interp = 1
157 | tracks/1/loop_wrap = true
158 | tracks/1/imported = false
159 | tracks/1/enabled = true
160 | tracks/1/keys = {
161 | "times": PoolRealArray( 0.3 ),
162 | "transitions": PoolRealArray( 1 ),
163 | "values": [ {
164 | "args": [ ],
165 | "method": "hide"
166 | } ]
167 | }
168 |
169 | [node name="Main" type="HSplitContainer"]
170 | anchor_right = 1.0
171 | anchor_bottom = 1.0
172 | theme = ExtResource( 4 )
173 | script = ExtResource( 1 )
174 | __meta__ = {
175 | "_edit_use_anchors_": false
176 | }
177 |
178 | [node name="PanelContainer" type="PanelContainer" parent="."]
179 | margin_right = 260.0
180 | margin_bottom = 600.0
181 | rect_min_size = Vector2( 260, 0 )
182 |
183 | [node name="MarginContainer" type="MarginContainer" parent="PanelContainer"]
184 | margin_right = 260.0
185 | margin_bottom = 600.0
186 | __meta__ = {
187 | "_edit_use_anchors_": false
188 | }
189 |
190 | [node name="DirectoryBrowser" type="VBoxContainer" parent="PanelContainer/MarginContainer"]
191 | margin_left = 20.0
192 | margin_top = 20.0
193 | margin_right = 240.0
194 | margin_bottom = 580.0
195 | custom_constants/separation = 10
196 | script = ExtResource( 8 )
197 |
198 | [node name="Load" type="Button" parent="PanelContainer/MarginContainer/DirectoryBrowser"]
199 | modulate = Color( 0.733333, 0.823529, 0.819608, 1 )
200 | margin_right = 220.0
201 | margin_bottom = 25.0
202 | shortcut = SubResource( 2 )
203 | text = "Root Folder"
204 | icon = ExtResource( 3 )
205 | clip_text = true
206 | align = 0
207 | __meta__ = {
208 | "_edit_use_anchors_": false
209 | }
210 |
211 | [node name="BrowserHelp" type="PanelContainer" parent="PanelContainer/MarginContainer/DirectoryBrowser"]
212 | margin_top = 35.0
213 | margin_right = 220.0
214 | margin_bottom = 234.0
215 | custom_styles/panel = SubResource( 3 )
216 | script = ExtResource( 16 )
217 |
218 | [node name="AnimationPlayer" type="AnimationPlayer" parent="PanelContainer/MarginContainer/DirectoryBrowser/BrowserHelp"]
219 | anims/hide = SubResource( 4 )
220 |
221 | [node name="MarginContainer" type="MarginContainer" parent="PanelContainer/MarginContainer/DirectoryBrowser/BrowserHelp"]
222 | margin_right = 220.0
223 | margin_bottom = 199.0
224 |
225 | [node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/MarginContainer/DirectoryBrowser/BrowserHelp/MarginContainer"]
226 | margin_left = 20.0
227 | margin_top = 20.0
228 | margin_right = 200.0
229 | margin_bottom = 179.0
230 |
231 | [node name="InfoBrowser" type="Label" parent="PanelContainer/MarginContainer/DirectoryBrowser/BrowserHelp/MarginContainer/HBoxContainer"]
232 | margin_right = 152.0
233 | margin_bottom = 159.0
234 | grow_vertical = 2
235 | size_flags_horizontal = 3
236 | size_flags_vertical = 0
237 | custom_colors/font_color = Color( 0.215686, 0.215686, 0.27451, 1 )
238 | text = "ctrl + o
239 |
240 | Start by selecting which folder you want to rummage through."
241 | autowrap = true
242 |
243 | [node name="Close" type="Button" parent="PanelContainer/MarginContainer/DirectoryBrowser/BrowserHelp/MarginContainer/HBoxContainer"]
244 | modulate = Color( 0.215686, 0.215686, 0.27451, 1 )
245 | margin_left = 156.0
246 | margin_right = 180.0
247 | margin_bottom = 25.0
248 | size_flags_horizontal = 0
249 | size_flags_vertical = 0
250 | icon = ExtResource( 12 )
251 | flat = true
252 |
253 | [node name="Tree" type="Tree" parent="PanelContainer/MarginContainer/DirectoryBrowser"]
254 | margin_top = 244.0
255 | margin_right = 220.0
256 | margin_bottom = 560.0
257 | rect_min_size = Vector2( 0, 80 )
258 | size_flags_vertical = 3
259 | hide_root = true
260 |
261 | [node name="FileDialog" type="FileDialog" parent="PanelContainer/MarginContainer/DirectoryBrowser"]
262 | margin_top = 386.0
263 | margin_right = 506.0
264 | margin_bottom = 578.0
265 | custom_colors/files_disabled = Color( 0.733333, 0.823529, 0.819608, 0.627451 )
266 | custom_colors/file_icon_modulate = Color( 0.733333, 0.823529, 0.819608, 1 )
267 | window_title = "Open a Directory"
268 | resizable = true
269 | mode = 2
270 | access = 2
271 | current_dir = "/home/richi/Projekte/SFX-Browser"
272 | current_path = "/home/richi/Projekte/SFX-Browser/"
273 |
274 | [node name="MarginContainer" type="MarginContainer" parent="."]
275 | margin_left = 272.0
276 | margin_right = 1024.0
277 | margin_bottom = 600.0
278 | custom_constants/margin_left = 6
279 |
280 | [node name="Workbench" type="VBoxContainer" parent="MarginContainer"]
281 | margin_left = 6.0
282 | margin_top = 20.0
283 | margin_right = 732.0
284 | margin_bottom = 580.0
285 | size_flags_horizontal = 15
286 | size_flags_vertical = 15
287 | custom_constants/separation = 10
288 | __meta__ = {
289 | "_edit_use_anchors_": false
290 | }
291 |
292 | [node name="Playback" type="HBoxContainer" parent="MarginContainer/Workbench"]
293 | margin_right = 726.0
294 | margin_bottom = 25.0
295 | mouse_filter = 2
296 | size_flags_horizontal = 15
297 | custom_constants/separation = 10
298 | script = ExtResource( 10 )
299 | __meta__ = {
300 | "_edit_use_anchors_": false
301 | }
302 |
303 | [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="MarginContainer/Workbench/Playback"]
304 |
305 | [node name="Logo" type="TextureRect" parent="MarginContainer/Workbench/Playback"]
306 | margin_right = 24.0
307 | margin_bottom = 25.0
308 | texture = ExtResource( 2 )
309 |
310 | [node name="Title" type="Label" parent="MarginContainer/Workbench/Playback"]
311 | modulate = Color( 0.807843, 0.917647, 0.780392, 1 )
312 | margin_left = 34.0
313 | margin_right = 138.0
314 | margin_bottom = 25.0
315 | size_flags_horizontal = 13
316 | size_flags_vertical = 15
317 | text = "SFX Browser"
318 | valign = 1
319 | __meta__ = {
320 | "_edit_use_anchors_": false
321 | }
322 |
323 | [node name="VSeparator2" type="VSeparator" parent="MarginContainer/Workbench/Playback"]
324 | margin_left = 148.0
325 | margin_right = 590.0
326 | margin_bottom = 25.0
327 | size_flags_horizontal = 3
328 | custom_styles/separator = SubResource( 5 )
329 |
330 | [node name="Play" type="Button" parent="MarginContainer/Workbench/Playback"]
331 | modulate = Color( 0.45098, 0.45098, 0.509804, 1 )
332 | margin_left = 600.0
333 | margin_right = 624.0
334 | margin_bottom = 25.0
335 | shortcut = SubResource( 7 )
336 | icon = ExtResource( 6 )
337 | __meta__ = {
338 | "_edit_use_anchors_": false
339 | }
340 |
341 | [node name="Loop" type="Button" parent="MarginContainer/Workbench/Playback"]
342 | modulate = Color( 0.45098, 0.45098, 0.509804, 1 )
343 | margin_left = 634.0
344 | margin_right = 658.0
345 | margin_bottom = 25.0
346 | toggle_mode = true
347 | keep_pressed_outside = true
348 | shortcut = SubResource( 9 )
349 | icon = ExtResource( 5 )
350 | __meta__ = {
351 | "_edit_use_anchors_": false
352 | }
353 |
354 | [node name="Help" type="Button" parent="MarginContainer/Workbench/Playback"]
355 | modulate = Color( 0.45098, 0.45098, 0.509804, 1 )
356 | margin_left = 668.0
357 | margin_right = 692.0
358 | margin_bottom = 25.0
359 | icon = ExtResource( 15 )
360 | align = 0
361 | __meta__ = {
362 | "_edit_use_anchors_": false
363 | }
364 |
365 | [node name="Info" type="Button" parent="MarginContainer/Workbench/Playback"]
366 | modulate = Color( 0.45098, 0.45098, 0.509804, 1 )
367 | margin_left = 702.0
368 | margin_right = 726.0
369 | margin_bottom = 25.0
370 | icon = ExtResource( 14 )
371 | align = 0
372 | __meta__ = {
373 | "_edit_use_anchors_": false
374 | }
375 |
376 | [node name="InfoBox" type="PanelContainer" parent="MarginContainer/Workbench"]
377 | margin_top = 35.0
378 | margin_right = 726.0
379 | margin_bottom = 80.0
380 | custom_styles/panel = SubResource( 10 )
381 | script = ExtResource( 17 )
382 |
383 | [node name="AnimationPlayer" type="AnimationPlayer" parent="MarginContainer/Workbench/InfoBox"]
384 | anims/hide = SubResource( 11 )
385 |
386 | [node name="MarginContainer" type="MarginContainer" parent="MarginContainer/Workbench/InfoBox"]
387 | margin_right = 726.0
388 | margin_bottom = 45.0
389 | custom_constants/margin_bottom = 0
390 |
391 | [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/Workbench/InfoBox/MarginContainer"]
392 | margin_left = 20.0
393 | margin_top = 20.0
394 | margin_right = 706.0
395 | margin_bottom = 45.0
396 |
397 | [node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/Workbench/InfoBox/MarginContainer/HBoxContainer"]
398 | margin_right = 658.0
399 | margin_bottom = 25.0
400 | size_flags_horizontal = 3
401 | custom_colors/default_color = Color( 0.215686, 0.215686, 0.27451, 1 )
402 | bbcode_enabled = true
403 | bbcode_text = "SAMPLE BROWSER"
404 | text = "SAMPLE BROWSER"
405 | fit_content_height = true
406 |
407 | [node name="Close" type="Button" parent="MarginContainer/Workbench/InfoBox/MarginContainer/HBoxContainer"]
408 | modulate = Color( 0.215686, 0.215686, 0.27451, 1 )
409 | margin_left = 662.0
410 | margin_right = 686.0
411 | margin_bottom = 25.0
412 | size_flags_horizontal = 0
413 | size_flags_vertical = 0
414 | icon = ExtResource( 12 )
415 | flat = true
416 |
417 | [node name="PlaybackHelp" type="PanelContainer" parent="MarginContainer/Workbench"]
418 | margin_top = 90.0
419 | margin_right = 726.0
420 | margin_bottom = 289.0
421 | custom_styles/panel = SubResource( 3 )
422 | script = ExtResource( 16 )
423 |
424 | [node name="AnimationPlayer" type="AnimationPlayer" parent="MarginContainer/Workbench/PlaybackHelp"]
425 | anims/hide = SubResource( 12 )
426 |
427 | [node name="MarginContainer" type="MarginContainer" parent="MarginContainer/Workbench/PlaybackHelp"]
428 | margin_right = 726.0
429 | margin_bottom = 199.0
430 |
431 | [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/Workbench/PlaybackHelp/MarginContainer"]
432 | margin_left = 20.0
433 | margin_top = 20.0
434 | margin_right = 706.0
435 | margin_bottom = 179.0
436 | custom_constants/separation = 20
437 |
438 | [node name="Info0" type="Label" parent="MarginContainer/Workbench/PlaybackHelp/MarginContainer/HBoxContainer"]
439 | margin_right = 145.0
440 | margin_bottom = 159.0
441 | grow_horizontal = 2
442 | grow_vertical = 2
443 | size_flags_horizontal = 3
444 | size_flags_vertical = 7
445 | custom_colors/font_color = Color( 0.215686, 0.215686, 0.27451, 1 )
446 | text = "ctrl + o
447 |
448 | Start by selecting which folder you want to rummage through."
449 | autowrap = true
450 |
451 | [node name="Info1" type="Label" parent="MarginContainer/Workbench/PlaybackHelp/MarginContainer/HBoxContainer"]
452 | margin_left = 165.0
453 | margin_right = 311.0
454 | margin_bottom = 159.0
455 | grow_horizontal = 2
456 | grow_vertical = 2
457 | size_flags_horizontal = 3
458 | size_flags_vertical = 7
459 | custom_colors/font_color = Color( 0.215686, 0.215686, 0.27451, 1 )
460 | text = "ctrl + o
461 |
462 | Start by selecting which folder you want to rummage through."
463 | autowrap = true
464 |
465 | [node name="Info2" type="Label" parent="MarginContainer/Workbench/PlaybackHelp/MarginContainer/HBoxContainer"]
466 | margin_left = 331.0
467 | margin_right = 476.0
468 | margin_bottom = 159.0
469 | grow_horizontal = 2
470 | grow_vertical = 2
471 | size_flags_horizontal = 3
472 | size_flags_vertical = 7
473 | custom_colors/font_color = Color( 0.215686, 0.215686, 0.27451, 1 )
474 | text = "ctrl + o
475 |
476 | Start by selecting which folder you want to rummage through."
477 | autowrap = true
478 |
479 | [node name="Info3" type="Label" parent="MarginContainer/Workbench/PlaybackHelp/MarginContainer/HBoxContainer"]
480 | margin_left = 496.0
481 | margin_right = 642.0
482 | margin_bottom = 159.0
483 | grow_horizontal = 2
484 | grow_vertical = 2
485 | size_flags_horizontal = 3
486 | size_flags_vertical = 7
487 | custom_colors/font_color = Color( 0.215686, 0.215686, 0.27451, 1 )
488 | text = "ctrl + o
489 |
490 | Start by selecting which folder you want to rummage through."
491 | autowrap = true
492 |
493 | [node name="Close" type="Button" parent="MarginContainer/Workbench/PlaybackHelp/MarginContainer/HBoxContainer"]
494 | modulate = Color( 0.215686, 0.215686, 0.27451, 1 )
495 | margin_left = 662.0
496 | margin_right = 686.0
497 | margin_bottom = 25.0
498 | size_flags_horizontal = 0
499 | size_flags_vertical = 0
500 | icon = ExtResource( 12 )
501 | flat = true
502 |
503 | [node name="HSeparator1" type="HSeparator" parent="MarginContainer/Workbench"]
504 | margin_top = 299.0
505 | margin_right = 726.0
506 | margin_bottom = 309.0
507 | size_flags_horizontal = 3
508 |
509 | [node name="Playlist" type="ScrollContainer" parent="MarginContainer/Workbench"]
510 | margin_top = 319.0
511 | margin_right = 726.0
512 | margin_bottom = 430.0
513 | size_flags_horizontal = 3
514 | size_flags_vertical = 3
515 | follow_focus = true
516 | scroll_horizontal_enabled = false
517 | script = ExtResource( 9 )
518 | __meta__ = {
519 | "_edit_use_anchors_": false
520 | }
521 |
522 | [node name="AnalizeThread" type="Node" parent="MarginContainer/Workbench/Playlist"]
523 | script = ExtResource( 7 )
524 |
525 | [node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/Workbench/Playlist"]
526 | margin_right = 726.0
527 | margin_bottom = 111.0
528 | size_flags_horizontal = 3
529 | size_flags_vertical = 15
530 |
531 | [node name="HSeparator2" type="HSeparator" parent="MarginContainer/Workbench"]
532 | margin_top = 440.0
533 | margin_right = 726.0
534 | margin_bottom = 450.0
535 | size_flags_horizontal = 3
536 |
537 | [node name="MessageBox" type="PanelContainer" parent="MarginContainer/Workbench"]
538 | margin_top = 460.0
539 | margin_right = 726.0
540 | margin_bottom = 525.0
541 | rect_min_size = Vector2( 0, 40 )
542 | custom_styles/panel = SubResource( 13 )
543 | script = ExtResource( 13 )
544 |
545 | [node name="Timer" type="Timer" parent="MarginContainer/Workbench/MessageBox"]
546 | wait_time = 8.0
547 | one_shot = true
548 |
549 | [node name="AnimationPlayer" type="AnimationPlayer" parent="MarginContainer/Workbench/MessageBox"]
550 | anims/hide = SubResource( 14 )
551 |
552 | [node name="MarginContainer" type="MarginContainer" parent="MarginContainer/Workbench/MessageBox"]
553 | margin_right = 726.0
554 | margin_bottom = 65.0
555 |
556 | [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/Workbench/MessageBox/MarginContainer"]
557 | margin_left = 20.0
558 | margin_top = 20.0
559 | margin_right = 706.0
560 | margin_bottom = 45.0
561 |
562 | [node name="Label" type="Label" parent="MarginContainer/Workbench/MessageBox/MarginContainer/HBoxContainer"]
563 | margin_right = 658.0
564 | margin_bottom = 24.0
565 | size_flags_horizontal = 3
566 | custom_colors/font_color = Color( 0.215686, 0.215686, 0.27451, 1 )
567 | text = "error text"
568 |
569 | [node name="Close" type="Button" parent="MarginContainer/Workbench/MessageBox/MarginContainer/HBoxContainer"]
570 | modulate = Color( 0.215686, 0.215686, 0.27451, 1 )
571 | margin_left = 662.0
572 | margin_right = 686.0
573 | margin_bottom = 25.0
574 | size_flags_horizontal = 0
575 | size_flags_vertical = 0
576 | icon = ExtResource( 12 )
577 |
578 | [node name="Export" type="HBoxContainer" parent="MarginContainer/Workbench"]
579 | margin_top = 535.0
580 | margin_right = 726.0
581 | margin_bottom = 560.0
582 | rect_min_size = Vector2( 0, 20 )
583 | size_flags_horizontal = 3
584 | custom_constants/separation = 10
585 | script = ExtResource( 11 )
586 | __meta__ = {
587 | "_edit_use_anchors_": false
588 | }
589 |
590 | [node name="Clear" type="Button" parent="MarginContainer/Workbench/Export"]
591 | modulate = Color( 0.733333, 0.823529, 0.819608, 1 )
592 | margin_right = 138.0
593 | margin_bottom = 25.0
594 | text = "clear all"
595 | icon = ExtResource( 12 )
596 | align = 0
597 | __meta__ = {
598 | "_edit_use_anchors_": false
599 | }
600 |
601 | [node name="VSeparator" type="VSeparator" parent="MarginContainer/Workbench/Export"]
602 | margin_left = 148.0
603 | margin_right = 188.0
604 | margin_bottom = 25.0
605 |
606 | [node name="ExportPath" type="Button" parent="MarginContainer/Workbench/Export"]
607 | modulate = Color( 0.733333, 0.823529, 0.819608, 1 )
608 | margin_left = 198.0
609 | margin_right = 222.0
610 | margin_bottom = 25.0
611 | icon = ExtResource( 3 )
612 | __meta__ = {
613 | "_edit_use_anchors_": false
614 | }
615 |
616 | [node name="FolderPath" type="Label" parent="MarginContainer/Workbench/Export"]
617 | margin_left = 232.0
618 | margin_right = 650.0
619 | margin_bottom = 25.0
620 | size_flags_horizontal = 15
621 | size_flags_vertical = 15
622 | text = "..."
623 | valign = 1
624 | __meta__ = {
625 | "_edit_use_anchors_": false
626 | }
627 |
628 | [node name="Export" type="Button" parent="MarginContainer/Workbench/Export"]
629 | margin_left = 660.0
630 | margin_right = 726.0
631 | margin_bottom = 25.0
632 | text = "export"
633 | __meta__ = {
634 | "_edit_use_anchors_": false
635 | }
636 |
637 | [node name="FileDialog" type="FileDialog" parent="MarginContainer/Workbench/Export"]
638 | margin_left = 269.0
639 | margin_right = 732.0
640 | margin_bottom = 143.0
641 | window_title = "Open a Directory"
642 | resizable = true
643 | mode = 2
644 | access = 2
645 | current_dir = "/home/richi/Projekte/SFX-Browser"
646 | current_path = "/home/richi/Projekte/SFX-Browser/"
647 |
648 | [connection signal="pressed" from="PanelContainer/MarginContainer/DirectoryBrowser/Load" to="PanelContainer/MarginContainer/DirectoryBrowser" method="_on_Load_pressed"]
649 | [connection signal="pressed" from="PanelContainer/MarginContainer/DirectoryBrowser/BrowserHelp/MarginContainer/HBoxContainer/Close" to="PanelContainer/MarginContainer/DirectoryBrowser/BrowserHelp" method="_on_Close_pressed"]
650 | [connection signal="item_selected" from="PanelContainer/MarginContainer/DirectoryBrowser/Tree" to="PanelContainer/MarginContainer/DirectoryBrowser" method="_on_Tree_item_selected"]
651 | [connection signal="dir_selected" from="PanelContainer/MarginContainer/DirectoryBrowser/FileDialog" to="PanelContainer/MarginContainer/DirectoryBrowser" method="_on_FileDialog_dir_selected"]
652 | [connection signal="finished" from="MarginContainer/Workbench/Playback/AudioStreamPlayer" to="MarginContainer/Workbench/Playback" method="_on_AudioStreamPlayer_finished"]
653 | [connection signal="pressed" from="MarginContainer/Workbench/Playback/Play" to="MarginContainer/Workbench/Playback" method="_on_Play_pressed"]
654 | [connection signal="toggled" from="MarginContainer/Workbench/Playback/Loop" to="MarginContainer/Workbench/Playback" method="_on_Loop_toggled"]
655 | [connection signal="pressed" from="MarginContainer/Workbench/Playback/Help" to="MarginContainer/Workbench/Playback" method="_on_Help_pressed"]
656 | [connection signal="pressed" from="MarginContainer/Workbench/Playback/Info" to="MarginContainer/Workbench/Playback" method="_on_Info_pressed"]
657 | [connection signal="meta_clicked" from="MarginContainer/Workbench/InfoBox/MarginContainer/HBoxContainer/RichTextLabel" to="MarginContainer/Workbench/InfoBox" method="_on_RichTextLabel_meta_clicked"]
658 | [connection signal="pressed" from="MarginContainer/Workbench/InfoBox/MarginContainer/HBoxContainer/Close" to="MarginContainer/Workbench/InfoBox" method="_on_Close_pressed"]
659 | [connection signal="pressed" from="MarginContainer/Workbench/PlaybackHelp/MarginContainer/HBoxContainer/Close" to="MarginContainer/Workbench/PlaybackHelp" method="_on_Close_pressed"]
660 | [connection signal="timeout" from="MarginContainer/Workbench/MessageBox/Timer" to="MarginContainer/Workbench/MessageBox" method="_on_Timer_timeout"]
661 | [connection signal="pressed" from="MarginContainer/Workbench/MessageBox/MarginContainer/HBoxContainer/Close" to="MarginContainer/Workbench/MessageBox" method="_on_Close_pressed"]
662 | [connection signal="pressed" from="MarginContainer/Workbench/Export/Clear" to="MarginContainer/Workbench/Export" method="_on_Clear_pressed"]
663 | [connection signal="pressed" from="MarginContainer/Workbench/Export/ExportPath" to="MarginContainer/Workbench/Export" method="_on_ExportPath_pressed"]
664 | [connection signal="pressed" from="MarginContainer/Workbench/Export/Export" to="MarginContainer/Workbench/Export" method="_on_Export_pressed"]
665 | [connection signal="dir_selected" from="MarginContainer/Workbench/Export/FileDialog" to="MarginContainer/Workbench/Export" method="_on_FileDialog_dir_selected"]
666 |
--------------------------------------------------------------------------------