commit 5b667d0ea50f84898e842f53f4751b2464eb008f Author: Hamcha Date: Mon Jun 29 16:53:39 2020 +0200 First commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cfc3df4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.mp4 +*.webm +*.mkv +export \ No newline at end of file diff --git a/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.md5 b/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.md5 new file mode 100644 index 0000000..f3d24d4 --- /dev/null +++ b/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.md5 @@ -0,0 +1,3 @@ +source_md5="6c4f0854417e25f28a78a6d5bc6c861b" +dest_md5="4a45b895909a5a7ee73376500dcc91cb" + diff --git a/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex b/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex new file mode 100644 index 0000000..ace8440 Binary files /dev/null and b/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex differ diff --git a/.import/logo.png-e2220799298e3631eb0e245316e0501a.md5 b/.import/logo.png-e2220799298e3631eb0e245316e0501a.md5 new file mode 100644 index 0000000..3d5ffd2 --- /dev/null +++ b/.import/logo.png-e2220799298e3631eb0e245316e0501a.md5 @@ -0,0 +1,3 @@ +source_md5="dee400f81183c985487fd90658d5d775" +dest_md5="235ef106e2c691bdd3fa260662a7fb04" + diff --git a/.import/logo.png-e2220799298e3631eb0e245316e0501a.stex b/.import/logo.png-e2220799298e3631eb0e245316e0501a.stex new file mode 100644 index 0000000..2631164 Binary files /dev/null and b/.import/logo.png-e2220799298e3631eb0e245316e0501a.stex differ diff --git a/Main.gd b/Main.gd new file mode 100644 index 0000000..b41052a --- /dev/null +++ b/Main.gd @@ -0,0 +1,127 @@ +extends Control + +signal finished + +var os: String +var executable: String + +var video_url: String setget set_url +var analyzed: bool = false setget set_analyzed +var audio_only: bool = false +var format_checked: bool = false setget set_format_checked +var ratelimit_checked: bool = false setget set_ratelimit_checked +var finished: bool = false +var lastLine: String = "" + +onready var analyzeWarning = $Panel/Margin/Main/Settings/General/VBox/Format/Option as HBoxContainer +onready var analyzeButton = $Panel/Margin/Main/Settings/General/VBox/Format/Option/Button as Button +onready var formatCheckbox = $Panel/Margin/Main/Settings/General/VBox/Format/Checkbox as CheckBox +onready var formatMenu = $Panel/Margin/Main/Settings/General/VBox/Format/MenuButton as OptionButton +onready var rateLimitValue = $Panel/Margin/Main/Settings/Network/VBox/RateLimit/Value as LineEdit +onready var progressText = $ProgressBG/ProgressPanel/TextEdit as TextEdit +onready var downloadButton = $Panel/Margin/Main/Actions/Download as Button + +func _analyze(): + run_youtubedl(["-F", video_url]) + +func _download(): + var output = run_youtubedl_blocking(["--get-filename", video_url]) + $FileDialog.current_file = output[0].strip_edges() + $FileDialog.popup_centered_ratio() + +func _download_with_name(name): + run_youtubedl(["-o", name, video_url]) + +func set_url(new_val): + video_url = new_val + set_analyzed(false) + downloadButton.disabled = video_url.length() == 0 + +func _url_changed(new_text): + set_url(new_text) + +func set_analyzed(new_val): + analyzed = new_val + analyzeWarning.visible = !analyzed + analyzeButton.disabled = video_url.length() == 0 + formatCheckbox.disabled = !analyzed + formatMenu.disabled = !analyzed or !format_checked + +func _format_checkbox_changed(button_pressed): + set_format_checked(button_pressed) + +func set_format_checked(new_val): + format_checked = new_val + formatMenu.disabled = !analyzed or !format_checked + +func _audio_checkbox_changed(button_pressed): + audio_only = button_pressed + +func _ratelimit_checkbox_changed(button_pressed): + set_ratelimit_checked(button_pressed) + +func set_ratelimit_checked(new_val): + ratelimit_checked = new_val + rateLimitValue.editable = ratelimit_checked + +func _ready(): + os = OS.get_name() + match os: + "Windows", "UWP", "OSX", "Server", "X11": + pass + _: + OS.alert("OS not supported") + get_tree().quit(1) + +var output = [] +func run_youtubedl_thread(params: Array): + output = [] + var exit = 0 + match os: + "Windows", "UWP": + params.push_front("bin\\youtube-dl.exe") + exit = OS.execute("bin\\sorun_win.exe", params, true, output, true) + finished = true + +var socketUDP = null + +func run_youtubedl_blocking(params): + output = [] + var exit = 0 + match os: + "Windows", "UWP": + exit = OS.execute("bin\\youtube-dl.exe", params, true, output, true) + return output + +func run_youtubedl(params): + print(params) + finished = false + var execute_thread = Thread.new() + execute_thread.start(self, "run_youtubedl_thread", params) + $ProgressBG.visible = true + + yield(get_tree().create_timer(0.5), "timeout") + # Start UDP client + socketUDP = PacketPeerUDP.new() + socketUDP.set_dest_address("127.0.0.1", 8987) + socketUDP.put_var(0) + progressText.text = "" + $Timer.start() + +func _timer_tick(): + while socketUDP.get_available_packet_count() > 0: + var newstr = socketUDP.get_packet().get_string_from_ascii() as String + if newstr == "\n": + emit_signal("finished") + return + if newstr.ends_with("\n") == false: + newstr += "\n" + progressText.text += newstr + lastLine = newstr.strip_edges() + progressText.scroll_vertical = 999 + +func _on_finish(): + $ProgressBG.visible = false + +func _target_selected(path): + _download_with_name(path.strip_edges()) diff --git a/Main.tscn b/Main.tscn new file mode 100644 index 0000000..08f04f6 --- /dev/null +++ b/Main.tscn @@ -0,0 +1,285 @@ +[gd_scene load_steps=7 format=2] + +[ext_resource path="res://theme.tres" type="Theme" id=1] +[ext_resource path="res://Main.gd" type="Script" id=2] + +[sub_resource type="StyleBoxFlat" id=1] +bg_color = Color( 0, 0, 0, 0.392157 ) + +[sub_resource type="StyleBoxFlat" id=2] +bg_color = Color( 0, 0, 0, 0.784314 ) +border_width_left = 2 +border_width_top = 2 +border_width_right = 2 +border_width_bottom = 2 +border_color = Color( 0.392157, 0.392157, 0.392157, 0.784314 ) +border_blend = true +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="StyleBoxEmpty" id=3] + +[sub_resource type="StyleBoxEmpty" id=4] + +[node name="Control" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Panel" type="Panel" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Margin" type="MarginContainer" parent="Panel"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 20.0 +margin_top = 20.0 +margin_right = -20.0 +margin_bottom = -20.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Main" type="VBoxContainer" parent="Panel/Margin"] +margin_right = 984.0 +margin_bottom = 560.0 +custom_constants/separation = 20 + +[node name="URL" type="VBoxContainer" parent="Panel/Margin/Main"] +margin_right = 984.0 +margin_bottom = 60.0 +custom_constants/separation = 10 + +[node name="Label" type="Label" parent="Panel/Margin/Main/URL"] +margin_right = 984.0 +margin_bottom = 20.0 +theme = ExtResource( 1 ) +text = "Page URL" + +[node name="Value" type="LineEdit" parent="Panel/Margin/Main/URL"] +margin_top = 30.0 +margin_right = 984.0 +margin_bottom = 60.0 +size_flags_horizontal = 3 +theme = ExtResource( 1 ) +placeholder_text = "Write your Youtube (or other website) URL here" + +[node name="Settings" type="TabContainer" parent="Panel/Margin/Main"] +margin_top = 80.0 +margin_right = 984.0 +margin_bottom = 500.0 +size_flags_vertical = 3 +theme = ExtResource( 1 ) +tab_align = 0 + +[node name="General" type="MarginContainer" parent="Panel/Margin/Main/Settings"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 38.0 +margin_right = -4.0 +margin_bottom = -4.0 +custom_constants/margin_right = 5 +custom_constants/margin_top = 5 +custom_constants/margin_left = 5 +custom_constants/margin_bottom = 5 + +[node name="VBox" type="VBoxContainer" parent="Panel/Margin/Main/Settings/General"] +process_priority = 10 +margin_left = 5.0 +margin_top = 5.0 +margin_right = 971.0 +margin_bottom = 373.0 +custom_constants/separation = 20 + +[node name="Audio" type="CheckBox" parent="Panel/Margin/Main/Settings/General/VBox"] +margin_right = 966.0 +margin_bottom = 28.0 +theme = ExtResource( 1 ) +text = "Audio only" + +[node name="Format" type="VBoxContainer" parent="Panel/Margin/Main/Settings/General/VBox"] +margin_top = 48.0 +margin_right = 966.0 +margin_bottom = 136.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Option" type="HBoxContainer" parent="Panel/Margin/Main/Settings/General/VBox/Format"] +margin_right = 966.0 +margin_bottom = 26.0 + +[node name="Label" type="Label" parent="Panel/Margin/Main/Settings/General/VBox/Format/Option"] +margin_right = 340.0 +margin_bottom = 26.0 +size_flags_vertical = 7 +theme = ExtResource( 1 ) +text = "To choose a format, analyze the video first: " +valign = 1 + +[node name="Button" type="Button" parent="Panel/Margin/Main/Settings/General/VBox/Format/Option"] +margin_left = 344.0 +margin_right = 417.0 +margin_bottom = 26.0 +theme = ExtResource( 1 ) +disabled = true +text = "Analyze" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Checkbox" type="CheckBox" parent="Panel/Margin/Main/Settings/General/VBox/Format"] +margin_top = 30.0 +margin_right = 966.0 +margin_bottom = 58.0 +theme = ExtResource( 1 ) +disabled = true +text = "Download specific format" + +[node name="MenuButton" type="OptionButton" parent="Panel/Margin/Main/Settings/General/VBox/Format"] +margin_top = 62.0 +margin_right = 966.0 +margin_bottom = 88.0 +theme = ExtResource( 1 ) +disabled = true +text = "Video format" + +[node name="Network" type="MarginContainer" parent="Panel/Margin/Main/Settings"] +visible = false +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 38.0 +margin_right = -4.0 +margin_bottom = -4.0 +custom_constants/margin_right = 5 +custom_constants/margin_top = 5 +custom_constants/margin_left = 5 +custom_constants/margin_bottom = 5 + +[node name="VBox" type="VBoxContainer" parent="Panel/Margin/Main/Settings/Network"] +process_priority = 10 +margin_left = 5.0 +margin_top = 5.0 +margin_right = 971.0 +margin_bottom = 373.0 +custom_constants/separation = 20 + +[node name="RateLimit" type="VBoxContainer" parent="Panel/Margin/Main/Settings/Network/VBox"] +process_priority = 10 +margin_right = 742.0 +margin_bottom = 62.0 + +[node name="Checkbox" type="CheckBox" parent="Panel/Margin/Main/Settings/Network/VBox/RateLimit"] +margin_right = 742.0 +margin_bottom = 28.0 +theme = ExtResource( 1 ) +text = "Set maximum download rate (in bytes per second)" + +[node name="Value" type="LineEdit" parent="Panel/Margin/Main/Settings/Network/VBox/RateLimit"] +margin_top = 32.0 +margin_right = 742.0 +margin_bottom = 62.0 +theme = ExtResource( 1 ) +editable = false +placeholder_text = "eg. 50K or 4.2M" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Geo box" type="CheckBox" parent="Panel/Margin/Main/Settings/Network/VBox"] +margin_top = 82.0 +margin_right = 742.0 +margin_bottom = 110.0 +theme = ExtResource( 1 ) +text = "Bypass geographic restriction via faking X-Forwarded-For HTTP header" + +[node name="Actions" type="HBoxContainer" parent="Panel/Margin/Main"] +margin_top = 520.0 +margin_right = 984.0 +margin_bottom = 560.0 + +[node name="Download" type="Button" parent="Panel/Margin/Main/Actions"] +margin_right = 150.0 +margin_bottom = 40.0 +rect_min_size = Vector2( 150, 40 ) +theme = ExtResource( 1 ) +disabled = true +text = "Download" + +[node name="ProgressBG" type="Panel" parent="."] +visible = false +anchor_right = 1.0 +anchor_bottom = 1.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +custom_styles/panel = SubResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ProgressPanel" type="Panel" parent="ProgressBG"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 40.0 +margin_top = 40.0 +margin_right = -40.0 +margin_bottom = -40.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +custom_styles/panel = SubResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="TextEdit" type="TextEdit" parent="ProgressBG/ProgressPanel"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 10.0 +margin_top = 10.0 +margin_right = -10.0 +margin_bottom = -10.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme = ExtResource( 1 ) +custom_styles/read_only = SubResource( 3 ) +custom_styles/normal = SubResource( 4 ) +custom_colors/font_color = Color( 1, 1, 1, 1 ) +readonly = true +context_menu_enabled = false +shortcut_keys_enabled = false +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Timer" type="Timer" parent="."] +wait_time = 0.2 + +[node name="FileDialog" type="FileDialog" parent="."] +margin_right = 341.0 +margin_bottom = 154.0 +window_title = "Save video" +resizable = true +dialog_hide_on_ok = true +access = 2 +current_dir = "/VC/yodel" +current_path = "/VC/yodel/" +[connection signal="finished" from="." to="." method="_on_finish"] +[connection signal="text_changed" from="Panel/Margin/Main/URL/Value" to="." method="_url_changed"] +[connection signal="toggled" from="Panel/Margin/Main/Settings/General/VBox/Audio" to="." method="_audio_checkbox_changed"] +[connection signal="pressed" from="Panel/Margin/Main/Settings/General/VBox/Format/Option/Button" to="." method="_analyze"] +[connection signal="toggled" from="Panel/Margin/Main/Settings/General/VBox/Format/Checkbox" to="." method="_format_checkbox_changed"] +[connection signal="toggled" from="Panel/Margin/Main/Settings/Network/VBox/RateLimit/Checkbox" to="." method="_ratelimit_checkbox_changed"] +[connection signal="pressed" from="Panel/Margin/Main/Actions/Download" to="." method="_download"] +[connection signal="timeout" from="Timer" to="." method="_timer_tick"] +[connection signal="file_selected" from="FileDialog" to="." method="_target_selected"] diff --git a/assets/Inter-Medium.ttf b/assets/Inter-Medium.ttf new file mode 100644 index 0000000..2c4114c Binary files /dev/null and b/assets/Inter-Medium.ttf differ diff --git a/assets/logo.afdesign b/assets/logo.afdesign new file mode 100644 index 0000000..cf9dfd4 Binary files /dev/null and b/assets/logo.afdesign differ diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000..ffe138d Binary files /dev/null and b/assets/logo.png differ diff --git a/assets/logo.png.import b/assets/logo.png.import new file mode 100644 index 0000000..30a0210 --- /dev/null +++ b/assets/logo.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/logo.png-e2220799298e3631eb0e245316e0501a.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/logo.png" +dest_files=[ "res://.import/logo.png-e2220799298e3631eb0e245316e0501a.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/bin/ffmpeg.exe b/bin/ffmpeg.exe new file mode 100644 index 0000000..c1b168c Binary files /dev/null and b/bin/ffmpeg.exe differ diff --git a/bin/sorun_darwin b/bin/sorun_darwin new file mode 100644 index 0000000..d5c9b6e Binary files /dev/null and b/bin/sorun_darwin differ diff --git a/bin/sorun_linux b/bin/sorun_linux new file mode 100644 index 0000000..a2ac65c Binary files /dev/null and b/bin/sorun_linux differ diff --git a/bin/sorun_win.exe b/bin/sorun_win.exe new file mode 100644 index 0000000..6318374 Binary files /dev/null and b/bin/sorun_win.exe differ diff --git a/bin/youtube-dl b/bin/youtube-dl new file mode 100644 index 0000000..a806646 Binary files /dev/null and b/bin/youtube-dl differ diff --git a/bin/youtube-dl.exe b/bin/youtube-dl.exe new file mode 100644 index 0000000..6331505 Binary files /dev/null and b/bin/youtube-dl.exe differ diff --git a/default_env.tres b/default_env.tres new file mode 100644 index 0000000..20207a4 --- /dev/null +++ b/default_env.tres @@ -0,0 +1,7 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="ProceduralSky" id=1] + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) diff --git a/export_presets.cfg b/export_presets.cfg new file mode 100644 index 0000000..b41437b --- /dev/null +++ b/export_presets.cfg @@ -0,0 +1,101 @@ +[preset.0] + +name="Windows Desktop" +platform="Windows Desktop" +runnable=true +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="export/yodel.exe" +patch_list=PoolStringArray( ) +script_export_mode=1 +script_encryption_key="" + +[preset.0.options] + +texture_format/bptc=false +texture_format/s3tc=true +texture_format/etc=false +texture_format/etc2=false +texture_format/no_bptc_fallbacks=true +binary_format/64_bits=true +binary_format/embed_pck=false +custom_template/release="" +custom_template/debug="" +codesign/enable=false +codesign/identity_type=0 +codesign/identity="" +codesign/password="" +codesign/timestamp=true +codesign/timestamp_server_url="" +codesign/digest_algorithm=1 +codesign/description="" +codesign/custom_options=PoolStringArray( ) +application/icon="res://win.ico" +application/file_version="0.1.0" +application/product_version="0.1.0" +application/company_name="Hamcha" +application/product_name="YoDeL" +application/file_description="Youtube-dl GUI" +application/copyright="" +application/trademarks="" + +[preset.1] + +name="Linux/X11" +platform="Linux/X11" +runnable=true +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="" +patch_list=PoolStringArray( ) +script_export_mode=1 +script_encryption_key="" + +[preset.1.options] + +texture_format/bptc=false +texture_format/s3tc=true +texture_format/etc=false +texture_format/etc2=false +texture_format/no_bptc_fallbacks=true +binary_format/64_bits=true +binary_format/embed_pck=false +custom_template/release="" +custom_template/debug="" + +[preset.2] + +name="Mac OSX" +platform="Mac OSX" +runnable=true +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="export/yodel.zip" +patch_list=PoolStringArray( ) +script_export_mode=1 +script_encryption_key="" + +[preset.2.options] + +custom_template/debug="" +custom_template/release="" +application/name="YoDeL" +application/info="youtube-dl GUI wrapper" +application/icon="res://icon.png" +application/identifier="com.hamcha.yodel" +application/signature="" +application/short_version="0.1" +application/version="0.1" +application/copyright="" +display/high_res=true +privacy/camera_usage_description="" +privacy/microphone_usage_description="" +texture_format/s3tc=true +texture_format/etc=false +texture_format/etc2=false diff --git a/font.tres b/font.tres new file mode 100644 index 0000000..e8333ae --- /dev/null +++ b/font.tres @@ -0,0 +1,6 @@ +[gd_resource type="DynamicFont" load_steps=2 format=2] + +[ext_resource path="res://assets/Inter-Medium.ttf" type="DynamicFontData" id=1] + +[resource] +font_data = ExtResource( 1 ) diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..deedf23 Binary files /dev/null and b/icon.png differ diff --git a/icon.png.import b/icon.png.import new file mode 100644 index 0000000..96cbf46 --- /dev/null +++ b/icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.png" +dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..78f3ffb --- /dev/null +++ b/project.godot @@ -0,0 +1,42 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=4 + +_global_script_classes=[ ] +_global_script_class_icons={ + +} + +[application] + +config/name="YoDeL" +config/description="youtube-dl GUI wrapper" +run/main_scene="res://Main.tscn" +run/low_processor_mode=true +boot_splash/image="res://assets/logo.png" +boot_splash/fullsize=false +config/icon="res://icon.png" +config/windows_native_icon="res://win.ico" + +[display] + +window/dpi/allow_hidpi=true + +[gui] + +theme/custom="res://theme.tres" +theme/custom_font="res://font.tres" + +[rendering] + +quality/driver/driver_name="GLES2" +vram_compression/import_etc=true +vram_compression/import_etc2=false +quality/depth/hdr=false +environment/default_environment="res://default_env.tres" diff --git a/theme.tres b/theme.tres new file mode 100644 index 0000000..65f5aee --- /dev/null +++ b/theme.tres @@ -0,0 +1,6 @@ +[gd_resource type="Theme" load_steps=2 format=2] + +[ext_resource path="res://font.tres" type="DynamicFont" id=1] + +[resource] +default_font = ExtResource( 1 ) diff --git a/tools/sorun.go b/tools/sorun.go new file mode 100644 index 0000000..a410df3 --- /dev/null +++ b/tools/sorun.go @@ -0,0 +1,64 @@ +package main + +import ( + "flag" + "io" + "net" + "os/exec" +) + +func main() { + bind := flag.String("bind", "127.0.0.1:8987", "Addr:Port to listen to") + flag.Parse() + + args := flag.Args() + + if flag.NArg() < 1 { + panic("no arguments provided") + } + uaddr, err := net.ResolveUDPAddr("udp", *bind) + if err != nil { + panic(err) + } + + lst, err := net.ListenUDP("udp", uaddr) + if err != nil { + panic(err) + } + defer lst.Close() + + cmd := exec.Command(args[0], args[1:]...) + stdoutIn, _ := cmd.StdoutPipe() + stderrIn, _ := cmd.StderrPipe() + output := io.MultiReader(stdoutIn, stderrIn) + + buf := make([]byte, 1024) + _, addr, err := lst.ReadFromUDP(buf) + if err != nil { + panic(err) + } + println("Received connection from %v", addr) + + go func() { + for { + _, err := output.Read(buf) + if err != nil { + if err == io.EOF { + return + } + panic(err) + } + lst.WriteTo(buf, addr) + } + }() + + defer func() { + lst.WriteTo([]byte("\n"), addr) + }() + + cmd.Start() + err = cmd.Wait() + if err != nil { + panic(err) + } +} diff --git a/win.ico b/win.ico new file mode 100644 index 0000000..68fd419 Binary files /dev/null and b/win.ico differ