Compare commits
	
		
			133 Commits
		
	
	
		
			4fa977347c
			...
			develop
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| a8602914ce | |||
| fb82846e9e | |||
| 4a9182d063 | |||
| 799d257e9d | |||
| 6adbff9bbf | |||
| fc4c916735 | |||
| aaf43c15aa | |||
| 04eb6b87f4 | |||
| 26827d5ccd | |||
| b56199fe8b | |||
| f6958ffa97 | |||
| 7f410ef700 | |||
| c4d205a79e | |||
| c45c106f2f | |||
| 63c13de181 | |||
| 57767de4b3 | |||
| c59c87d109 | |||
| 0a22377cd6 | |||
| 7930a907f1 | |||
| 850cbbaf70 | |||
| f4604f94c6 | |||
| 077d7a82a9 | |||
| e6db590937 | |||
| d7428683e4 | |||
| a9c59137af | |||
| c8619cdc7f | |||
| c49957e583 | |||
| 39080cac14 | |||
| cae996a141 | |||
| fc4e585620 | |||
| 690f84e2c8 | |||
| 568d8f0897 | |||
| 2909ef7cea | |||
| 1b1cdd5c22 | |||
| eb43669ae7 | |||
| 29ca392880 | |||
| df8095fb16 | |||
| e48f363de0 | |||
| 9bb835beaf | |||
| 9cdfa18fc8 | |||
| 6c0abac1c5 | |||
| 394824ce88 | |||
| 6e8b148c81 | |||
| 57637606c0 | |||
| c60b9f7b0c | |||
| b24155caf6 | |||
| 43d794373a | |||
| 3241b88158 | |||
| d69767f5e9 | |||
| 7340f43d6e | |||
| 5ab11922b9 | |||
| 5f72ce8c56 | |||
| 5b15848048 | |||
| 84b36dd29e | |||
| 82167f042f | |||
| 712ec2f182 | |||
| 883bf376b0 | |||
| 306383449a | |||
| a831d56d93 | |||
| 9d46db43c2 | |||
| 46d210d6d5 | |||
| 3149ca25e1 | |||
| 992762ef0a | |||
| 411e6c554a | |||
| bf3340e526 | |||
| 6be10dbd75 | |||
| 16b32e0167 | |||
| 2a7d860cbf | |||
| cf2a0933b4 | |||
| fa6c929ec8 | |||
| cce45ee791 | |||
| da7d9c8035 | |||
| 17c570bf1d | |||
| 86886fb5d9 | |||
| f262d5f931 | |||
| 12dc5c8ef9 | |||
| 9aaee4c183 | |||
| 2017617614 | |||
| 21d4afcedb | |||
| 8347e9fbb2 | |||
| 8d17a52f00 | |||
| 4668da3223 | |||
| a3b30c4543 | |||
| 3f358c8b7d | |||
| 7b7c15ad27 | |||
| a95692196e | |||
| 68d9c4bb66 | |||
| 1ece1e443d | |||
| 1eb7ea4a93 | |||
| e766c6d465 | |||
| 1f9f646f51 | |||
| d88586739a | |||
| a3db2b8f89 | |||
| d0539f5e90 | |||
| 240ae7aa96 | |||
| 0d05fdb307 | |||
| 8e6fb90482 | |||
| bab8c1f383 | |||
| a1c9143685 | |||
| c4ec958576 | |||
| 359db74251 | |||
| 154cd1c7dd | |||
| a617635911 | |||
| 48f8c577c0 | |||
| ee0a305972 | |||
| 3dc59344cb | |||
| f631c55eae | |||
| d46d642e61 | |||
| a82d283c1a | |||
| b7c363faaa | |||
| 2c0e20210f | |||
| eec298bfd7 | |||
| 2afc5f5b1a | |||
| fd7ce5fa08 | |||
| 05553f06b8 | |||
| 0d5cfab38d | |||
| d86c0d37af | |||
| f09dd01b6d | |||
| 6358d5d8cc | |||
| 5025807b14 | |||
| 0cd32bb0f0 | |||
| f3e034356b | |||
| 6f0bbf7e29 | |||
| 3c563d1966 | |||
| 6df775955f | |||
| d68382e418 | |||
| 846986279c | |||
| adf9bc9c27 | |||
| c572a3cabe | |||
| 7cc22e1553 | |||
| 9bb19a0263 | |||
| fc38a1b20c | |||
| 2596e822bd | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| fyne-cross/* | ||||
| ffmpeg/* | ||||
							
								
								
									
										14
									
								
								FyneApp.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								FyneApp.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| Website = "https://gui-for-ffmpeg.projects.kor-elf.net/language/en" | ||||
|  | ||||
| [Details] | ||||
|   Icon = "assets/icon.png" | ||||
|   Name = "GUI for FFmpeg" | ||||
|   ID = "net.kor-elf.projects.gui-for-ffmpeg" | ||||
|   Version = "1.0.1" | ||||
|   Build = 98 | ||||
|  | ||||
| [LinuxAndBSD] | ||||
|   GenericName = "GUI for FFmpeg" | ||||
|   Categories = ["AudioVideo", "Utility"] | ||||
|   Comment = "A simple interface for the FFmpeg console utility." | ||||
|   Keywords = ["ffmpeg", "media", "convert", "transcode", "audio", "video", "конвертер", "видео", "аудио", "кодек"] | ||||
							
								
								
									
										2426
									
								
								LICENSE-3RD-PARTY.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2426
									
								
								LICENSE-3RD-PARTY.txt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										88
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| VERSION ?= $(shell grep '^ *Version *= *' FyneApp.toml | sed -E "s/.*=[[:space:]]*\"([0-9\.]+)\".*/\1/") | ||||
|  | ||||
| BUILD_TMP := fyne-cross/tmp | ||||
|  | ||||
| WINDOWS_AMD64 := gui-for-ffmpeg-$(VERSION)-windows-amd64 | ||||
| BUILD_TMP_WINDOWS_AMD64 := $(BUILD_TMP)/$(WINDOWS_AMD64) | ||||
|  | ||||
| LINUX_AMD64 := gui-for-ffmpeg-$(VERSION)-linux-amd64 | ||||
| BUILD_TMP_LINUX_AMD64 := $(BUILD_TMP)/$(LINUX_AMD64) | ||||
|  | ||||
| RELEASES := fyne-cross/releases/$(VERSION) | ||||
|  | ||||
| default: | ||||
| 	# Run "make build-for-linux_amd64" | ||||
| 	# Run "make build-for-windows_amd64" | ||||
| 	# Build for all | ||||
| 	# Run "make build" | ||||
|  | ||||
| build: | ||||
| 	make build-for-linux_amd64 | ||||
| 	make build-for-windows_amd64 | ||||
| 	# $(RELEASES)/$(LINUX_AMD64).tar.gz | ||||
| 	# $(RELEASES)/$(LINUX_AMD64).tar.gz.sha256 | ||||
| 	# $(RELEASES)/$(WINDOWS_AMD64).zip | ||||
| 	# $(RELEASES)/$(WINDOWS_AMD64).zip.sha256 | ||||
|  | ||||
| build-for-windows_amd64: | ||||
| 	fyne-cross windows | ||||
|  | ||||
| 	@if [ -d $(BUILD_TMP_WINDOWS_AMD64) ]; then \ | ||||
| 		rm -rf $(BUILD_TMP_WINDOWS_AMD64)/*; \ | ||||
| 	else \ | ||||
| 		mkdir -p $(BUILD_TMP_WINDOWS_AMD64); \ | ||||
| 	fi | ||||
| 	cp LICENSE $(BUILD_TMP_WINDOWS_AMD64)/LICENSE | ||||
| 	cp LICENSE-3RD-PARTY.txt $(BUILD_TMP_WINDOWS_AMD64)/LICENSE-3RD-PARTY.txt | ||||
| 	cp "fyne-cross/bin/windows-amd64/GUI for FFmpeg.exe" $(BUILD_TMP_WINDOWS_AMD64)/gui-for-ffmpeg.exe | ||||
| 	cd $(BUILD_TMP) && 7z a -tzip $(WINDOWS_AMD64).zip $(WINDOWS_AMD64) | ||||
|  | ||||
| 	@if [ ! -d $(RELEASES) ]; then \ | ||||
| 		mkdir -p $(RELEASES); \ | ||||
| 	fi | ||||
|  | ||||
| 	@if [ -f $(RELEASES)/$(WINDOWS_AMD64).zip ]; then \ | ||||
| 		rm $(RELEASES)/$(WINDOWS_AMD64).zip; \ | ||||
| 	fi | ||||
|  | ||||
| 	@if [ -f $(RELEASES)/$(WINDOWS_AMD64).zip.sha256 ]; then \ | ||||
| 		rm $(RELEASES)/$(WINDOWS_AMD64).zip.sha256; \ | ||||
| 	fi | ||||
|  | ||||
| 	mv $(BUILD_TMP)/$(WINDOWS_AMD64).zip $(RELEASES)/$(WINDOWS_AMD64).zip | ||||
| 	cd $(RELEASES) && sha256sum $(WINDOWS_AMD64).zip > $(WINDOWS_AMD64).zip.sha256 | ||||
| 	# $(RELEASES)/$(WINDOWS_AMD64).zip | ||||
| 	# $(RELEASES)/$(WINDOWS_AMD64).zip.sha256 | ||||
|  | ||||
| build-for-linux_amd64: | ||||
| 	fyne-cross linux | ||||
|  | ||||
| 	@if [ -d $(BUILD_TMP_LINUX_AMD64) ]; then \ | ||||
| 		rm -rf $(BUILD_TMP_LINUX_AMD64)/*; \ | ||||
| 	else \ | ||||
| 		mkdir -p $(BUILD_TMP_LINUX_AMD64); \ | ||||
| 	fi | ||||
| 	cp -r dist/linux/* $(BUILD_TMP_LINUX_AMD64)/ | ||||
| 	cp LICENSE $(BUILD_TMP_LINUX_AMD64)/LICENSE | ||||
| 	cp LICENSE-3RD-PARTY.txt $(BUILD_TMP_LINUX_AMD64)/LICENSE-3RD-PARTY.txt | ||||
| 	cp fyne-cross/bin/linux-amd64/gui-for-ffmpeg $(BUILD_TMP_LINUX_AMD64)/usr/local/bin/gui-for-ffmpeg | ||||
| 	cp assets/icon.png $(BUILD_TMP_LINUX_AMD64)/usr/local/share/pixmaps/gui-for-ffmpeg.png | ||||
|  | ||||
| 	cd $(BUILD_TMP) && tar -czvf $(LINUX_AMD64).tar.gz $(LINUX_AMD64) | ||||
|  | ||||
| 	@if [ ! -d $(RELEASES) ]; then \ | ||||
| 		mkdir -p $(RELEASES); \ | ||||
| 	fi | ||||
|  | ||||
| 	@if [ -f $(RELEASES)/$(LINUX_AMD64).tar.gz ]; then \ | ||||
| 		rm $(RELEASES)/$(LINUX_AMD64).tar.gz; \ | ||||
| 	fi | ||||
|  | ||||
| 	@if [ -f $(RELEASES)/$(LINUX_AMD64).tar.gz.sha256 ]; then \ | ||||
| 		rm $(RELEASES)/$(LINUX_AMD64).tar.gz.sha256; \ | ||||
| 	fi | ||||
|  | ||||
| 	mv $(BUILD_TMP)/$(LINUX_AMD64).tar.gz $(RELEASES)/$(LINUX_AMD64).tar.gz | ||||
| 	cd $(RELEASES) && sha256sum $(LINUX_AMD64).tar.gz > $(LINUX_AMD64).tar.gz.sha256 | ||||
| 	# $(RELEASES)/$(LINUX_AMD64).tar.gz | ||||
| 	# $(RELEASES)/$(LINUX_AMD64).tar.gz.sha256 | ||||
							
								
								
									
										40
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,3 +1,39 @@ | ||||
| # ffmpeg-gui | ||||
| # GUI for FFmpeg | ||||
|  | ||||
| Простенький интерфейс к программе ffmpeg. | ||||
| <p>Простенький интерфейс для консольной утилиты FFmpeg. Но я <strong>не являюсь</strong> автором самой утилиты <strong>FFmpeg</strong>.</p> | ||||
| <p><strong>FFmpeg</strong> — торговая марка <strong><a href="https://bellard.org/" target="_blank">Fabrice Bellard</a></strong>, создателя проекта <strong><a href="https://ffmpeg.org/about.html" target="_blank">FFmpeg</a></strong>.</p> | ||||
|  | ||||
| <p>Программное обеспечение является MIT (см. <a href="https://git.kor-elf.net/kor-elf/gui-for-ffmpeg/src/branch/main/LICENSE">LICENSE</a>) и использует сторонние библиотеки, которые распространяются на их собственных условиях (см. <a href="https://git.kor-elf.net/kor-elf/gui-for-ffmpeg/src/branch/main/LICENSE-3RD-PARTY.txt">LICENSE-3RD-PARTY.txt</a>).</p> | ||||
|  | ||||
| <img src="assets/screenshot-gui-for-ffmpeg.png" alt="Скриншот программы"> | ||||
|  | ||||
| <p>Скачать скомпилированные готовые версии можно тут: <a href="https://git.kor-elf.net/kor-elf/gui-for-ffmpeg/releases">https://git.kor-elf.net/kor-elf/gui-for-ffmpeg/releases</a>.</p> | ||||
|  | ||||
| ## Установка через fyne: | ||||
| 1. go install fyne.io/fyne/v2/cmd/fyne@latest | ||||
| 2. fyne get git.kor-elf.net/kor-elf/gui-for-ffmpeg | ||||
|  | ||||
| ## Скомпилировать через Makefile: | ||||
| 1. git clone https://git.kor-elf.net/kor-elf/gui-for-ffmpeg.git | ||||
| 2. Переходим в папку проекта и там переходим в папку src: **cd gui-for-ffmpeg** | ||||
| 3. Ознакамливаемся, что нужно ещё установить для Вашей ОС для простого запуска (через go run) тут: https://docs.fyne.io/started/ | ||||
| 4. go install github.com/fyne-io/fyne-cross@latest | ||||
|    * У Вас так же должен быть установлен docker | ||||
|    * О fyne-cross можно по подробней почитать тут: https://github.com/fyne-io/fyne-cross | ||||
| 5. * make build-for-linux_amd64 | ||||
|    * make build-for-windows_amd64 | ||||
|    * Или просто **make build**  | ||||
| 6. Создаться папка с архивом в **fyne-cross/releases** | ||||
|  | ||||
| ## Скомпилировать через исходники: | ||||
| 1. git clone https://git.kor-elf.net/kor-elf/gui-for-ffmpeg.git | ||||
| 2. Переходим в папку проекта и там переходим в папку src: **cd gui-for-ffmpeg** | ||||
| 3. Ознакамливаемся, что нужно ещё установить для Вашей ОС для простого запуска (через go run) тут: https://docs.fyne.io/started/ | ||||
| 4. *(не обязательный шаг)* Просто запустить можно так: **go run main.go** | ||||
| 5. go install github.com/fyne-io/fyne-cross@latest | ||||
|    * У Вас так же должен быть установлен docker | ||||
|    * О fyne-cross можно по подробней почитать тут: https://github.com/fyne-io/fyne-cross | ||||
| 6. * fyne-cross windows | ||||
|    * fyne-cross linux | ||||
| 7. Создаться папка **fyne-cross/dist** и там будет созданна папка с тем названием под которую Вы компилировали приложения (linux-amd64 или windows-amd64). | ||||
| 8. В папке **fyne-cross/dist/linux-amd64** или **fyne-cross/dist/windows-amd64** будут архивы, которые надо распаковать и пользоваться программой. | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								assets/icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 29 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/screenshot-gui-for-ffmpeg.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/screenshot-gui-for-ffmpeg.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 77 KiB | 
							
								
								
									
										39
									
								
								dist/linux/Makefile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								dist/linux/Makefile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| # If PREFIX isn't provided, we check for $(DESTDIR)/usr/local and use that if it exists. | ||||
| # Otherwice we fall back to using /usr. | ||||
|  | ||||
| LOCAL != test -d $(DESTDIR)/usr/local && echo -n "/local" || echo -n "" | ||||
| LOCAL ?= $(shell test -d $(DESTDIR)/usr/local && echo "/local" || echo "") | ||||
| PREFIX ?= /usr$(LOCAL) | ||||
|  | ||||
| Name := "gui-for-ffmpeg" | ||||
| Exec := "gui-for-ffmpeg" | ||||
| Icon := "gui-for-ffmpeg.png" | ||||
|  | ||||
| default: | ||||
| 	# User install | ||||
| 	# Run "make user-install" to install in ~/.local/ | ||||
| 	# Run "make user-uninstall" to uninstall from ~/.local/ | ||||
| 	# | ||||
| 	# System install | ||||
| 	# Run "sudo make install" to install the application. | ||||
| 	# Run "sudo make uninstall" to uninstall the application. | ||||
|  | ||||
| install: | ||||
| 	install -Dm00644 usr/local/share/applications/$(Name).desktop $(DESTDIR)$(PREFIX)/share/applications/$(Name).desktop | ||||
| 	install -Dm00755 usr/local/bin/$(Exec) $(DESTDIR)$(PREFIX)/bin/$(Exec) | ||||
| 	install -Dm00644 usr/local/share/pixmaps/$(Icon) $(DESTDIR)$(PREFIX)/share/pixmaps/$(Icon) | ||||
| uninstall: | ||||
| 	-rm $(DESTDIR)$(PREFIX)/share/applications/$(Name).desktop | ||||
| 	-rm $(DESTDIR)$(PREFIX)/bin/$(Exec) | ||||
| 	-rm $(DESTDIR)$(PREFIX)/share/pixmaps/$(Icon) | ||||
|  | ||||
| user-install: | ||||
| 	install -Dm00644 usr/local/share/applications/$(Name).desktop $(DESTDIR)$(HOME)/.local/share/applications/$(Name).desktop | ||||
| 	install -Dm00755 usr/local/bin/$(Exec) $(DESTDIR)$(HOME)/.local/bin/$(Exec) | ||||
| 	install -Dm00644 usr/local/share/pixmaps/$(Icon) $(DESTDIR)$(HOME)/.local/share/icons/$(Icon) | ||||
| 	sed -i -e "s,Exec=$(Exec),Exec=$(DESTDIR)$(HOME)/.local/bin/$(Exec),g" $(DESTDIR)$(HOME)/.local/share/applications/$(Name).desktop | ||||
|  | ||||
| user-uninstall: | ||||
| 	-rm $(DESTDIR)$(HOME)/.local/share/applications/$(Name).desktop | ||||
| 	-rm $(DESTDIR)$(HOME)/.local/bin/$(Exec) | ||||
| 	-rm $(DESTDIR)$(HOME)/.local/share/icons/$(Icon) | ||||
							
								
								
									
										12
									
								
								dist/linux/Readme-eng.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								dist/linux/Readme-eng.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| User install | ||||
| Run "make user-install" to install in ~/.local/ | ||||
| Run "make user-uninstall" to uninstall from ~/.local/ | ||||
|  | ||||
| System install | ||||
| Run "sudo make install" to install the application. | ||||
| Run "sudo make uninstall" to uninstall the application. | ||||
|  | ||||
|  | ||||
| The program can be launched via the start menu in the Audio/Video or Standard section. | ||||
| You can also call the program via the terminal: | ||||
| gui-for-ffmpeg | ||||
							
								
								
									
										12
									
								
								dist/linux/Readme-rus.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								dist/linux/Readme-rus.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| Установить для пользователя (рекомендуется) | ||||
| Запустите "make user-install" для установки в домашнюю папку ~/.local/ | ||||
| Запустите "make user-uninstall" для удаления из домашней папки ~/.local/ | ||||
|  | ||||
| Установить для всей системы | ||||
| Запустить "sudo make install" Для установки в систему. | ||||
| Запустить "sudo make uninstall" Для удаления из системы. | ||||
|  | ||||
|  | ||||
| Программу можно запустить через пуск в разделе Аудио/Видео или Стандартные. | ||||
| Также можно вызвать программу через терминал: | ||||
| gui-for-ffmpeg | ||||
							
								
								
									
										2
									
								
								dist/linux/usr/local/bin/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								dist/linux/usr/local/bin/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| * | ||||
| !.gitignore | ||||
							
								
								
									
										9
									
								
								dist/linux/usr/local/share/applications/gui-for-ffmpeg.desktop
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								dist/linux/usr/local/share/applications/gui-for-ffmpeg.desktop
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| [Desktop Entry] | ||||
| Type=Application | ||||
| Name=GUI for FFmpeg | ||||
| GenericName=GUI for FFmpeg | ||||
| Exec=gui-for-ffmpeg | ||||
| Icon=gui-for-ffmpeg | ||||
| Comment=A simple interface for the FFmpeg console utility. | ||||
| Categories=AudioVideo;Utility; | ||||
| Keywords=ffmpeg;media;convert;transcode;audio;video;конвертер;видео;аудио;кодек; | ||||
							
								
								
									
										2
									
								
								dist/linux/usr/local/share/pixmaps/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								dist/linux/usr/local/share/pixmaps/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| * | ||||
| !.gitignore | ||||
							
								
								
									
										45
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| module git.kor-elf.net/kor-elf/gui-for-ffmpeg | ||||
|  | ||||
| go 1.23.0 | ||||
|  | ||||
| toolchain go1.23.9 | ||||
|  | ||||
| require ( | ||||
| 	fyne.io/fyne/v2 v2.6.3 | ||||
| 	github.com/ulikunitz/xz v0.5.13 | ||||
| 	golang.org/x/image v0.30.0 | ||||
| 	golang.org/x/text v0.28.0 | ||||
| ) | ||||
|  | ||||
| require ( | ||||
| 	fyne.io/systray v1.11.0 // indirect | ||||
| 	github.com/BurntSushi/toml v1.5.0 // indirect | ||||
| 	github.com/davecgh/go-spew v1.1.1 // indirect | ||||
| 	github.com/fredbi/uri v1.1.1 // indirect | ||||
| 	github.com/fsnotify/fsnotify v1.9.0 // indirect | ||||
| 	github.com/fyne-io/gl-js v0.2.0 // indirect | ||||
| 	github.com/fyne-io/glfw-js v0.3.0 // indirect | ||||
| 	github.com/fyne-io/image v0.1.1 // indirect | ||||
| 	github.com/fyne-io/oksvg v0.1.0 // indirect | ||||
| 	github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect | ||||
| 	github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728 // indirect | ||||
| 	github.com/go-text/render v0.2.0 // indirect | ||||
| 	github.com/go-text/typesetting v0.3.0 // indirect | ||||
| 	github.com/godbus/dbus/v5 v5.1.0 // indirect | ||||
| 	github.com/hack-pad/go-indexeddb v0.3.2 // indirect | ||||
| 	github.com/hack-pad/safejs v0.1.1 // indirect | ||||
| 	github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect | ||||
| 	github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect | ||||
| 	github.com/kr/text v0.2.0 // indirect | ||||
| 	github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect | ||||
| 	github.com/nicksnyder/go-i18n/v2 v2.6.0 // indirect | ||||
| 	github.com/pmezard/go-difflib v1.0.0 // indirect | ||||
| 	github.com/rymdport/portal v0.4.2 // indirect | ||||
| 	github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect | ||||
| 	github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect | ||||
| 	github.com/stretchr/testify v1.10.0 // indirect | ||||
| 	github.com/yuin/goldmark v1.7.13 // indirect | ||||
| 	golang.org/x/net v0.43.0 // indirect | ||||
| 	golang.org/x/sys v0.35.0 // indirect | ||||
| 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||
| ) | ||||
							
								
								
									
										106
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,106 @@ | ||||
| fyne.io/fyne/v2 v2.6.1 h1:kjPJD4/rBS9m2nHJp+npPSuaK79yj6ObMTuzR6VQ1Is= | ||||
| fyne.io/fyne/v2 v2.6.1/go.mod h1:YZt7SksjvrSNJCwbWFV32WON3mE1Sr7L41D29qMZ/lU= | ||||
| fyne.io/fyne/v2 v2.6.3 h1:cvtM2KHeRuH+WhtHiA63z5wJVBkQ9+Ay0UMl9PxFHyA= | ||||
| fyne.io/fyne/v2 v2.6.3/go.mod h1:NGSurpRElVoI1G3h+ab2df3O5KLGh1CGbsMMcX0bPIs= | ||||
| fyne.io/systray v1.11.0 h1:D9HISlxSkx+jHSniMBR6fCFOUjk1x/OOOJLa9lJYAKg= | ||||
| fyne.io/systray v1.11.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs= | ||||
| github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= | ||||
| github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= | ||||
| github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= | ||||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= | ||||
| github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= | ||||
| github.com/fredbi/uri v1.1.0 h1:OqLpTXtyRg9ABReqvDGdJPqZUxs8cyBDOMXBbskCaB8= | ||||
| github.com/fredbi/uri v1.1.0/go.mod h1:aYTUoAXBOq7BLfVJ8GnKmfcuURosB1xyHDIfWeC/iW4= | ||||
| github.com/fredbi/uri v1.1.1 h1:xZHJC08GZNIUhbP5ImTHnt5Ya0T8FI2VAwI/37kh2Ko= | ||||
| github.com/fredbi/uri v1.1.1/go.mod h1:4+DZQ5zBjEwQCDmXW5JdIjz0PUA+yJbvtBv+u+adr5o= | ||||
| github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= | ||||
| github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= | ||||
| github.com/fyne-io/gl-js v0.1.0 h1:8luJzNs0ntEAJo+8x8kfUOXujUlP8gB3QMOxO2mUdpM= | ||||
| github.com/fyne-io/gl-js v0.1.0/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI= | ||||
| github.com/fyne-io/gl-js v0.2.0 h1:+EXMLVEa18EfkXBVKhifYB6OGs3HwKO3lUElA0LlAjs= | ||||
| github.com/fyne-io/gl-js v0.2.0/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI= | ||||
| github.com/fyne-io/glfw-js v0.2.0 h1:8GUZtN2aCoTPNqgRDxK5+kn9OURINhBEBc7M4O1KrmM= | ||||
| github.com/fyne-io/glfw-js v0.2.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk= | ||||
| github.com/fyne-io/glfw-js v0.3.0 h1:d8k2+Y7l+zy2pc7wlGRyPfTgZoqDf3AI4G+2zOWhWUk= | ||||
| github.com/fyne-io/glfw-js v0.3.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk= | ||||
| github.com/fyne-io/image v0.1.1 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA= | ||||
| github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM= | ||||
| github.com/fyne-io/oksvg v0.1.0 h1:7EUKk3HV3Y2E+qypp3nWqMXD7mum0hCw2KEGhI1fnBw= | ||||
| github.com/fyne-io/oksvg v0.1.0/go.mod h1:dJ9oEkPiWhnTFNCmRgEze+YNprJF7YRbpjgpWS4kzoI= | ||||
| github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA= | ||||
| github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw= | ||||
| github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728 h1:RkGhqHxEVAvPM0/R+8g7XRwQnHatO0KAuVcwHo8q9W8= | ||||
| github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728/go.mod h1:SyRD8YfuKk+ZXlDqYiqe1qMSqjNgtHzBTG810KUagMc= | ||||
| github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc= | ||||
| github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU= | ||||
| github.com/go-text/typesetting v0.3.0 h1:OWCgYpp8njoxSRpwrdd1bQOxdjOXDj9Rqart9ML4iF4= | ||||
| github.com/go-text/typesetting v0.3.0/go.mod h1:qjZLkhRgOEYMhU9eHBr3AR4sfnGJvOXNLt8yRAySFuY= | ||||
| github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066 h1:qCuYC+94v2xrb1PoS4NIDe7DGYtLnU2wWiQe9a1B1c0= | ||||
| github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o= | ||||
| github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= | ||||
| github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= | ||||
| github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= | ||||
| github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= | ||||
| github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A= | ||||
| github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0= | ||||
| github.com/hack-pad/safejs v0.1.1 h1:d5qPO0iQ7h2oVtpzGnLExE+Wn9AtytxIfltcS2b9KD8= | ||||
| github.com/hack-pad/safejs v0.1.1/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio= | ||||
| github.com/jeandeaual/go-locale v0.0.0-20250421151639-a9d6ed1b3d45 h1:vFdvrlsVU+p/KFBWTq0lTG4fvWvG88sawGlCzM+RUEU= | ||||
| github.com/jeandeaual/go-locale v0.0.0-20250421151639-a9d6ed1b3d45/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o= | ||||
| github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE= | ||||
| github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o= | ||||
| github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M= | ||||
| github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw= | ||||
| github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= | ||||
| github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= | ||||
| github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= | ||||
| github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= | ||||
| github.com/nicksnyder/go-i18n/v2 v2.6.0 h1:C/m2NNWNiTB6SK4Ao8df5EWm3JETSTIGNXBpMJTxzxQ= | ||||
| github.com/nicksnyder/go-i18n/v2 v2.6.0/go.mod h1:88sRqr0C6OPyJn0/KRNaEz1uWorjxIKP7rUUcvycecE= | ||||
| github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= | ||||
| github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= | ||||
| github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= | ||||
| github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= | ||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
| github.com/rymdport/portal v0.4.1 h1:2dnZhjf5uEaeDjeF/yBIeeRo6pNI2QAKm7kq1w/kbnA= | ||||
| github.com/rymdport/portal v0.4.1/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4= | ||||
| github.com/rymdport/portal v0.4.2 h1:7jKRSemwlTyVHHrTGgQg7gmNPJs88xkbKcIL3NlcmSU= | ||||
| github.com/rymdport/portal v0.4.2/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4= | ||||
| github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE= | ||||
| github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q= | ||||
| github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= | ||||
| github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= | ||||
| github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= | ||||
| github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||||
| github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= | ||||
| github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= | ||||
| github.com/ulikunitz/xz v0.5.13 h1:ar98gWrjf4H1ev05fYP/o29PDZw9DrI3niHtnEqyuXA= | ||||
| github.com/ulikunitz/xz v0.5.13/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= | ||||
| github.com/yuin/goldmark v1.7.11 h1:ZCxLyDMtz0nT2HFfsYG8WZ47Trip2+JyLysKcMYE5bo= | ||||
| github.com/yuin/goldmark v1.7.11/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= | ||||
| github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA= | ||||
| github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= | ||||
| golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w= | ||||
| golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g= | ||||
| golang.org/x/image v0.30.0 h1:jD5RhkmVAnjqaCUXfbGBrn3lpxbknfN9w2UhHHU+5B4= | ||||
| golang.org/x/image v0.30.0/go.mod h1:SAEUTxCCMWSrJcCy/4HwavEsfZZJlYxeHLc6tTiAe/c= | ||||
| golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= | ||||
| golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= | ||||
| golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= | ||||
| golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= | ||||
| golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= | ||||
| golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= | ||||
| golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= | ||||
| golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= | ||||
| golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= | ||||
| golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= | ||||
| golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= | ||||
| golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= | ||||
| gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||||
| gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
							
								
								
									
										137
									
								
								internal/application/app.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								internal/application/app.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | ||||
| package application | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/convertor" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/setting" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| type AppContract interface { | ||||
| 	FyneApp() fyne.App | ||||
| 	GetSetting() setting.SettingContract | ||||
| 	GetProgressBarService() convertor.ProgressBarContract | ||||
| 	GetFFmpegService() ffmpeg.UtilitiesContract | ||||
| 	GetConvertorService() convertor.ConvertorContract | ||||
| 	GetItemsToConvert() convertor.ItemsToConvertContract | ||||
| 	GetQueueService() convertor.QueueListContract | ||||
| 	Run() | ||||
| 	AfterClosing() | ||||
| 	RunConvertor() | ||||
| } | ||||
|  | ||||
| type application struct { | ||||
| 	fyneApp            fyne.App | ||||
| 	setting            setting.SettingContract | ||||
| 	progressBarService convertor.ProgressBarContract | ||||
| 	ffmpegService      ffmpeg.UtilitiesContract | ||||
| 	itemsToConvert     convertor.ItemsToConvertContract | ||||
| 	queueService       convertor.QueueListContract | ||||
| 	convertorService   convertor.ConvertorContract | ||||
| } | ||||
|  | ||||
| func NewApp( | ||||
| 	fyneApp fyne.App, | ||||
| 	setting setting.SettingContract, | ||||
| 	progressBarService convertor.ProgressBarContract, | ||||
| 	ffmpegService ffmpeg.UtilitiesContract, | ||||
| 	itemsToConvert convertor.ItemsToConvertContract, | ||||
| 	queueService convertor.QueueListContract, | ||||
| 	convertorService convertor.ConvertorContract, | ||||
| ) AppContract { | ||||
| 	return &application{ | ||||
| 		fyneApp:            fyneApp, | ||||
| 		setting:            setting, | ||||
| 		progressBarService: progressBarService, | ||||
| 		ffmpegService:      ffmpegService, | ||||
| 		itemsToConvert:     itemsToConvert, | ||||
| 		queueService:       queueService, | ||||
| 		convertorService:   convertorService, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (a *application) FyneApp() fyne.App { | ||||
| 	return a.fyneApp | ||||
| } | ||||
|  | ||||
| func (a *application) GetSetting() setting.SettingContract { | ||||
| 	return a.setting | ||||
| } | ||||
|  | ||||
| func (a *application) GetProgressBarService() convertor.ProgressBarContract { | ||||
| 	return a.progressBarService | ||||
| } | ||||
|  | ||||
| func (a *application) GetFFmpegService() ffmpeg.UtilitiesContract { | ||||
| 	return a.ffmpegService | ||||
| } | ||||
|  | ||||
| func (a *application) GetItemsToConvert() convertor.ItemsToConvertContract { | ||||
| 	return a.itemsToConvert | ||||
| } | ||||
|  | ||||
| func (a *application) GetQueueService() convertor.QueueListContract { | ||||
| 	return a.queueService | ||||
| } | ||||
|  | ||||
| func (a *application) GetConvertorService() convertor.ConvertorContract { | ||||
| 	return a.convertorService | ||||
| } | ||||
|  | ||||
| func (a *application) Run() { | ||||
| 	a.fyneApp.Run() | ||||
| } | ||||
|  | ||||
| func (a *application) RunConvertor() { | ||||
| 	go func() { | ||||
| 		for { | ||||
| 			time.Sleep(time.Millisecond * 3000) | ||||
| 			queueId, queue := a.queueService.Next() | ||||
| 			if queue == nil { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			queue.Status = convertor.StatusType(convertor.InProgress) | ||||
| 			a.queueService.EventChangeQueue(queueId, queue) | ||||
|  | ||||
| 			if a.progressBarService.GetContainer().Hidden { | ||||
| 				a.progressBarService.GetContainer().Show() | ||||
| 			} | ||||
|  | ||||
| 			totalDuration := float64(0) | ||||
| 			ffprobe, err := a.ffmpegService.GetFFprobe() | ||||
| 			if err == nil { | ||||
| 				totalDuration, err = ffprobe.GetTotalDuration(&queue.Setting.FileInput) | ||||
| 				if err != nil { | ||||
| 					totalDuration = float64(0) | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			progress := a.progressBarService.GetProgressbar( | ||||
| 				totalDuration, | ||||
| 				queue.Setting.FileInput.Path, | ||||
| 			) | ||||
|  | ||||
| 			err = a.convertorService.RunConvert(*queue.Setting, progress) | ||||
| 			if err != nil { | ||||
| 				queue.Status = convertor.StatusType(convertor.Error) | ||||
| 				queue.Error = err | ||||
| 				a.queueService.EventChangeQueue(queueId, queue) | ||||
| 				a.progressBarService.ProcessEndedWithError(err.Error()) | ||||
|  | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			queue.Status = convertor.StatusType(convertor.Completed) | ||||
| 			a.queueService.EventChangeQueue(queueId, queue) | ||||
| 			a.progressBarService.ProcessEndedWithSuccess(&queue.Setting.FileOut) | ||||
| 		} | ||||
| 	}() | ||||
| } | ||||
|  | ||||
| func (a *application) AfterClosing() { | ||||
| 	for _, cmd := range a.convertorService.GetRunningProcesses() { | ||||
| 		_ = cmd.Process.Kill() | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										87
									
								
								internal/application/convertor/convertor.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								internal/application/convertor/convertor.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| package convertor | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/convertor/encoder" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg" | ||||
| 	"io" | ||||
| 	"os/exec" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type ConvertorContract interface { | ||||
| 	RunConvert(setting ffmpeg.ConvertSetting, progress ffmpeg.ProgressContract) error | ||||
| 	GetSupportFormats() (encoder.ConvertorFormatsContract, error) | ||||
| 	GetRunningProcesses() map[int]*exec.Cmd | ||||
| } | ||||
|  | ||||
| type runningProcesses struct { | ||||
| 	items          map[int]*exec.Cmd | ||||
| 	numberOfStarts int | ||||
| } | ||||
|  | ||||
| type convertor struct { | ||||
| 	ffmpegService    ffmpeg.UtilitiesContract | ||||
| 	runningProcesses *runningProcesses | ||||
| } | ||||
|  | ||||
| func NewConvertor( | ||||
| 	ffmpegService ffmpeg.UtilitiesContract, | ||||
| ) ConvertorContract { | ||||
| 	return &convertor{ | ||||
| 		ffmpegService:    ffmpegService, | ||||
| 		runningProcesses: &runningProcesses{items: map[int]*exec.Cmd{}, numberOfStarts: 0}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *convertor) RunConvert(setting ffmpeg.ConvertSetting, progress ffmpeg.ProgressContract) error { | ||||
| 	ffmpegService, err := c.ffmpegService.GetFFmpeg() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	index := c.runningProcesses.numberOfStarts | ||||
| 	beforeWait := func(cmd *exec.Cmd) { | ||||
| 		c.runningProcesses.numberOfStarts++ | ||||
| 		c.runningProcesses.items[index] = cmd | ||||
| 	} | ||||
|  | ||||
| 	afterWait := func(cmd *exec.Cmd) { | ||||
| 		delete(c.runningProcesses.items, index) | ||||
| 	} | ||||
|  | ||||
| 	return ffmpegService.RunConvert(setting, progress, beforeWait, afterWait) | ||||
| } | ||||
|  | ||||
| func (c *convertor) GetSupportFormats() (encoder.ConvertorFormatsContract, error) { | ||||
| 	var err error | ||||
|  | ||||
| 	formats := encoder.NewConvertorFormats() | ||||
| 	ffmpeg, err := c.ffmpegService.GetFFmpeg() | ||||
| 	if err != nil { | ||||
| 		return formats, err | ||||
| 	} | ||||
| 	err = ffmpeg.GetEncoders(func(scanner *bufio.Reader) { | ||||
| 		for { | ||||
| 			line, _, err := scanner.ReadLine() | ||||
| 			if err != nil { | ||||
| 				if err == io.EOF { | ||||
| 					break | ||||
| 				} | ||||
| 				continue | ||||
| 			} | ||||
| 			text := strings.Split(strings.TrimSpace(string(line)), " ") | ||||
| 			encoderType := string(text[0][0]) | ||||
| 			if len(text) < 2 || (encoderType != "V" && encoderType != "A") { | ||||
| 				continue | ||||
| 			} | ||||
| 			formats.NewEncoder(text[1]) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	return formats, err | ||||
| } | ||||
|  | ||||
| func (c *convertor) GetRunningProcesses() map[int]*exec.Cmd { | ||||
| 	return c.runningProcesses.items | ||||
| } | ||||
							
								
								
									
										84
									
								
								internal/application/convertor/encoder/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								internal/application/convertor/encoder/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| package encoder | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| type ConvertorFormatContract interface { | ||||
| 	GetTitle() string | ||||
| 	AddEncoder(encoder encoder.EncoderDataContract) | ||||
| 	GetFileType() encoder.FileTypeContract | ||||
| 	GetEncoders() map[int]encoder.EncoderDataContract | ||||
| } | ||||
|  | ||||
| type ConvertorFormat struct { | ||||
| 	title    string | ||||
| 	fileType encoder.FileTypeContract | ||||
| 	encoders map[int]encoder.EncoderDataContract | ||||
| } | ||||
|  | ||||
| func NewConvertorFormat(title string, fileType encoder.FileTypeContract) ConvertorFormatContract { | ||||
| 	return &ConvertorFormat{ | ||||
| 		title:    title, | ||||
| 		fileType: fileType, | ||||
| 		encoders: map[int]encoder.EncoderDataContract{}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (f *ConvertorFormat) GetTitle() string { | ||||
| 	return f.title | ||||
| } | ||||
|  | ||||
| func (f *ConvertorFormat) AddEncoder(encoder encoder.EncoderDataContract) { | ||||
| 	f.encoders[len(f.encoders)] = encoder | ||||
| } | ||||
|  | ||||
| func (f *ConvertorFormat) GetEncoders() map[int]encoder.EncoderDataContract { | ||||
| 	return f.encoders | ||||
| } | ||||
|  | ||||
| func (f *ConvertorFormat) GetFileType() encoder.FileTypeContract { | ||||
| 	return f.fileType | ||||
| } | ||||
|  | ||||
| type ConvertorFormatsContract interface { | ||||
| 	NewEncoder(encoderName string) bool | ||||
| 	GetFormats() map[string]ConvertorFormatContract | ||||
| 	GetFormat(format string) (ConvertorFormatContract, error) | ||||
| } | ||||
|  | ||||
| type ConvertorFormats struct { | ||||
| 	formats map[string]ConvertorFormatContract | ||||
| } | ||||
|  | ||||
| func NewConvertorFormats() ConvertorFormatsContract { | ||||
| 	return &ConvertorFormats{ | ||||
| 		formats: map[string]ConvertorFormatContract{}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (f *ConvertorFormats) NewEncoder(encoderName string) bool { | ||||
| 	if supportEncoders[encoderName] == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	data := supportEncoders[encoderName]() | ||||
| 	for _, format := range data.GetFormats() { | ||||
| 		if f.formats[format] == nil { | ||||
| 			f.formats[format] = NewConvertorFormat(format, data.GetFileType()) | ||||
| 		} | ||||
| 		f.formats[format].AddEncoder(data) | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (f *ConvertorFormats) GetFormats() map[string]ConvertorFormatContract { | ||||
| 	return f.formats | ||||
| } | ||||
|  | ||||
| func (f *ConvertorFormats) GetFormat(format string) (ConvertorFormatContract, error) { | ||||
| 	if f.formats[format] == nil { | ||||
| 		return &ConvertorFormat{}, errors.New("not found ConvertorFormat") | ||||
| 	} | ||||
| 	return f.formats[format], nil | ||||
| } | ||||
							
								
								
									
										74
									
								
								internal/application/convertor/encoder/encoders.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								internal/application/convertor/encoder/encoders.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| package encoder | ||||
|  | ||||
| import ( | ||||
| 	encoder2 "git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/apng" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/bmp" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/flv" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/gif" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/h264_nvenc" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/libmp3lame" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/libshine" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/libtwolame" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/libvpx" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/libvpx_vp9" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/libwebp" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/libwebp_anim" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/libx264" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/libx265" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/libxvid" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/mjpeg" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/mp2" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/mp2fixed" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/mpeg1video" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/mpeg2video" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/mpeg4" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/msmpeg4" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/msmpeg4v2" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/msvideo1" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/png" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/qtrle" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/sgi" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/tiff" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/wmav1" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/wmav2" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/wmv1" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/wmv2" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/xbm" | ||||
| ) | ||||
|  | ||||
| var supportEncoders = map[string]func() encoder2.EncoderDataContract{ | ||||
| 	"libx264":      libx264.NewData, | ||||
| 	"h264_nvenc":   h264_nvenc.NewData, | ||||
| 	"libx265":      libx265.NewData, | ||||
| 	"png":          png.NewData, | ||||
| 	"gif":          gif.NewData, | ||||
| 	"flv":          flv.NewData, | ||||
| 	"apng":         apng.NewData, | ||||
| 	"bmp":          bmp.NewData, | ||||
| 	"mjpeg":        mjpeg.NewData, | ||||
| 	"mpeg1video":   mpeg1video.NewData, | ||||
| 	"mpeg2video":   mpeg2video.NewData, | ||||
| 	"mpeg4":        mpeg4.NewData, | ||||
| 	"libxvid":      libxvid.NewData, | ||||
| 	"msmpeg4v2":    msmpeg4v2.NewData, | ||||
| 	"msmpeg4":      msmpeg4.NewData, | ||||
| 	"msvideo1":     msvideo1.NewData, | ||||
| 	"qtrle":        qtrle.NewData, | ||||
| 	"tiff":         tiff.NewData, | ||||
| 	"sgi":          sgi.NewData, | ||||
| 	"libvpx":       libvpx.NewData, | ||||
| 	"libvpx-vp9":   libvpx_vp9.NewData, | ||||
| 	"libwebp_anim": libwebp_anim.NewData, | ||||
| 	"libwebp":      libwebp.NewData, | ||||
| 	"wmv1":         wmv1.NewData, | ||||
| 	"wmv2":         wmv2.NewData, | ||||
| 	"xbm":          xbm.NewData, | ||||
| 	"mp2":          mp2.NewData, | ||||
| 	"mp2fixed":     mp2fixed.NewData, | ||||
| 	"libtwolame":   libtwolame.NewData, | ||||
| 	"libmp3lame":   libmp3lame.NewData, | ||||
| 	"libshine":     libshine.NewData, | ||||
| 	"wmav1":        wmav1.NewData, | ||||
| 	"wmav2":        wmav2.NewData, | ||||
| } | ||||
							
								
								
									
										139
									
								
								internal/application/convertor/items_to_convert.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								internal/application/convertor/items_to_convert.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,139 @@ | ||||
| package convertor | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/theme" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg" | ||||
| ) | ||||
|  | ||||
| type ItemsToConvertContract interface { | ||||
| 	Add(file *ffmpeg.File) | ||||
| 	Clear() | ||||
| 	GetItems() map[int]ItemToConvertContract | ||||
| 	GetItemsContainer() *fyne.Container | ||||
| 	AfterAddingQueue() | ||||
| 	GetIsAutoRemove() bool | ||||
| 	SetIsAutoRemove(isAutoRemove bool) | ||||
| } | ||||
|  | ||||
| type itemsToConvert struct { | ||||
| 	ffmpeg         ffmpeg.UtilitiesContract | ||||
| 	nextId         int | ||||
| 	items          map[int]ItemToConvertContract | ||||
| 	itemsContainer *fyne.Container | ||||
| 	isAutoRemove   bool | ||||
| } | ||||
|  | ||||
| func NewItemsToConvert(ffmpeg ffmpeg.UtilitiesContract) ItemsToConvertContract { | ||||
| 	return &itemsToConvert{ | ||||
| 		ffmpeg:         ffmpeg, | ||||
| 		nextId:         0, | ||||
| 		items:          map[int]ItemToConvertContract{}, | ||||
| 		itemsContainer: container.NewVBox(), | ||||
| 		isAutoRemove:   true, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (items *itemsToConvert) GetItemsContainer() *fyne.Container { | ||||
| 	return items.itemsContainer | ||||
| } | ||||
|  | ||||
| func (items *itemsToConvert) Add(file *ffmpeg.File) { | ||||
| 	nextId := items.nextId | ||||
| 	var content *fyne.Container | ||||
| 	var buttonPlay *widget.Button | ||||
|  | ||||
| 	buttonPlay = widget.NewButtonWithIcon("", theme.Icon(theme.IconNameMediaPlay), func() { | ||||
| 		buttonPlay.Disable() | ||||
| 		go func() { | ||||
| 			ffplay, err := items.ffmpeg.GetFFplay() | ||||
| 			if err != nil { | ||||
| 				fyne.Do(func() { | ||||
| 					buttonPlay.Enable() | ||||
| 				}) | ||||
| 				return | ||||
| 			} | ||||
|  | ||||
| 			_ = ffplay.Play(file) | ||||
| 			fyne.Do(func() { | ||||
| 				buttonPlay.Enable() | ||||
| 			}) | ||||
| 		}() | ||||
| 	}) | ||||
|  | ||||
| 	buttonRemove := widget.NewButtonWithIcon("", theme.Icon(theme.IconNameDelete), func() { | ||||
| 		items.itemsContainer.Remove(content) | ||||
| 		items.itemsContainer.Refresh() | ||||
| 		delete(items.items, nextId) | ||||
| 	}) | ||||
| 	buttonRemove.Importance = widget.DangerImportance | ||||
|  | ||||
| 	content = container.NewVBox( | ||||
| 		container.NewBorder( | ||||
| 			nil, | ||||
| 			nil, | ||||
| 			buttonPlay, | ||||
| 			buttonRemove, | ||||
| 			container.NewHScroll(widget.NewLabel(file.Name)), | ||||
| 		), | ||||
| 		container.NewHScroll(widget.NewLabel(file.Path)), | ||||
| 		container.NewPadded(), | ||||
| 		canvas.NewLine(theme.Color(theme.ColorNameFocus)), | ||||
| 		container.NewPadded(), | ||||
| 	) | ||||
|  | ||||
| 	items.itemsContainer.Add(content) | ||||
| 	items.items[nextId] = newItemToConvert(file, content) | ||||
| 	items.nextId++ | ||||
| } | ||||
|  | ||||
| func (items *itemsToConvert) GetIsAutoRemove() bool { | ||||
| 	return items.isAutoRemove | ||||
| } | ||||
|  | ||||
| func (items *itemsToConvert) SetIsAutoRemove(isAutoRemove bool) { | ||||
| 	items.isAutoRemove = isAutoRemove | ||||
| } | ||||
|  | ||||
| func (items *itemsToConvert) GetItems() map[int]ItemToConvertContract { | ||||
| 	return items.items | ||||
| } | ||||
|  | ||||
| func (items *itemsToConvert) AfterAddingQueue() { | ||||
| 	if items.isAutoRemove { | ||||
| 		items.Clear() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (items *itemsToConvert) Clear() { | ||||
| 	items.itemsContainer.RemoveAll() | ||||
| 	items.items = map[int]ItemToConvertContract{} | ||||
| } | ||||
|  | ||||
| type ItemToConvertContract interface { | ||||
| 	GetFile() *ffmpeg.File | ||||
| 	GetContent() *fyne.Container | ||||
| } | ||||
|  | ||||
| type itemToConvert struct { | ||||
| 	file    *ffmpeg.File | ||||
| 	content *fyne.Container | ||||
| } | ||||
|  | ||||
| func newItemToConvert(file *ffmpeg.File, content *fyne.Container) ItemToConvertContract { | ||||
| 	return &itemToConvert{ | ||||
| 		file:    file, | ||||
| 		content: content, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (item *itemToConvert) GetFile() *ffmpeg.File { | ||||
| 	return item.file | ||||
| } | ||||
|  | ||||
| func (item *itemToConvert) GetContent() *fyne.Container { | ||||
| 	return item.content | ||||
| } | ||||
							
								
								
									
										217
									
								
								internal/application/convertor/progressbar.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								internal/application/convertor/progressbar.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,217 @@ | ||||
| package convertor | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"errors" | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/theme" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg" | ||||
| 	"image/color" | ||||
| 	"io" | ||||
| 	"regexp" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type ProgressBarContract interface { | ||||
| 	GetContainer() *fyne.Container | ||||
| 	GetProgressbar(totalDuration float64, filePath string) ffmpeg.ProgressContract | ||||
| 	ProcessEndedWithError(errorText string) | ||||
| 	ProcessEndedWithSuccess(file *ffmpeg.File) | ||||
| } | ||||
|  | ||||
| type progressBar struct { | ||||
| 	container     *fyne.Container | ||||
| 	label         *widget.Label | ||||
| 	progressbar   *widget.ProgressBar | ||||
| 	errorBlock    *container.Scroll | ||||
| 	messageError  *canvas.Text | ||||
| 	statusMessage *canvas.Text | ||||
| 	buttonPlay    *widget.Button | ||||
| 	ffmpegService ffmpeg.UtilitiesContract | ||||
| } | ||||
|  | ||||
| func NewProgressBar(ffmpegService ffmpeg.UtilitiesContract) ProgressBarContract { | ||||
| 	label := widget.NewLabel("") | ||||
| 	progressbar := widget.NewProgressBar() | ||||
|  | ||||
| 	statusMessage := canvas.NewText("", theme.Color(theme.ColorNamePrimary)) | ||||
| 	messageError := canvas.NewText("", theme.Color(theme.ColorNameError)) | ||||
| 	buttonPlay := widget.NewButtonWithIcon("", theme.Icon(theme.IconNameMediaPlay), func() { | ||||
|  | ||||
| 	}) | ||||
| 	buttonPlay.Hide() | ||||
|  | ||||
| 	errorBlock := container.NewHScroll(messageError) | ||||
| 	errorBlock.Hide() | ||||
|  | ||||
| 	content := container.NewVBox( | ||||
| 		container.NewHScroll(label), | ||||
| 		progressbar, | ||||
| 		container.NewHScroll(container.NewHBox( | ||||
| 			buttonPlay, | ||||
| 			statusMessage, | ||||
| 		)), | ||||
| 		errorBlock, | ||||
| 	) | ||||
| 	content.Hide() | ||||
|  | ||||
| 	return &progressBar{ | ||||
| 		container:     content, | ||||
| 		label:         label, | ||||
| 		progressbar:   progressbar, | ||||
| 		errorBlock:    errorBlock, | ||||
| 		messageError:  messageError, | ||||
| 		statusMessage: statusMessage, | ||||
| 		buttonPlay:    buttonPlay, | ||||
| 		ffmpegService: ffmpegService, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (p *progressBar) GetContainer() *fyne.Container { | ||||
| 	return p.container | ||||
| } | ||||
|  | ||||
| func (p *progressBar) GetProgressbar(totalDuration float64, filePath string) ffmpeg.ProgressContract { | ||||
| 	p.label.Text = filePath | ||||
| 	p.statusMessage.Color = theme.Color(theme.ColorNamePrimary) | ||||
| 	p.statusMessage.Text = lang.L("inProgressQueue") | ||||
| 	p.messageError.Text = "" | ||||
| 	fyne.Do(func() { | ||||
| 		p.buttonPlay.Hide() | ||||
| 		if p.errorBlock.Visible() { | ||||
| 			p.errorBlock.Hide() | ||||
| 		} | ||||
| 		p.statusMessage.Refresh() | ||||
| 		p.container.Refresh() | ||||
| 		p.errorBlock.Refresh() | ||||
| 	}) | ||||
|  | ||||
| 	p.progressbar.Value = 0 | ||||
| 	return NewProgress(totalDuration, p.progressbar) | ||||
| } | ||||
|  | ||||
| func (p *progressBar) ProcessEndedWithError(errorText string) { | ||||
| 	fyne.Do(func() { | ||||
| 		p.statusMessage.Color = theme.Color(theme.ColorNameError) | ||||
| 		p.statusMessage.Text = lang.L("errorQueue") | ||||
| 		p.messageError.Text = errorText | ||||
| 		p.errorBlock.Show() | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (p *progressBar) ProcessEndedWithSuccess(file *ffmpeg.File) { | ||||
| 	fyne.Do(func() { | ||||
| 		p.statusMessage.Color = color.RGBA{R: 49, G: 127, B: 114, A: 255} | ||||
| 		p.statusMessage.Text = lang.L("completedQueue") | ||||
| 		p.buttonPlay.Show() | ||||
| 		p.buttonPlay.OnTapped = func() { | ||||
| 			p.buttonPlay.Disable() | ||||
| 			go func() { | ||||
| 				ffplay, err := p.ffmpegService.GetFFplay() | ||||
| 				if err == nil { | ||||
| 					_ = ffplay.Play(file) | ||||
| 				} | ||||
|  | ||||
| 				fyne.Do(func() { | ||||
| 					p.buttonPlay.Enable() | ||||
| 				}) | ||||
| 			}() | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| type Progress struct { | ||||
| 	totalDuration float64 | ||||
| 	progressbar   *widget.ProgressBar | ||||
| 	protocol      string | ||||
| } | ||||
|  | ||||
| func NewProgress(totalDuration float64, progressbar *widget.ProgressBar) ffmpeg.ProgressContract { | ||||
| 	return &Progress{ | ||||
| 		totalDuration: totalDuration, | ||||
| 		progressbar:   progressbar, | ||||
| 		protocol:      "pipe:", | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (p *Progress) GetProtocole() string { | ||||
| 	return p.protocol | ||||
| } | ||||
|  | ||||
| func (p *Progress) Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error { | ||||
| 	isProcessCompleted := false | ||||
| 	var errorText string | ||||
|  | ||||
| 	p.progressbar.Value = 0 | ||||
| 	p.progressbar.Max = p.totalDuration | ||||
| 	fyne.Do(func() { | ||||
| 		p.progressbar.Refresh() | ||||
| 	}) | ||||
| 	progress := 0.0 | ||||
|  | ||||
| 	go func() { | ||||
| 		scannerErr := bufio.NewReader(stdErr) | ||||
| 		for { | ||||
| 			line, _, err := scannerErr.ReadLine() | ||||
| 			if err != nil { | ||||
| 				if err == io.EOF { | ||||
| 					break | ||||
| 				} | ||||
| 				continue | ||||
| 			} | ||||
| 			data := strings.TrimSpace(string(line)) | ||||
| 			errorText = data | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	scannerOut := bufio.NewReader(stdOut) | ||||
| 	for { | ||||
| 		line, _, err := scannerOut.ReadLine() | ||||
| 		if err != nil { | ||||
| 			if err == io.EOF { | ||||
| 				break | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 		data := strings.TrimSpace(string(line)) | ||||
| 		if strings.Contains(data, "progress=end") { | ||||
| 			p.progressbar.Value = p.totalDuration | ||||
| 			fyne.Do(func() { | ||||
| 				p.progressbar.Refresh() | ||||
| 			}) | ||||
| 			isProcessCompleted = true | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		re := regexp.MustCompile(`frame=(\d+)`) | ||||
| 		a := re.FindAllStringSubmatch(data, -1) | ||||
|  | ||||
| 		if len(a) > 0 && len(a[len(a)-1]) > 0 { | ||||
| 			c, err := strconv.Atoi(a[len(a)-1][len(a[len(a)-1])-1]) | ||||
| 			if err != nil { | ||||
| 				continue | ||||
| 			} | ||||
| 			progress = float64(c) | ||||
| 		} | ||||
| 		if p.progressbar.Value != progress { | ||||
| 			p.progressbar.Value = progress | ||||
| 			fyne.Do(func() { | ||||
| 				p.progressbar.Refresh() | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if isProcessCompleted == false { | ||||
| 		if len(errorText) == 0 { | ||||
| 			errorText = lang.L("errorConverter") | ||||
| 		} | ||||
| 		return errors.New(errorText) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										152
									
								
								internal/application/convertor/queue.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								internal/application/convertor/queue.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,152 @@ | ||||
| package convertor | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg" | ||||
| ) | ||||
|  | ||||
| type Queue struct { | ||||
| 	Setting *ffmpeg.ConvertSetting | ||||
| 	Status  StatusContract | ||||
| 	Error   error | ||||
| } | ||||
|  | ||||
| type StatusContract interface { | ||||
| 	Name() string | ||||
| 	Ordinal() int | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	Waiting = iota | ||||
| 	InProgress | ||||
| 	Completed | ||||
| 	Error | ||||
| ) | ||||
|  | ||||
| type StatusType uint | ||||
|  | ||||
| var statusTypeStrings = []string{ | ||||
| 	"waiting", | ||||
| 	"inProgress", | ||||
| 	"completed", | ||||
| 	"error", | ||||
| } | ||||
|  | ||||
| func (status StatusType) Name() string { | ||||
| 	return statusTypeStrings[status] | ||||
| } | ||||
|  | ||||
| func (status StatusType) Ordinal() int { | ||||
| 	return int(status) | ||||
| } | ||||
|  | ||||
| type QueueListenerContract interface { | ||||
| 	AddQueue(key int, queue *Queue) | ||||
| 	ChangeQueue(key int, queue *Queue) | ||||
| 	RemoveQueue(key int, status StatusContract) | ||||
| } | ||||
|  | ||||
| type QueueListContract interface { | ||||
| 	AddListener(queueListener QueueListenerContract) | ||||
| 	GetItems() map[int]*Queue | ||||
| 	Add(setting *ffmpeg.ConvertSetting) | ||||
| 	EventChangeQueue(key int, queue *Queue) | ||||
| 	Remove(key int) | ||||
| 	GetItem(key int) (*Queue, error) | ||||
| 	Next() (key int, queue *Queue) | ||||
| } | ||||
|  | ||||
| type queueList struct { | ||||
| 	currentKey    int | ||||
| 	items         map[int]*Queue | ||||
| 	queue         map[int]int | ||||
| 	queueListener map[int]QueueListenerContract | ||||
| } | ||||
|  | ||||
| func NewQueueList() QueueListContract { | ||||
| 	return &queueList{ | ||||
| 		currentKey:    0, | ||||
| 		items:         map[int]*Queue{}, | ||||
| 		queue:         map[int]int{}, | ||||
| 		queueListener: map[int]QueueListenerContract{}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (l *queueList) GetItems() map[int]*Queue { | ||||
| 	return l.items | ||||
| } | ||||
|  | ||||
| func (l *queueList) Add(setting *ffmpeg.ConvertSetting) { | ||||
| 	queue := Queue{ | ||||
| 		Setting: setting, | ||||
| 		Status:  StatusType(Waiting), | ||||
| 	} | ||||
|  | ||||
| 	l.currentKey += 1 | ||||
| 	l.items[l.currentKey] = &queue | ||||
| 	l.queue[l.currentKey] = l.currentKey | ||||
|  | ||||
| 	l.eventAdd(l.currentKey, &queue) | ||||
| } | ||||
|  | ||||
| func (l *queueList) EventChangeQueue(key int, queue *Queue) { | ||||
| 	l.eventChange(key, queue) | ||||
| } | ||||
|  | ||||
| func (l *queueList) Remove(key int) { | ||||
| 	if _, ok := l.queue[key]; ok { | ||||
| 		delete(l.queue, key) | ||||
| 	} | ||||
|  | ||||
| 	if _, ok := l.items[key]; ok { | ||||
| 		status := l.items[key].Status | ||||
| 		l.eventRemove(key, status) | ||||
| 		delete(l.items, key) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (l *queueList) GetItem(key int) (*Queue, error) { | ||||
| 	if item, ok := l.items[key]; ok { | ||||
| 		return item, nil | ||||
| 	} | ||||
|  | ||||
| 	return nil, errors.New("key not found") | ||||
| } | ||||
|  | ||||
| func (l *queueList) AddListener(queueListener QueueListenerContract) { | ||||
| 	l.queueListener[len(l.queueListener)] = queueListener | ||||
| } | ||||
|  | ||||
| func (l *queueList) Next() (key int, queue *Queue) { | ||||
| 	statusWaiting := StatusType(Waiting) | ||||
| 	for key, queueId := range l.queue { | ||||
| 		if queue, ok := l.items[queueId]; ok { | ||||
| 			if queue.Status == statusWaiting { | ||||
| 				return queueId, queue | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if _, ok := l.queue[key]; ok { | ||||
| 			delete(l.queue, key) | ||||
| 		} | ||||
| 	} | ||||
| 	return -1, nil | ||||
| } | ||||
|  | ||||
| func (l *queueList) eventAdd(key int, queue *Queue) { | ||||
| 	for _, listener := range l.queueListener { | ||||
| 		listener.AddQueue(key, queue) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (l *queueList) eventChange(key int, queue *Queue) { | ||||
| 	for _, listener := range l.queueListener { | ||||
| 		listener.ChangeQueue(key, queue) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (l *queueList) eventRemove(key int, status StatusContract) { | ||||
| 	for _, listener := range l.queueListener { | ||||
| 		listener.RemoveQueue(key, status) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										40
									
								
								internal/application/setting/ffmpeg.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								internal/application/setting/ffmpeg.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| package setting | ||||
|  | ||||
| func (s *setting) GetFFmpegPath() string { | ||||
| 	path := s.fyneApp.Preferences().String("ffmpegPath") | ||||
| 	if path == "" { | ||||
| 		return "ffmpeg" | ||||
| 	} | ||||
|  | ||||
| 	return path | ||||
| } | ||||
|  | ||||
| func (s *setting) SetFFmpegPath(path string) { | ||||
| 	s.fyneApp.Preferences().SetString("ffmpegPath", path) | ||||
| } | ||||
|  | ||||
| func (s *setting) GetFFprobePath() string { | ||||
| 	path := s.fyneApp.Preferences().String("ffprobePath") | ||||
| 	if path == "" { | ||||
| 		return "ffprobe" | ||||
| 	} | ||||
|  | ||||
| 	return path | ||||
| } | ||||
|  | ||||
| func (s *setting) SetFFprobePath(path string) { | ||||
| 	s.fyneApp.Preferences().SetString("ffprobePath", path) | ||||
| } | ||||
|  | ||||
| func (s *setting) GetFFplayPath() string { | ||||
| 	path := s.fyneApp.Preferences().String("ffplayPath") | ||||
| 	if path == "" { | ||||
| 		return "ffplay" | ||||
| 	} | ||||
|  | ||||
| 	return path | ||||
| } | ||||
|  | ||||
| func (s *setting) SetFFplayPath(path string) { | ||||
| 	s.fyneApp.Preferences().SetString("ffplayPath", path) | ||||
| } | ||||
							
								
								
									
										66
									
								
								internal/application/setting/lang.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								internal/application/setting/lang.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| package setting | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	fyneLang "fyne.io/fyne/v2/lang" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/resources" | ||||
| ) | ||||
|  | ||||
| var supportedLanguages = map[string]Lang{ | ||||
| 	"ru": {Code: "ru", Title: "Русский"}, | ||||
| 	"kk": {Code: "kk", Title: "Қазақ Тілі"}, | ||||
| 	"en": {Code: "en", Title: "English"}, | ||||
| } | ||||
|  | ||||
| type Lang struct { | ||||
| 	Code  string | ||||
| 	Title string | ||||
| } | ||||
|  | ||||
| func ChangeLang(lang Lang) error { | ||||
| 	translationsData, err := getTranslations(lang) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	name := fyneLang.SystemLocale().LanguageString() | ||||
| 	return fyneLang.AddTranslations(fyne.NewStaticResource(name+".json", translationsData)) | ||||
| } | ||||
|  | ||||
| func defaultLang() Lang { | ||||
| 	return supportedLanguages["ru"] | ||||
| } | ||||
|  | ||||
| func getTranslations(language Lang) ([]byte, error) { | ||||
| 	translations := resources.GetTranslations() | ||||
|  | ||||
| 	baseJson, err := translations.ReadFile("translations/base." + language.Code + ".json") | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	appJson, err := translations.ReadFile("translations/app." + language.Code + ".json") | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return mergeTranslations(baseJson, appJson) | ||||
| } | ||||
|  | ||||
| func mergeTranslations(baseJson []byte, appJson []byte) ([]byte, error) { | ||||
| 	base := map[string]interface{}{} | ||||
| 	custom := map[string]interface{}{} | ||||
| 	err := json.Unmarshal(baseJson, &base) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	err = json.Unmarshal(appJson, &custom) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	for k, v := range custom { | ||||
| 		base[k] = v | ||||
| 	} | ||||
| 	return json.Marshal(base) | ||||
| } | ||||
							
								
								
									
										84
									
								
								internal/application/setting/setting.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								internal/application/setting/setting.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| package setting | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"golang.org/x/text/language" | ||||
| ) | ||||
|  | ||||
| type SettingContract interface { | ||||
| 	GetLanguages() []Lang | ||||
| 	GetCurrentLangOrDefaultLang() (currentLang Lang, isDefault bool) | ||||
| 	SetLang(language Lang) error | ||||
|  | ||||
| 	GetDirectoryForSaving() string | ||||
| 	SetDirectoryForSaving(path string) | ||||
|  | ||||
| 	GetFFmpegPath() string | ||||
| 	SetFFmpegPath(path string) | ||||
|  | ||||
| 	GetFFprobePath() string | ||||
| 	SetFFprobePath(path string) | ||||
|  | ||||
| 	GetFFplayPath() string | ||||
| 	SetFFplayPath(path string) | ||||
|  | ||||
| 	ThemeInit() | ||||
| 	GetThemes() map[string]ThemeInfoContract | ||||
| 	GetTheme() ThemeInfoContract | ||||
| 	SetTheme(themeInfo ThemeInfoContract) | ||||
| } | ||||
|  | ||||
| type setting struct { | ||||
| 	fyneApp fyne.App | ||||
| } | ||||
|  | ||||
| func NewSetting(fyneApp fyne.App) SettingContract { | ||||
| 	return &setting{ | ||||
| 		fyneApp: fyneApp, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (s *setting) GetLanguages() []Lang { | ||||
| 	items := []Lang{} | ||||
| 	for _, item := range supportedLanguages { | ||||
| 		items = append(items, item) | ||||
| 	} | ||||
| 	return items | ||||
| } | ||||
|  | ||||
| func (s *setting) GetCurrentLangOrDefaultLang() (currentLang Lang, isDefault bool) { | ||||
| 	languageCode := s.fyneApp.Preferences().String("language") | ||||
|  | ||||
| 	if languageCode == "" { | ||||
| 		languageTag, err := language.Parse(lang.SystemLocale().LanguageString()) | ||||
| 		if err != nil { | ||||
| 			return currentLang, true | ||||
| 		} | ||||
| 		base, _ := languageTag.Base() | ||||
| 		languageCode = base.String() | ||||
| 	} | ||||
|  | ||||
| 	if currentLang, ok := supportedLanguages[languageCode]; ok { | ||||
| 		return currentLang, false | ||||
| 	} | ||||
|  | ||||
| 	return defaultLang(), true | ||||
| } | ||||
|  | ||||
| func (s *setting) SetLang(language Lang) error { | ||||
| 	err := ChangeLang(language) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	s.fyneApp.Preferences().SetString("language", language.Code) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (s *setting) GetDirectoryForSaving() string { | ||||
| 	return s.fyneApp.Preferences().String("directoryForSaving") | ||||
| } | ||||
|  | ||||
| func (s *setting) SetDirectoryForSaving(path string) { | ||||
| 	s.fyneApp.Preferences().SetString("directoryForSaving", path) | ||||
| } | ||||
							
								
								
									
										112
									
								
								internal/application/setting/theme.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								internal/application/setting/theme.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| package setting | ||||
|  | ||||
| import ( | ||||
| 	"image/color" | ||||
|  | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/theme" | ||||
| ) | ||||
|  | ||||
| func (s *setting) GetTheme() ThemeInfoContract { | ||||
| 	name := s.fyneApp.Preferences().String("theme") | ||||
| 	if name != "" { | ||||
| 		if _, ok := s.GetThemes()[name]; ok { | ||||
| 			return s.GetThemes()[name] | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return s.GetThemes()["default"] | ||||
| } | ||||
|  | ||||
| func (s *setting) SetTheme(themeInfo ThemeInfoContract) { | ||||
| 	s.fyneApp.Preferences().SetString("theme", themeInfo.GetName()) | ||||
|  | ||||
| 	if themeInfo.GetName() == "default" { | ||||
| 		s.fyneApp.Settings().SetTheme(theme.DefaultTheme()) | ||||
| 		return | ||||
| 	} | ||||
| 	s.fyneApp.Settings().SetTheme(&forcedVariant{theme: theme.DefaultTheme(), variant: themeInfo.GetVariant()}) | ||||
| } | ||||
|  | ||||
| func (s *setting) ThemeInit() { | ||||
| 	themeInfo := s.GetTheme() | ||||
| 	if themeInfo.GetName() == "default" { | ||||
| 		// In the new version of Fyne the theme color changes incorrectly if it is set to default. | ||||
| 		// s.fyneApp.Settings().SetTheme(theme.DefaultTheme()) | ||||
| 		return | ||||
| 	} | ||||
| 	s.fyneApp.Settings().SetTheme(&forcedVariant{theme: theme.DefaultTheme(), variant: themeInfo.GetVariant()}) | ||||
| } | ||||
|  | ||||
| func (s *setting) GetThemes() map[string]ThemeInfoContract { | ||||
| 	themesNameDefault := &themeInfo{ | ||||
| 		name:  "default", | ||||
| 		title: lang.L("themesNameDefault"), | ||||
| 	} | ||||
|  | ||||
| 	themesNameLight := &themeInfo{ | ||||
| 		name:    "light", | ||||
| 		title:   lang.L("themesNameLight"), | ||||
| 		variant: theme.VariantLight, | ||||
| 	} | ||||
|  | ||||
| 	themesNameDark := &themeInfo{ | ||||
| 		name:    "dark", | ||||
| 		title:   lang.L("themesNameDark"), | ||||
| 		variant: theme.VariantDark, | ||||
| 	} | ||||
|  | ||||
| 	list := map[string]ThemeInfoContract{ | ||||
| 		"default": themesNameDefault, | ||||
| 		"light":   themesNameLight, | ||||
| 		"dark":    themesNameDark, | ||||
| 	} | ||||
|  | ||||
| 	return list | ||||
| } | ||||
|  | ||||
| type ThemeInfoContract interface { | ||||
| 	GetName() string | ||||
| 	GetTitle() string | ||||
| 	GetVariant() fyne.ThemeVariant | ||||
| } | ||||
|  | ||||
| type themeInfo struct { | ||||
| 	name    string | ||||
| 	title   string | ||||
| 	variant fyne.ThemeVariant | ||||
| } | ||||
|  | ||||
| func (inf *themeInfo) GetName() string { | ||||
| 	return inf.name | ||||
| } | ||||
|  | ||||
| func (inf *themeInfo) GetTitle() string { | ||||
| 	return inf.title | ||||
| } | ||||
|  | ||||
| func (inf *themeInfo) GetVariant() fyne.ThemeVariant { | ||||
| 	return inf.variant | ||||
| } | ||||
|  | ||||
| type forcedVariant struct { | ||||
| 	theme   fyne.Theme | ||||
| 	variant fyne.ThemeVariant | ||||
| } | ||||
|  | ||||
| func (f *forcedVariant) Color(name fyne.ThemeColorName, _ fyne.ThemeVariant) color.Color { | ||||
| 	return f.theme.Color(name, f.variant) | ||||
| } | ||||
|  | ||||
| func (f *forcedVariant) Font(style fyne.TextStyle) fyne.Resource { | ||||
| 	return theme.DefaultTheme().Font(style) | ||||
| } | ||||
|  | ||||
| func (f *forcedVariant) Icon(name fyne.ThemeIconName) fyne.Resource { | ||||
| 	return theme.DefaultTheme().Icon(name) | ||||
| } | ||||
|  | ||||
| func (f *forcedVariant) Size(name fyne.ThemeSizeName) float32 { | ||||
| 	return theme.DefaultTheme().Size(name) | ||||
| } | ||||
							
								
								
									
										111
									
								
								internal/controller/convertor.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								internal/controller/convertor.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| package controller | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/download/service" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/view" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/utils" | ||||
| ) | ||||
|  | ||||
| func (c *controller) convertor() { | ||||
| 	formats, err := c.app.GetConvertorService().GetSupportFormats() | ||||
| 	if err != nil { | ||||
| 		c.startWithError(err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	content := view.Convertor( | ||||
| 		c.window, | ||||
| 		c.addFileForConversion, | ||||
| 		c.app.GetSetting().GetDirectoryForSaving(), | ||||
| 		c.setDirectoryForSaving, | ||||
| 		formats, | ||||
| 		c.addToConversion, | ||||
| 	) | ||||
| 	c.window.SetContent(content) | ||||
| } | ||||
|  | ||||
| func (c *controller) addFileForConversion(file ffmpeg.File) { | ||||
| 	c.app.GetItemsToConvert().Add(&file) | ||||
| 	c.window.GetLayout().GetRContainer().SelectAddedFilesTab() | ||||
| } | ||||
|  | ||||
| func (c *controller) setDirectoryForSaving(path string) { | ||||
| 	c.app.GetSetting().SetDirectoryForSaving(path) | ||||
| } | ||||
|  | ||||
| func (c *controller) addToConversion(convertSetting view.ConvertSetting) error { | ||||
| 	if len(c.app.GetItemsToConvert().GetItems()) == 0 { | ||||
| 		return errors.New(lang.L("errorNoFilesAddedForConversion")) | ||||
| 	} | ||||
| 	c.window.GetLayout().GetRContainer().SelectFileQueueTab() | ||||
| 	for _, item := range c.app.GetItemsToConvert().GetItems() { | ||||
| 		file := item.GetFile() | ||||
| 		if file == nil { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		c.app.GetQueueService().Add(&ffmpeg.ConvertSetting{ | ||||
| 			FileInput: *file, | ||||
| 			FileOut: ffmpeg.File{ | ||||
| 				Path: convertSetting.DirectoryForSave + utils.PathSeparator() + file.Name + "." + convertSetting.Format, | ||||
| 				Name: file.Name, | ||||
| 				Ext:  "." + convertSetting.Format, | ||||
| 			}, | ||||
| 			OverwriteOutputFiles: convertSetting.OverwriteOutputFiles, | ||||
| 			Encoder:              convertSetting.Encoder, | ||||
| 		}) | ||||
| 	} | ||||
| 	c.app.GetItemsToConvert().AfterAddingQueue() | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (c *controller) settingConvertor(isAllowCancellation bool) { | ||||
| 	ffmpegPath := c.app.GetFFmpegService().GetFFmpegPath() | ||||
| 	ffprobePath := c.app.GetFFmpegService().GetFFprobePath() | ||||
| 	ffplayPath := c.app.GetFFmpegService().GetFFplayPath() | ||||
|  | ||||
| 	var cancel func() | ||||
| 	cancel = nil | ||||
| 	if isAllowCancellation { | ||||
| 		cancel = func() { | ||||
| 			c.convertor() | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	content := view.ConfiguringFFmpegUtilities( | ||||
| 		c.window, | ||||
| 		ffmpegPath, | ||||
| 		ffprobePath, | ||||
| 		ffplayPath, | ||||
| 		c.saveSettingConvertor, | ||||
| 		cancel, | ||||
| 		service.DownloadFFmpeg(c.app, c.saveSettingConvertor), | ||||
| 	) | ||||
| 	c.window.SetContent(content) | ||||
| } | ||||
|  | ||||
| func (c *controller) saveSettingConvertor(ffmpegPath string, ffprobePath string, ffplayPath string) error { | ||||
| 	var err error | ||||
|  | ||||
| 	err = c.app.GetFFmpegService().ChangeFFmpeg(ffmpegPath) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	c.app.GetFFmpegService().ChangeFFprobe(ffprobePath) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	c.app.GetFFmpegService().ChangeFFplay(ffplayPath) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	c.convertor() | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										16
									
								
								internal/controller/error.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								internal/controller/error.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| package controller | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/setting" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/view" | ||||
| ) | ||||
|  | ||||
| func (c *controller) startWithError(err error) { | ||||
| 	languages := c.app.GetSetting().GetLanguages() | ||||
|  | ||||
| 	content := view.StartWithError(err, languages, func(lang setting.Lang) { | ||||
| 		_ = setting.ChangeLang(lang) | ||||
| 		c.startWithError(err) | ||||
| 	}) | ||||
| 	c.window.SetContent(content) | ||||
| } | ||||
							
								
								
									
										96
									
								
								internal/controller/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								internal/controller/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| package controller | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/setting" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/menu" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/view" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/window" | ||||
| ) | ||||
|  | ||||
| type ControllerContract interface { | ||||
| 	Start() | ||||
| } | ||||
|  | ||||
| type controller struct { | ||||
| 	app    application.AppContract | ||||
| 	window window.WindowContract | ||||
| } | ||||
|  | ||||
| func NewController(app application.AppContract) ControllerContract { | ||||
| 	fyneWindow := app.FyneApp().NewWindow("GUI for FFmpeg") | ||||
| 	fyneWindow.SetMaster() | ||||
| 	queueLayout := window.NewQueueLayout(app.GetFFmpegService()) | ||||
| 	app.GetQueueService().AddListener(queueLayout) | ||||
|  | ||||
| 	return &controller{ | ||||
| 		app: app, | ||||
| 		window: window.NewMainWindow( | ||||
| 			fyneWindow, | ||||
| 			app.GetProgressBarService(), | ||||
| 			app.GetItemsToConvert(), | ||||
| 			queueLayout, | ||||
| 		), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *controller) Start() { | ||||
| 	isDefault, err := c.initLanguage() | ||||
| 	if err != nil { | ||||
| 		c.startWithError(err) | ||||
| 		c.window.Show() | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	c.app.GetSetting().ThemeInit() | ||||
|  | ||||
| 	if isDefault { | ||||
| 		languages := c.app.GetSetting().GetLanguages() | ||||
| 		content := view.StartWithoutSupportLang(languages, func(lang setting.Lang) { | ||||
| 			err = c.app.GetSetting().SetLang(lang) | ||||
| 			if err != nil { | ||||
| 				c.startWithError(err) | ||||
| 				return | ||||
| 			} | ||||
| 			c.initLayout() | ||||
| 			c.verificareaFFmpeg() | ||||
| 		}) | ||||
| 		c.window.SetContent(content) | ||||
| 		c.window.Show() | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	c.initLayout() | ||||
| 	c.verificareaFFmpeg() | ||||
| 	c.window.Show() | ||||
| } | ||||
|  | ||||
| func (c *controller) verificareaFFmpeg() { | ||||
| 	if !c.app.GetFFmpegService().UtilityCheck() { | ||||
| 		c.settingConvertor(false) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	c.convertor() | ||||
| } | ||||
|  | ||||
| func (c *controller) initLanguage() (isDefault bool, err error) { | ||||
| 	lang, isDefault := c.app.GetSetting().GetCurrentLangOrDefaultLang() | ||||
| 	err = setting.ChangeLang(lang) | ||||
| 	return isDefault, err | ||||
| } | ||||
|  | ||||
| func (c *controller) initLayout() { | ||||
| 	c.window.SetMainMenu(fyne.NewMainMenu( | ||||
| 		menu.MainMenuSettings( | ||||
| 			c.actionMainSettings, | ||||
| 			c.actionSettingConvertor, | ||||
| 		), | ||||
| 		menu.MainMenuHelp( | ||||
| 			c.actionAbout, | ||||
| 			c.actionHelpFFplay, | ||||
| 		), | ||||
| 	)) | ||||
| 	c.window.InitLayout() | ||||
| } | ||||
							
								
								
									
										67
									
								
								internal/controller/menu.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								internal/controller/menu.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| package controller | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/view" | ||||
| ) | ||||
|  | ||||
| func (c *controller) actionSettingConvertor() { | ||||
| 	c.settingConvertor(true) | ||||
| } | ||||
|  | ||||
| func (c *controller) actionMainSettings() { | ||||
| 	currentLang, _ := c.app.GetSetting().GetCurrentLangOrDefaultLang() | ||||
| 	content := view.MainSettings( | ||||
| 		currentLang, | ||||
| 		c.app.GetSetting().GetLanguages(), | ||||
|  | ||||
| 		c.app.GetSetting().GetTheme(), | ||||
| 		c.app.GetSetting().GetThemes(), | ||||
|  | ||||
| 		c.actionMainSettingsSave, | ||||
| 		c.convertor, | ||||
| 	) | ||||
| 	c.window.SetContent(content) | ||||
| } | ||||
|  | ||||
| func (c *controller) actionMainSettingsSave(setting *view.MainSettingForm) error { | ||||
| 	err := c.app.GetSetting().SetLang(setting.Language) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	c.app.GetSetting().SetTheme(setting.ThemeInfo) | ||||
| 	c.initLayout() | ||||
|  | ||||
| 	c.convertor() | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (c *controller) actionAbout() { | ||||
| 	ffmpegVersion := c.app.GetFFmpegService().GetFFmpegVersion() | ||||
| 	ffprobeVersion := c.app.GetFFmpegService().GetFFprobeVersion() | ||||
| 	ffplayVersion := c.app.GetFFmpegService().GetFFplayVersion() | ||||
| 	appVersion := c.app.FyneApp().Metadata().Version | ||||
|  | ||||
| 	window := c.app.FyneApp().NewWindow(lang.L("about")) | ||||
| 	window.Resize(fyne.Size{Width: 793, Height: 550}) | ||||
| 	window.SetFixedSize(true) | ||||
|  | ||||
| 	content := view.About(appVersion, ffmpegVersion, ffprobeVersion, ffplayVersion) | ||||
|  | ||||
| 	window.SetContent(content) | ||||
| 	window.CenterOnScreen() | ||||
| 	window.Show() | ||||
| } | ||||
|  | ||||
| func (c *controller) actionHelpFFplay() { | ||||
| 	window := c.app.FyneApp().NewWindow(lang.L("helpFFplay")) | ||||
| 	window.Resize(fyne.Size{Width: 800, Height: 550}) | ||||
| 	window.SetFixedSize(true) | ||||
|  | ||||
| 	content := view.HelpFFplay() | ||||
|  | ||||
| 	window.SetContent(content) | ||||
| 	window.CenterOnScreen() | ||||
| 	window.Show() | ||||
| } | ||||
							
								
								
									
										14
									
								
								internal/ffmpeg/download/gui/download_anyos.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								internal/ffmpeg/download/gui/download_anyos.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| //go:build !windows && !linux | ||||
| // +build !windows,!linux | ||||
|  | ||||
| package gui | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| ) | ||||
|  | ||||
| func DownloadFFmpeg(donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error) fyne.CanvasObject { | ||||
| 	return container.NewVBox() | ||||
| } | ||||
							
								
								
									
										59
									
								
								internal/ffmpeg/download/gui/download_linux.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								internal/ffmpeg/download/gui/download_linux.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| //go:build linux | ||||
| // +build linux | ||||
|  | ||||
| package gui | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"golang.org/x/image/colornames" | ||||
| 	"image/color" | ||||
| ) | ||||
|  | ||||
| func DownloadFFmpeg(donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error) fyne.CanvasObject { | ||||
| 	errorDownloadFFmpegMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255}) | ||||
| 	errorDownloadFFmpegMessage.TextSize = 16 | ||||
| 	errorDownloadFFmpegMessage.TextStyle = fyne.TextStyle{Bold: true} | ||||
|  | ||||
| 	progressDownloadFFmpegMessage := canvas.NewText("", color.RGBA{R: 49, G: 127, B: 114, A: 255}) | ||||
| 	progressDownloadFFmpegMessage.TextSize = 16 | ||||
| 	progressDownloadFFmpegMessage.TextStyle = fyne.TextStyle{Bold: true} | ||||
|  | ||||
| 	progressBar := widget.NewProgressBar() | ||||
|  | ||||
| 	var buttonDownloadFFmpeg *widget.Button | ||||
|  | ||||
| 	buttonDownloadFFmpeg = widget.NewButton(lang.L("download"), func() { | ||||
| 		fyne.Do(func() { | ||||
| 			buttonDownloadFFmpeg.Disable() | ||||
| 		}) | ||||
| 		go func() { | ||||
| 			err := donwloadFFmpeg(progressBar, progressDownloadFFmpegMessage) | ||||
| 			if err != nil { | ||||
| 				errorDownloadFFmpegMessage.Text = err.Error() | ||||
| 			} | ||||
| 			fyne.Do(func() { | ||||
| 				buttonDownloadFFmpeg.Enable() | ||||
| 			}) | ||||
| 		}() | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	downloadFFmpegFromSiteMessage := lang.L("downloadFFmpegFromSite") | ||||
|  | ||||
| 	return container.NewVBox( | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
| 		widget.NewCard(lang.L("buttonDownloadFFmpeg"), "", container.NewVBox( | ||||
| 			widget.NewRichTextFromMarkdown( | ||||
| 				downloadFFmpegFromSiteMessage+" [https://github.com/BtbN/FFmpeg-Builds/releases](https://github.com/BtbN/FFmpeg-Builds/releases)", | ||||
| 			), | ||||
| 			buttonDownloadFFmpeg, | ||||
| 			container.NewHScroll(errorDownloadFFmpegMessage), | ||||
| 			progressDownloadFFmpegMessage, | ||||
| 			progressBar, | ||||
| 		)), | ||||
| 	) | ||||
| } | ||||
							
								
								
									
										59
									
								
								internal/ffmpeg/download/gui/download_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								internal/ffmpeg/download/gui/download_windows.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| //go:build windows | ||||
| // +build windows | ||||
|  | ||||
| package gui | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"golang.org/x/image/colornames" | ||||
| 	"image/color" | ||||
| ) | ||||
|  | ||||
| func DownloadFFmpeg(donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error) fyne.CanvasObject { | ||||
| 	errorDownloadFFmpegMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255}) | ||||
| 	errorDownloadFFmpegMessage.TextSize = 16 | ||||
| 	errorDownloadFFmpegMessage.TextStyle = fyne.TextStyle{Bold: true} | ||||
|  | ||||
| 	progressDownloadFFmpegMessage := canvas.NewText("", color.RGBA{R: 49, G: 127, B: 114, A: 255}) | ||||
| 	progressDownloadFFmpegMessage.TextSize = 16 | ||||
| 	progressDownloadFFmpegMessage.TextStyle = fyne.TextStyle{Bold: true} | ||||
|  | ||||
| 	progressBar := widget.NewProgressBar() | ||||
|  | ||||
| 	var buttonDownloadFFmpeg *widget.Button | ||||
|  | ||||
| 	buttonDownloadFFmpeg = widget.NewButton(lang.L("download"), func() { | ||||
|  | ||||
| 		go func() { | ||||
| 			fyne.Do(func() { | ||||
| 				buttonDownloadFFmpeg.Disable() | ||||
| 			}) | ||||
| 			err := donwloadFFmpeg(progressBar, progressDownloadFFmpegMessage) | ||||
| 			if err != nil { | ||||
| 				errorDownloadFFmpegMessage.Text = err.Error() | ||||
| 			} | ||||
| 			fyne.Do(func() { | ||||
| 				buttonDownloadFFmpeg.Enable() | ||||
| 			}) | ||||
| 		}() | ||||
| 	}) | ||||
|  | ||||
| 	downloadFFmpegFromSiteMessage := lang.L("downloadFFmpegFromSite") | ||||
|  | ||||
| 	return container.NewVBox( | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
| 		widget.NewCard(lang.L("buttonDownloadFFmpeg"), "", container.NewVBox( | ||||
| 			widget.NewRichTextFromMarkdown( | ||||
| 				downloadFFmpegFromSiteMessage+" [https://github.com/BtbN/FFmpeg-Builds/releases](https://github.com/BtbN/FFmpeg-Builds/releases)", | ||||
| 			), | ||||
| 			buttonDownloadFFmpeg, | ||||
| 			container.NewHScroll(errorDownloadFFmpegMessage), | ||||
| 			progressDownloadFFmpegMessage, | ||||
| 			progressBar, | ||||
| 		)), | ||||
| 	) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/download/service/download.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/download/service/download.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package service | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/download/gui" | ||||
| ) | ||||
|  | ||||
| func DownloadFFmpeg(app application.AppContract, save func(ffmpegPath string, ffprobePath string, ffplayPath string) error) fyne.CanvasObject { | ||||
| 	return gui.DownloadFFmpeg(func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error { | ||||
| 		var err error | ||||
| 		err = startDownload(app, progressBar, progressMessage, save) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		return nil | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										15
									
								
								internal/ffmpeg/download/service/download_anyos.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								internal/ffmpeg/download/service/download_anyos.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| //go:build !windows && !linux | ||||
| // +build !windows,!linux | ||||
|  | ||||
| package service | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application" | ||||
| ) | ||||
|  | ||||
| func startDownload(app application.AppContract, progressBar *widget.ProgressBar, progressMessage *canvas.Text, save func(ffmpegPath string, ffprobePath string, ffplayPath string) error) error { | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										236
									
								
								internal/ffmpeg/download/service/download_linux.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								internal/ffmpeg/download/service/download_linux.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,236 @@ | ||||
| //go:build linux | ||||
| // +build linux | ||||
|  | ||||
| package service | ||||
|  | ||||
| import ( | ||||
| 	"archive/tar" | ||||
| 	"errors" | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application" | ||||
| 	"github.com/ulikunitz/xz" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| ) | ||||
|  | ||||
| func startDownload(app application.AppContract, progressBar *widget.ProgressBar, progressMessage *canvas.Text, save func(ffmpegPath string, ffprobePath string, ffplayPath string) error) error { | ||||
| 	var err error | ||||
|  | ||||
| 	dir, err := localSharePath() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	dir = filepath.Join(dir, "fyne", app.FyneApp().UniqueID()) | ||||
| 	err = os.MkdirAll(dir, 0755) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	fyne.Do(func() { | ||||
| 		progressMessage.Text = lang.L("downloadRun") | ||||
| 		progressMessage.Refresh() | ||||
| 	}) | ||||
| 	err = downloadFile(dir+"/ffmpeg.tar.xz", "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz", progressBar) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	fyne.Do(func() { | ||||
| 		progressMessage.Text = lang.L("unzipRun") | ||||
| 		progressMessage.Refresh() | ||||
| 	}) | ||||
| 	err = unTarXz(dir+"/ffmpeg.tar.xz", dir, progressBar) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	_ = os.Remove(dir + "/ffmpeg.tar.xz") | ||||
|  | ||||
| 	fyne.Do(func() { | ||||
| 		progressMessage.Text = lang.L("testFF") | ||||
| 		progressMessage.Refresh() | ||||
| 	}) | ||||
|  | ||||
| 	err = save( | ||||
| 		dir+"/ffmpeg-master-latest-linux64-gpl/bin/ffmpeg", | ||||
| 		dir+"/ffmpeg-master-latest-linux64-gpl/bin/ffprobe", | ||||
| 		dir+"/ffmpeg-master-latest-linux64-gpl/bin/ffplay", | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	fyne.Do(func() { | ||||
| 		progressMessage.Text = lang.L("completedQueue") | ||||
| 		progressMessage.Refresh() | ||||
| 	}) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func localSharePath() (string, error) { | ||||
| 	xdgDataHome := os.Getenv("XDG_DATA_HOME") | ||||
| 	if xdgDataHome != "" { | ||||
| 		return xdgDataHome, nil | ||||
| 	} | ||||
| 	homeDir, err := os.UserHomeDir() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return filepath.Join(homeDir, ".local", "share"), nil | ||||
| } | ||||
|  | ||||
| func downloadFile(filepath string, url string, progressBar *widget.ProgressBar) (err error) { | ||||
| 	progressBar.Value = 0 | ||||
| 	progressBar.Max = 100 | ||||
|  | ||||
| 	req, err := http.NewRequest("GET", url, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	resp, err := http.DefaultClient.Do(req) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer resp.Body.Close() | ||||
|  | ||||
| 	f, err := os.OpenFile(filepath, os.O_CREATE|os.O_WRONLY, 0644) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer f.Close() | ||||
|  | ||||
| 	buf := make([]byte, 32*1024) | ||||
| 	var downloaded int64 | ||||
| 	for { | ||||
| 		n, err := resp.Body.Read(buf) | ||||
| 		if err != nil { | ||||
| 			if err == io.EOF { | ||||
| 				break | ||||
| 			} | ||||
| 			return err | ||||
| 		} | ||||
| 		if n > 0 { | ||||
| 			f.Write(buf[:n]) | ||||
| 			downloaded += int64(n) | ||||
| 			progressBar.Value = float64(downloaded) / float64(resp.ContentLength) * 100 | ||||
| 			fyne.Do(func() { | ||||
| 				progressBar.Refresh() | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func unTarXz(fileTar string, directory string, progressBar *widget.ProgressBar) error { | ||||
| 	progressBar.Value = 0 | ||||
| 	progressBar.Max = 100 | ||||
|  | ||||
| 	fyne.Do(func() { | ||||
| 		progressBar.Refresh() | ||||
| 	}) | ||||
|  | ||||
| 	f, err := os.Open(fileTar) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer f.Close() | ||||
|  | ||||
| 	xzReader, err := xz.NewReader(f) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	tarReader := tar.NewReader(xzReader) | ||||
|  | ||||
| 	totalFiles := 0 | ||||
| 	for { | ||||
| 		_, err := tarReader.Next() | ||||
| 		if err == io.EOF { | ||||
| 			break | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		totalFiles++ | ||||
| 	} | ||||
|  | ||||
| 	// Rewind back to the beginning of the file to re-process | ||||
| 	_, err = f.Seek(0, 0) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	xzReader, err = xz.NewReader(f) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	tarReader = tar.NewReader(xzReader) | ||||
|  | ||||
| 	// We count the number of files already unpacked | ||||
| 	unpackedFiles := 0 | ||||
|  | ||||
| 	for { | ||||
| 		header, err := tarReader.Next() | ||||
| 		if err == io.EOF { | ||||
| 			break | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		targetPath := filepath.Join(directory, header.Name) | ||||
| 		switch header.Typeflag { | ||||
| 		case tar.TypeDir: | ||||
| 			err := os.MkdirAll(targetPath, 0755) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		case tar.TypeReg: | ||||
| 			outFile, err := os.Create(targetPath) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			defer outFile.Close() | ||||
|  | ||||
| 			_, err = io.Copy(outFile, tarReader) | ||||
|  | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		default: | ||||
| 			return errors.New("unsupported file type") | ||||
| 		} | ||||
|  | ||||
| 		unpackedFiles++ | ||||
| 		progressBar.Value = float64(unpackedFiles) / float64(totalFiles) * 100 | ||||
| 		fyne.Do(func() { | ||||
| 			progressBar.Refresh() | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	ffmpegPath := filepath.Join(directory, "ffmpeg-master-latest-linux64-gpl", "bin", "ffmpeg") | ||||
| 	err = os.Chmod(ffmpegPath, 0755) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	ffprobePath := filepath.Join(directory, "ffmpeg-master-latest-linux64-gpl", "bin", "ffprobe") | ||||
| 	err = os.Chmod(ffprobePath, 0755) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	ffplayPath := filepath.Join(directory, "ffmpeg-master-latest-linux64-gpl", "bin", "ffplay") | ||||
| 	err = os.Chmod(ffplayPath, 0755) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										175
									
								
								internal/ffmpeg/download/service/download_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								internal/ffmpeg/download/service/download_windows.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | ||||
| //go:build windows | ||||
| // +build windows | ||||
|  | ||||
| package service | ||||
|  | ||||
| import ( | ||||
| 	"archive/zip" | ||||
| 	"errors" | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| func startDownload(app application.AppContract, progressBar *widget.ProgressBar, progressMessage *canvas.Text, save func(ffmpegPath string, ffprobePath string, ffplayPath string) error) error { | ||||
| 	var err error | ||||
|  | ||||
| 	dir := os.Getenv("APPDATA") | ||||
| 	dir = filepath.Join(dir, "fyne", app.FyneApp().UniqueID()) | ||||
| 	err = os.MkdirAll(dir, 0755) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	fyne.Do(func() { | ||||
| 		progressMessage.Text = lang.L("downloadRun") | ||||
| 		progressMessage.Refresh() | ||||
| 	}) | ||||
| 	err = downloadFile(dir+"/ffmpeg.zip", "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl.zip", progressBar) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	fyne.Do(func() { | ||||
| 		progressMessage.Text = lang.L("unzipRun") | ||||
| 		progressMessage.Refresh() | ||||
| 	}) | ||||
| 	err = unZip(dir+"/ffmpeg.zip", dir, progressBar) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	_ = os.Remove(dir + "/ffmpeg.zip") | ||||
|  | ||||
| 	fyne.Do(func() { | ||||
| 		progressMessage.Text = lang.L("testFF") | ||||
| 		progressMessage.Refresh() | ||||
| 	}) | ||||
| 	err = save( | ||||
| 		dir+"/ffmpeg-master-latest-win64-gpl/bin/ffmpeg.exe", | ||||
| 		dir+"/ffmpeg-master-latest-win64-gpl/bin/ffprobe.exe", | ||||
| 		dir+"/ffmpeg-master-latest-win64-gpl/bin/ffplay.exe", | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	fyne.Do(func() { | ||||
| 		progressMessage.Text = lang.L("completedQueue") | ||||
| 		progressMessage.Refresh() | ||||
| 	}) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func downloadFile(filepath string, url string, progressBar *widget.ProgressBar) (err error) { | ||||
| 	progressBar.Value = 0 | ||||
| 	progressBar.Max = 100 | ||||
|  | ||||
| 	req, err := http.NewRequest("GET", url, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	resp, err := http.DefaultClient.Do(req) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer resp.Body.Close() | ||||
|  | ||||
| 	f, err := os.OpenFile(filepath, os.O_CREATE|os.O_WRONLY, 0644) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer f.Close() | ||||
|  | ||||
| 	buf := make([]byte, 32*1024) | ||||
| 	var downloaded int64 | ||||
| 	for { | ||||
| 		n, err := resp.Body.Read(buf) | ||||
| 		if err != nil { | ||||
| 			if err == io.EOF { | ||||
| 				break | ||||
| 			} | ||||
| 			return err | ||||
| 		} | ||||
| 		if n > 0 { | ||||
| 			f.Write(buf[:n]) | ||||
| 			downloaded += int64(n) | ||||
| 			progressBar.Value = float64(downloaded) / float64(resp.ContentLength) * 100 | ||||
| 			fyne.Do(func() { | ||||
| 				progressBar.Refresh() | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func unZip(fileZip string, directory string, progressBar *widget.ProgressBar) error { | ||||
| 	progressBar.Value = 0 | ||||
| 	progressBar.Max = 100 | ||||
|  | ||||
| 	fyne.Do(func() { | ||||
| 		progressBar.Refresh() | ||||
| 	}) | ||||
|  | ||||
| 	archive, err := zip.OpenReader(fileZip) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer archive.Close() | ||||
|  | ||||
| 	totalBytes := int64(0) | ||||
| 	for _, f := range archive.File { | ||||
| 		totalBytes += int64(f.UncompressedSize64) | ||||
| 	} | ||||
|  | ||||
| 	unpackedBytes := int64(0) | ||||
|  | ||||
| 	for _, f := range archive.File { | ||||
| 		filePath := filepath.Join(directory, f.Name) | ||||
|  | ||||
| 		if !strings.HasPrefix(filePath, filepath.Clean(directory)+string(os.PathSeparator)) { | ||||
| 			return errors.New("invalid file path") | ||||
| 		} | ||||
| 		if f.FileInfo().IsDir() { | ||||
| 			os.MkdirAll(filePath, os.ModePerm) | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		fileInArchive, err := f.Open() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		bytesRead, err := io.Copy(dstFile, fileInArchive) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		unpackedBytes += bytesRead | ||||
| 		progressBar.Value = float64(unpackedBytes) / float64(totalBytes) * 100 | ||||
| 		fyne.Do(func() { | ||||
| 			progressBar.Refresh() | ||||
| 		}) | ||||
|  | ||||
| 		dstFile.Close() | ||||
| 		fileInArchive.Close() | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/apng/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/apng/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package apng | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "apng"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("apng", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "apng" | ||||
| 	formats := []string{"apng"} | ||||
| 	fileType := encoder.FileType(encoder.Image) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/bmp/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/bmp/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package bmp | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "bmp"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("bmp", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "bmp" | ||||
| 	formats := []string{"bmp"} | ||||
| 	fileType := encoder.FileType(encoder.Image) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										169
									
								
								internal/ffmpeg/encoder/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								internal/ffmpeg/encoder/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,169 @@ | ||||
| package encoder | ||||
|  | ||||
| import "errors" | ||||
|  | ||||
| type EncoderContract interface { | ||||
| 	GetName() string | ||||
| 	GetParams() []string | ||||
| 	GetParameter(name string) (ParameterContract, error) | ||||
| } | ||||
|  | ||||
| type ParameterContract interface { | ||||
| 	GetName() string | ||||
| 	Set(string) error | ||||
| 	Get() string | ||||
| 	IsEnabled() bool | ||||
| 	SetEnable() | ||||
| 	SetDisable() | ||||
| } | ||||
|  | ||||
| type EncoderDataContract interface { | ||||
| 	GetTitle() string | ||||
| 	GetFormats() []string | ||||
| 	GetFileType() FileTypeContract | ||||
| 	NewEncoder() EncoderContract | ||||
| } | ||||
|  | ||||
| type data struct { | ||||
| 	title    string | ||||
| 	formats  []string | ||||
| 	fileType FileTypeContract | ||||
| 	encoder  func() EncoderContract | ||||
| } | ||||
|  | ||||
| func NewData(title string, formats []string, fileType FileTypeContract, encoder func() EncoderContract) EncoderDataContract { | ||||
| 	return &data{ | ||||
| 		title:    title, | ||||
| 		formats:  formats, | ||||
| 		fileType: fileType, | ||||
| 		encoder:  encoder, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (data *data) GetTitle() string { | ||||
| 	return data.title | ||||
| } | ||||
|  | ||||
| func (data *data) GetFormats() []string { | ||||
| 	return data.formats | ||||
| } | ||||
|  | ||||
| func (data *data) NewEncoder() EncoderContract { | ||||
| 	return data.encoder() | ||||
| } | ||||
|  | ||||
| func (data *data) GetFileType() FileTypeContract { | ||||
| 	return data.fileType | ||||
| } | ||||
|  | ||||
| type FileTypeContract interface { | ||||
| 	Name() string | ||||
| 	Ordinal() int | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	Video = iota | ||||
| 	Audio | ||||
| 	Image | ||||
| ) | ||||
|  | ||||
| type FileType uint | ||||
|  | ||||
| var fileTypeStrings = []string{ | ||||
| 	"video", | ||||
| 	"audio", | ||||
| 	"image", | ||||
| } | ||||
|  | ||||
| func (fileType FileType) Name() string { | ||||
| 	return fileTypeStrings[fileType] | ||||
| } | ||||
|  | ||||
| func (fileType FileType) Ordinal() int { | ||||
| 	return int(fileType) | ||||
| } | ||||
|  | ||||
| func GetListFileType() []FileTypeContract { | ||||
| 	return []FileTypeContract{ | ||||
| 		FileType(Video), | ||||
| 		FileType(Audio), | ||||
| 		FileType(Image), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type encoder struct { | ||||
| 	name       string | ||||
| 	parameters map[string]ParameterContract | ||||
| 	getParams  func(parameters map[string]ParameterContract) []string | ||||
| } | ||||
|  | ||||
| func NewEncoder(name string, parameters map[string]ParameterContract, getParams func(parameters map[string]ParameterContract) []string) EncoderContract { | ||||
| 	return &encoder{ | ||||
| 		name:       name, | ||||
| 		parameters: parameters, | ||||
| 		getParams:  getParams, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (e *encoder) GetName() string { | ||||
| 	return e.name | ||||
| } | ||||
|  | ||||
| func (e *encoder) GetParams() []string { | ||||
| 	return e.getParams(e.parameters) | ||||
| } | ||||
|  | ||||
| func (e *encoder) GetParameter(name string) (ParameterContract, error) { | ||||
| 	if e.parameters[name] == nil { | ||||
| 		return nil, errors.New("parameter not found") | ||||
| 	} | ||||
|  | ||||
| 	return e.parameters[name], nil | ||||
| } | ||||
|  | ||||
| type parameter struct { | ||||
| 	name         string | ||||
| 	isEnabled    bool | ||||
| 	parameter    string | ||||
| 	setParameter func(string) (string, error) | ||||
| } | ||||
|  | ||||
| func NewParameter(name string, isEnabled bool, defaultParameter string, setParameter func(string) (string, error)) ParameterContract { | ||||
| 	return ¶meter{ | ||||
| 		name:         name, | ||||
| 		isEnabled:    isEnabled, | ||||
| 		parameter:    defaultParameter, | ||||
| 		setParameter: setParameter, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (p *parameter) GetName() string { | ||||
| 	return p.name | ||||
| } | ||||
|  | ||||
| func (p *parameter) Set(s string) (err error) { | ||||
| 	if p.setParameter != nil { | ||||
| 		s, err = p.setParameter(s) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	p.parameter = s | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *parameter) Get() string { | ||||
| 	return p.parameter | ||||
| } | ||||
|  | ||||
| func (p *parameter) IsEnabled() bool { | ||||
| 	return p.isEnabled | ||||
| } | ||||
|  | ||||
| func (p *parameter) SetEnable() { | ||||
| 	p.isEnabled = true | ||||
| } | ||||
|  | ||||
| func (p *parameter) SetDisable() { | ||||
| 	p.isEnabled = false | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/flv/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/flv/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package flv | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "flv"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("flv", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "flv" | ||||
| 	formats := []string{"flv"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/gif/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/gif/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package gif | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "gif"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("gif", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "gif" | ||||
| 	formats := []string{"gif"} | ||||
| 	fileType := encoder.FileType(encoder.Image) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										58
									
								
								internal/ffmpeg/encoder/h264_nvenc/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								internal/ffmpeg/encoder/h264_nvenc/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| package h264_nvenc | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| var Presets = []string{ | ||||
| 	"default", | ||||
| 	"slow", | ||||
| 	"medium", | ||||
| 	"fast", | ||||
| 	"hp", | ||||
| 	"hq", | ||||
| 	"bd", | ||||
| 	"ll", | ||||
| 	"llhq", | ||||
| 	"llhp", | ||||
| 	"lossless", | ||||
| 	"losslesshp", | ||||
| } | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{ | ||||
| 		"preset": newParameterPreset(), | ||||
| 	} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		params := []string{"-c:v", "h264_nvenc"} | ||||
|  | ||||
| 		if parameters["preset"] != nil && parameters["preset"].IsEnabled() { | ||||
| 			params = append(params, "-preset", parameters["preset"].Get()) | ||||
| 		} | ||||
|  | ||||
| 		return params | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("h264_nvenc", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "h264_nvenc" | ||||
| 	formats := []string{"mp4"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
|  | ||||
| func newParameterPreset() encoder.ParameterContract { | ||||
| 	setParameter := func(s string) (string, error) { | ||||
| 		for _, value := range Presets { | ||||
| 			if value == s { | ||||
| 				return value, nil | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return "", errors.New("preset not found") | ||||
| 	} | ||||
| 	return encoder.NewParameter("preset", false, "default", setParameter) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/libmp3lame/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/libmp3lame/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package libmp3lame | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:a", "libmp3lame"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("libmp3lame", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "libmp3lame" | ||||
| 	formats := []string{"mp3"} | ||||
| 	fileType := encoder.FileType(encoder.Audio) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/libshine/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/libshine/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package libshine | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:a", "libshine"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("libshine", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "libshine" | ||||
| 	formats := []string{"mp3"} | ||||
| 	fileType := encoder.FileType(encoder.Audio) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/libtwolame/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/libtwolame/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package libtwolame | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:a", "libtwolame"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("libtwolame", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "libtwolame" | ||||
| 	formats := []string{"mp2"} | ||||
| 	fileType := encoder.FileType(encoder.Audio) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/libvpx/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/libvpx/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package libvpx | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "libvpx"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("libvpx", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "libvpx" | ||||
| 	formats := []string{"webm", "mkv"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/libvpx_vp9/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/libvpx_vp9/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package libvpx_vp9 | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "libvpx-vp9"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("libvpx_vp9", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "libvpx-vp9" | ||||
| 	formats := []string{"webm", "mkv"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/libwebp/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/libwebp/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package libwebp | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "libwebp"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("libwebp", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "libwebp" | ||||
| 	formats := []string{"webp"} | ||||
| 	fileType := encoder.FileType(encoder.Image) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/libwebp_anim/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/libwebp_anim/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package libwebp_anim | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "libwebp_anim"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("libwebp_anim", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "libwebp_anim" | ||||
| 	formats := []string{"webp"} | ||||
| 	fileType := encoder.FileType(encoder.Image) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										56
									
								
								internal/ffmpeg/encoder/libx264/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								internal/ffmpeg/encoder/libx264/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| package libx264 | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| var Presets = []string{ | ||||
| 	"ultrafast", | ||||
| 	"superfast", | ||||
| 	"veryfast", | ||||
| 	"faster", | ||||
| 	"fast", | ||||
| 	"medium", | ||||
| 	"slow", | ||||
| 	"slower", | ||||
| 	"veryslow", | ||||
| 	"placebo", | ||||
| } | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{ | ||||
| 		"preset": newParameterPreset(), | ||||
| 	} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		params := []string{"-c:v", "libx264"} | ||||
|  | ||||
| 		if parameters["preset"] != nil && parameters["preset"].IsEnabled() { | ||||
| 			params = append(params, "-preset", parameters["preset"].Get()) | ||||
| 		} | ||||
|  | ||||
| 		return params | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("libx264", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "libx264" | ||||
| 	formats := []string{"mp4"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
|  | ||||
| func newParameterPreset() encoder.ParameterContract { | ||||
| 	setParameter := func(s string) (string, error) { | ||||
| 		for _, value := range Presets { | ||||
| 			if value == s { | ||||
| 				return value, nil | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return "", errors.New("preset not found") | ||||
| 	} | ||||
| 	return encoder.NewParameter("preset", false, "medium", setParameter) | ||||
| } | ||||
							
								
								
									
										56
									
								
								internal/ffmpeg/encoder/libx265/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								internal/ffmpeg/encoder/libx265/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| package libx265 | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| var Presets = []string{ | ||||
| 	"ultrafast", | ||||
| 	"superfast", | ||||
| 	"veryfast", | ||||
| 	"faster", | ||||
| 	"fast", | ||||
| 	"medium", | ||||
| 	"slow", | ||||
| 	"slower", | ||||
| 	"veryslow", | ||||
| 	"placebo", | ||||
| } | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{ | ||||
| 		"preset": newParameterPreset(), | ||||
| 	} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		params := []string{"-c:v", "libx265"} | ||||
|  | ||||
| 		if parameters["preset"] != nil && parameters["preset"].IsEnabled() { | ||||
| 			params = append(params, "-preset", parameters["preset"].Get()) | ||||
| 		} | ||||
|  | ||||
| 		return params | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("libx265", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "libx265" | ||||
| 	formats := []string{"mp4"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
|  | ||||
| func newParameterPreset() encoder.ParameterContract { | ||||
| 	setParameter := func(s string) (string, error) { | ||||
| 		for _, value := range Presets { | ||||
| 			if value == s { | ||||
| 				return value, nil | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return "", errors.New("preset not found") | ||||
| 	} | ||||
| 	return encoder.NewParameter("preset", false, "medium", setParameter) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/libxvid/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/libxvid/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package libxvid | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "libxvid"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("libxvid", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "libxvid" | ||||
| 	formats := []string{"avi"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/mjpeg/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/mjpeg/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package mjpeg | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "mjpeg"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("mjpeg", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "mjpeg" | ||||
| 	formats := []string{"jpg"} | ||||
| 	fileType := encoder.FileType(encoder.Image) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/mp2/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/mp2/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package mp2 | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:a", "mp2"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("mp2", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "mp2" | ||||
| 	formats := []string{"mp2"} | ||||
| 	fileType := encoder.FileType(encoder.Audio) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/mp2fixed/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/mp2fixed/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package mp2fixed | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:a", "mp2fixed"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("mp2fixed", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "mp2fixed" | ||||
| 	formats := []string{"mp2"} | ||||
| 	fileType := encoder.FileType(encoder.Audio) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/mpeg1video/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/mpeg1video/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package mpeg1video | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "mpeg1video"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("mpeg1video", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "mpeg1video" | ||||
| 	formats := []string{"mpg", "mpeg"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/mpeg2video/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/mpeg2video/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package mpeg2video | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "mpeg2video"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("mpeg2video", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "mpeg2video" | ||||
| 	formats := []string{"mpg", "mpeg"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/mpeg4/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/mpeg4/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package mpeg4 | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "mpeg4"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("mpeg4", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "mpeg4" | ||||
| 	formats := []string{"avi"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/msmpeg4/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/msmpeg4/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package msmpeg4 | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "msmpeg4"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("msmpeg4", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "msmpeg4" | ||||
| 	formats := []string{"avi"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/msmpeg4v2/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/msmpeg4v2/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package msmpeg4v2 | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "msmpeg4v2"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("msmpeg4v2", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "msmpeg4v2" | ||||
| 	formats := []string{"avi"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/msvideo1/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/msvideo1/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package msvideo1 | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "msvideo1"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("msvideo1", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "msvideo1" | ||||
| 	formats := []string{"avi"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/png/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/png/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package png | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "png"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("png", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "png" | ||||
| 	formats := []string{"png"} | ||||
| 	fileType := encoder.FileType(encoder.Image) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/qtrle/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/qtrle/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package qtrle | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "qtrle"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("qtrle", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "qtrle" | ||||
| 	formats := []string{"mov"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/sgi/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/sgi/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package sgi | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "sgi"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("sgi", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "sgi" | ||||
| 	formats := []string{"sgi"} | ||||
| 	fileType := encoder.FileType(encoder.Image) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/tiff/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/tiff/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package tiff | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "tiff"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("tiff", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "tiff" | ||||
| 	formats := []string{"tiff"} | ||||
| 	fileType := encoder.FileType(encoder.Image) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/wmav1/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/wmav1/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package wmav1 | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:a", "wmav1"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("wmav1", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "wmav1" | ||||
| 	formats := []string{"wma"} | ||||
| 	fileType := encoder.FileType(encoder.Audio) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/wmav2/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/wmav2/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package wmav2 | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:a", "wmav2"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("wmav2", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "wmav2" | ||||
| 	formats := []string{"wma"} | ||||
| 	fileType := encoder.FileType(encoder.Audio) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/wmv1/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/wmv1/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package wmv1 | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "wmv1"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("wmv1", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "wmv1" | ||||
| 	formats := []string{"wmv"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/wmv2/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/wmv2/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package wmv2 | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "wmv2"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("wmv2", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "wmv2" | ||||
| 	formats := []string{"wmv"} | ||||
| 	fileType := encoder.FileType(encoder.Video) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										21
									
								
								internal/ffmpeg/encoder/xbm/encoder.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/ffmpeg/encoder/xbm/encoder.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package xbm | ||||
|  | ||||
| import ( | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| func NewEncoder() encoder.EncoderContract { | ||||
| 	parameters := map[string]encoder.ParameterContract{} | ||||
| 	getParams := func(parameters map[string]encoder.ParameterContract) []string { | ||||
| 		return []string{"-c:v", "xbm"} | ||||
| 	} | ||||
|  | ||||
| 	return encoder.NewEncoder("xbm", parameters, getParams) | ||||
| } | ||||
|  | ||||
| func NewData() encoder.EncoderDataContract { | ||||
| 	title := "xbm" | ||||
| 	formats := []string{"xbm"} | ||||
| 	fileType := encoder.FileType(encoder.Image) | ||||
| 	return encoder.NewData(title, formats, fileType, NewEncoder) | ||||
| } | ||||
							
								
								
									
										139
									
								
								internal/ffmpeg/ffmpeg.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								internal/ffmpeg/ffmpeg.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,139 @@ | ||||
| package ffmpeg | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"errors" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/utils" | ||||
| 	"io" | ||||
| 	"os/exec" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type ProgressContract interface { | ||||
| 	GetProtocole() string | ||||
| 	Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error | ||||
| } | ||||
|  | ||||
| type FFmpegContract interface { | ||||
| 	GetPath() string | ||||
| 	GetVersion() (string, error) | ||||
| 	GetEncoders(scanner func(scanner *bufio.Reader)) error | ||||
| 	RunConvert(setting ConvertSetting, progress ProgressContract, beforeWait func(cmd *exec.Cmd), afterWait func(cmd *exec.Cmd)) error | ||||
| } | ||||
|  | ||||
| type ffmpeg struct { | ||||
| 	path string | ||||
| } | ||||
|  | ||||
| func newFFmpeg(path string) (FFmpegContract, error) { | ||||
| 	if path == "" { | ||||
| 		return nil, errors.New(lang.L("errorFFmpeg")) | ||||
| 	} | ||||
|  | ||||
| 	isCheck, err := checkFFmpegPath(path) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if isCheck == false { | ||||
| 		return nil, errors.New(lang.L("errorFFmpeg")) | ||||
| 	} | ||||
|  | ||||
| 	return &ffmpeg{ | ||||
| 		path: path, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func (f *ffmpeg) GetPath() string { | ||||
| 	return f.path | ||||
| } | ||||
|  | ||||
| func (f *ffmpeg) GetVersion() (string, error) { | ||||
| 	cmd := exec.Command(f.path, "-version") | ||||
| 	utils.PrepareBackgroundCommand(cmd) | ||||
| 	out, err := cmd.CombinedOutput() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	text := regexp.MustCompile("\r?\n").Split(strings.TrimSpace(string(out)), -1) | ||||
| 	return text[0], nil | ||||
| } | ||||
|  | ||||
| func (f *ffmpeg) RunConvert(setting ConvertSetting, progress ProgressContract, beforeWait func(cmd *exec.Cmd), afterWait func(cmd *exec.Cmd)) error { | ||||
| 	overwriteOutputFiles := "-n" | ||||
| 	if setting.OverwriteOutputFiles == true { | ||||
| 		overwriteOutputFiles = "-y" | ||||
| 	} | ||||
| 	args := []string{overwriteOutputFiles, "-i", setting.FileInput.Path} | ||||
| 	args = append(args, setting.Encoder.GetParams()...) | ||||
| 	args = append(args, "-progress", progress.GetProtocole(), setting.FileOut.Path) | ||||
| 	cmd := exec.Command(f.path, args...) | ||||
| 	utils.PrepareBackgroundCommand(cmd) | ||||
|  | ||||
| 	stdOut, err := cmd.StdoutPipe() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	stdErr, err := cmd.StderrPipe() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	err = cmd.Start() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if beforeWait != nil { | ||||
| 		beforeWait(cmd) | ||||
| 	} | ||||
|  | ||||
| 	errProgress := progress.Run(stdOut, stdErr) | ||||
|  | ||||
| 	err = cmd.Wait() | ||||
| 	if afterWait != nil { | ||||
| 		afterWait(cmd) | ||||
| 	} | ||||
| 	if errProgress != nil { | ||||
| 		return errProgress | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (f *ffmpeg) GetEncoders(scanner func(scanner *bufio.Reader)) error { | ||||
| 	cmd := exec.Command(f.path, "-encoders") | ||||
| 	utils.PrepareBackgroundCommand(cmd) | ||||
|  | ||||
| 	stdOut, err := cmd.StdoutPipe() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	err = cmd.Start() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	scannerErr := bufio.NewReader(stdOut) | ||||
| 	scanner(scannerErr) | ||||
|  | ||||
| 	return cmd.Wait() | ||||
| } | ||||
|  | ||||
| func checkFFmpegPath(path string) (bool, error) { | ||||
| 	cmd := exec.Command(path, "-version") | ||||
| 	utils.PrepareBackgroundCommand(cmd) | ||||
| 	out, err := cmd.CombinedOutput() | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 	if strings.Contains(strings.TrimSpace(string(out)), "ffmpeg") == false { | ||||
| 		return false, nil | ||||
| 	} | ||||
| 	return true, nil | ||||
| } | ||||
							
								
								
									
										73
									
								
								internal/ffmpeg/ffplay.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								internal/ffmpeg/ffplay.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| package ffmpeg | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/utils" | ||||
| 	"os/exec" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type FFplayContract interface { | ||||
| 	GetPath() string | ||||
| 	GetVersion() (string, error) | ||||
| 	Play(file *File) error | ||||
| } | ||||
|  | ||||
| type ffplay struct { | ||||
| 	path string | ||||
| } | ||||
|  | ||||
| func newFFplay(path string) (FFplayContract, error) { | ||||
| 	if path == "" { | ||||
| 		return nil, errors.New(lang.L("errorFFplay")) | ||||
| 	} | ||||
|  | ||||
| 	isCheck, err := checkFFplayPath(path) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if isCheck == false { | ||||
| 		return nil, errors.New(lang.L("errorFFplay")) | ||||
| 	} | ||||
|  | ||||
| 	return &ffplay{ | ||||
| 		path: path, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func (f *ffplay) GetPath() string { | ||||
| 	return f.path | ||||
| } | ||||
|  | ||||
| func (f *ffplay) GetVersion() (string, error) { | ||||
| 	cmd := exec.Command(f.path, "-version") | ||||
| 	utils.PrepareBackgroundCommand(cmd) | ||||
| 	out, err := cmd.CombinedOutput() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	text := regexp.MustCompile("\r?\n").Split(strings.TrimSpace(string(out)), -1) | ||||
| 	return text[0], nil | ||||
| } | ||||
|  | ||||
| func (f *ffplay) Play(file *File) error { | ||||
| 	args := []string{file.Path} | ||||
| 	cmd := exec.Command(f.GetPath(), args...) | ||||
|  | ||||
| 	return cmd.Run() | ||||
| } | ||||
|  | ||||
| func checkFFplayPath(path string) (bool, error) { | ||||
| 	cmd := exec.Command(path, "-version") | ||||
| 	utils.PrepareBackgroundCommand(cmd) | ||||
| 	out, err := cmd.CombinedOutput() | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 	if strings.Contains(strings.TrimSpace(string(out)), "ffplay") == false { | ||||
| 		return false, nil | ||||
| 	} | ||||
| 	return true, nil | ||||
| } | ||||
							
								
								
									
										124
									
								
								internal/ffmpeg/ffprobe.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								internal/ffmpeg/ffprobe.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | ||||
| package ffmpeg | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/utils" | ||||
| 	"os/exec" | ||||
| 	"regexp" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"unicode" | ||||
| ) | ||||
|  | ||||
| type FFprobeContract interface { | ||||
| 	GetPath() string | ||||
| 	GetVersion() (string, error) | ||||
| 	GetTotalDuration(file *File) (float64, error) | ||||
| } | ||||
|  | ||||
| type ffprobe struct { | ||||
| 	path string | ||||
| } | ||||
|  | ||||
| func newFFprobe(path string) (FFprobeContract, error) { | ||||
| 	if path == "" { | ||||
| 		return nil, errors.New(lang.L("errorFFprobe")) | ||||
| 	} | ||||
|  | ||||
| 	isCheck, err := checkFFprobePath(path) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if isCheck == false { | ||||
| 		return nil, errors.New(lang.L("errorFFprobe")) | ||||
| 	} | ||||
|  | ||||
| 	return &ffprobe{ | ||||
| 		path: path, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func (f *ffprobe) GetPath() string { | ||||
| 	return f.path | ||||
| } | ||||
|  | ||||
| func (f *ffprobe) GetVersion() (string, error) { | ||||
| 	cmd := exec.Command(f.path, "-version") | ||||
| 	utils.PrepareBackgroundCommand(cmd) | ||||
| 	out, err := cmd.CombinedOutput() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	text := regexp.MustCompile("\r?\n").Split(strings.TrimSpace(string(out)), -1) | ||||
| 	return text[0], nil | ||||
| } | ||||
|  | ||||
| func (f *ffprobe) GetTotalDuration(file *File) (duration float64, err error) { | ||||
| 	args := []string{"-v", "error", "-select_streams", "v:0", "-count_packets", "-show_entries", "stream=nb_read_packets", "-of", "csv=p=0", file.Path} | ||||
| 	cmd := exec.Command(f.path, args...) | ||||
| 	utils.PrepareBackgroundCommand(cmd) | ||||
| 	out, err := cmd.CombinedOutput() | ||||
| 	if err != nil { | ||||
| 		errString := strings.TrimSpace(string(out)) | ||||
| 		if len(errString) > 1 { | ||||
| 			return 0, errors.New(errString) | ||||
| 		} | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	frames := strings.TrimSpace(string(out)) | ||||
| 	if len(frames) == 0 { | ||||
| 		return f.getAlternativeTotalDuration(file) | ||||
| 	} | ||||
|  | ||||
| 	duration, err = strconv.ParseFloat(frames, 64) | ||||
| 	if err != nil { | ||||
| 		// fix .mts duration | ||||
| 		return strconv.ParseFloat(getFirstDigits(frames), 64) | ||||
| 	} | ||||
| 	return duration, err | ||||
| } | ||||
|  | ||||
| func (f *ffprobe) getAlternativeTotalDuration(file *File) (duration float64, err error) { | ||||
| 	args := []string{"-v", "error", "-select_streams", "a:0", "-count_packets", "-show_entries", "stream=nb_read_packets", "-of", "csv=p=0", file.Path} | ||||
| 	cmd := exec.Command(f.path, args...) | ||||
| 	utils.PrepareBackgroundCommand(cmd) | ||||
| 	out, err := cmd.CombinedOutput() | ||||
| 	if err != nil { | ||||
| 		errString := strings.TrimSpace(string(out)) | ||||
| 		if len(errString) > 1 { | ||||
| 			return 0, errors.New(errString) | ||||
| 		} | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	frames := strings.TrimSpace(string(out)) | ||||
| 	if len(frames) == 0 { | ||||
| 		return 0, errors.New("error getting number of frames") | ||||
| 	} | ||||
| 	return strconv.ParseFloat(frames, 64) | ||||
| } | ||||
|  | ||||
| func checkFFprobePath(path string) (bool, error) { | ||||
| 	cmd := exec.Command(path, "-version") | ||||
| 	utils.PrepareBackgroundCommand(cmd) | ||||
| 	out, err := cmd.CombinedOutput() | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 	if strings.Contains(strings.TrimSpace(string(out)), "ffprobe") == false { | ||||
| 		return false, nil | ||||
| 	} | ||||
| 	return true, nil | ||||
| } | ||||
|  | ||||
| func getFirstDigits(s string) string { | ||||
| 	result := "" | ||||
| 	for _, r := range s { | ||||
| 		if unicode.IsDigit(r) { | ||||
| 			result += string(r) | ||||
| 		} else { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
							
								
								
									
										221
									
								
								internal/ffmpeg/utilities.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								internal/ffmpeg/utilities.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,221 @@ | ||||
| package ffmpeg | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/setting" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| ) | ||||
|  | ||||
| type File struct { | ||||
| 	Path string | ||||
| 	Name string | ||||
| 	Ext  string | ||||
| } | ||||
|  | ||||
| type ConvertSetting struct { | ||||
| 	FileInput            File | ||||
| 	FileOut              File | ||||
| 	OverwriteOutputFiles bool | ||||
| 	Encoder              encoder.EncoderContract | ||||
| } | ||||
|  | ||||
| type UtilitiesContract interface { | ||||
| 	UtilityCheck() bool | ||||
|  | ||||
| 	GetFFmpeg() (FFmpegContract, error) | ||||
| 	GetFFmpegVersion() string | ||||
| 	GetFFmpegPath() string | ||||
| 	ChangeFFmpeg(path string) error | ||||
|  | ||||
| 	GetFFprobe() (FFprobeContract, error) | ||||
| 	GetFFprobeVersion() string | ||||
| 	GetFFprobePath() string | ||||
| 	ChangeFFprobe(path string) error | ||||
|  | ||||
| 	GetFFplay() (FFplayContract, error) | ||||
| 	GetFFplayVersion() string | ||||
| 	GetFFplayPath() string | ||||
| 	ChangeFFplay(path string) error | ||||
| } | ||||
|  | ||||
| type utilities struct { | ||||
| 	setting setting.SettingContract | ||||
| 	ffmpeg  FFmpegContract | ||||
| 	ffprobe FFprobeContract | ||||
| 	ffplay  FFplayContract | ||||
| } | ||||
|  | ||||
| func NewUtilities(setting setting.SettingContract) UtilitiesContract { | ||||
| 	return &utilities{ | ||||
| 		setting: setting, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (u *utilities) UtilityCheck() bool { | ||||
| 	var err error | ||||
|  | ||||
| 	_, err = u.GetFFmpeg() | ||||
| 	if err != nil { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	_, err = u.GetFFprobe() | ||||
| 	if err != nil { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	_, err = u.GetFFplay() | ||||
| 	if err != nil { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (u *utilities) GetFFmpeg() (FFmpegContract, error) { | ||||
| 	if u.ffmpeg == nil { | ||||
| 		createFFmpeg, err := newFFmpeg(u.setting.GetFFmpegPath()) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		u.ffmpeg = createFFmpeg | ||||
| 	} | ||||
|  | ||||
| 	return u.ffmpeg, nil | ||||
| } | ||||
|  | ||||
| func (u *utilities) GetFFmpegVersion() string { | ||||
| 	ffmpegService, err := u.GetFFmpeg() | ||||
| 	if err != nil { | ||||
| 		return lang.L("errorFFmpegVersion") | ||||
| 	} | ||||
|  | ||||
| 	version, err := ffmpegService.GetVersion() | ||||
| 	if err != nil { | ||||
| 		return lang.L("errorFFmpegVersion") | ||||
| 	} | ||||
| 	return version | ||||
| } | ||||
|  | ||||
| func (u *utilities) GetFFmpegPath() string { | ||||
| 	ffmpegService, err := u.GetFFmpeg() | ||||
| 	if err != nil { | ||||
| 		return "" | ||||
| 	} | ||||
| 	return ffmpegService.GetPath() | ||||
| } | ||||
|  | ||||
| func (u *utilities) ChangeFFmpeg(path string) error { | ||||
| 	if path == "" { | ||||
| 		return errors.New(lang.L("errorFFmpeg")) | ||||
| 	} | ||||
|  | ||||
| 	createFFmpeg, err := newFFmpeg(path) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	u.ffmpeg = createFFmpeg | ||||
| 	u.setting.SetFFmpegPath(path) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (u *utilities) GetFFprobe() (FFprobeContract, error) { | ||||
| 	if u.ffprobe == nil { | ||||
| 		createFFprobe, err := newFFprobe(u.setting.GetFFprobePath()) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		u.ffprobe = createFFprobe | ||||
| 	} | ||||
|  | ||||
| 	return u.ffprobe, nil | ||||
| } | ||||
|  | ||||
| func (u *utilities) GetFFprobeVersion() string { | ||||
| 	ffprobeService, err := u.GetFFprobe() | ||||
| 	if err != nil { | ||||
| 		return lang.L("errorFFprobeVersion") | ||||
| 	} | ||||
|  | ||||
| 	ffprobeVersion, err := ffprobeService.GetVersion() | ||||
| 	if err != nil { | ||||
| 		return lang.L("errorFFprobeVersion") | ||||
| 	} | ||||
| 	return ffprobeVersion | ||||
| } | ||||
|  | ||||
| func (u *utilities) GetFFprobePath() string { | ||||
| 	ffprobeService, err := u.GetFFprobe() | ||||
| 	if err != nil { | ||||
| 		return "" | ||||
| 	} | ||||
| 	return ffprobeService.GetPath() | ||||
| } | ||||
|  | ||||
| func (u *utilities) ChangeFFprobe(path string) error { | ||||
| 	if path == "" { | ||||
| 		return errors.New(lang.L("errorFFprobe")) | ||||
| 	} | ||||
|  | ||||
| 	createFFprobe, err := newFFprobe(path) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	u.ffprobe = createFFprobe | ||||
| 	u.setting.SetFFprobePath(path) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (u *utilities) GetFFplay() (FFplayContract, error) { | ||||
| 	if u.ffplay == nil { | ||||
| 		createFFplay, err := newFFplay(u.setting.GetFFplayPath()) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		u.ffplay = createFFplay | ||||
| 	} | ||||
|  | ||||
| 	return u.ffplay, nil | ||||
| } | ||||
|  | ||||
| func (u *utilities) GetFFplayVersion() string { | ||||
| 	ffplayService, err := u.GetFFplay() | ||||
| 	if err != nil { | ||||
| 		return lang.L("errorFFplayVersion") | ||||
| 	} | ||||
|  | ||||
| 	ffplayVersion, err := ffplayService.GetVersion() | ||||
| 	if err != nil { | ||||
| 		return lang.L("errorFFplayVersion") | ||||
| 	} | ||||
| 	return ffplayVersion | ||||
| } | ||||
|  | ||||
| func (u *utilities) GetFFplayPath() string { | ||||
| 	ffplayService, err := u.GetFFplay() | ||||
| 	if err != nil { | ||||
| 		return "" | ||||
| 	} | ||||
| 	return ffplayService.GetPath() | ||||
| } | ||||
|  | ||||
| func (u *utilities) ChangeFFplay(path string) error { | ||||
| 	if path == "" { | ||||
| 		return errors.New(lang.L("errorFFplay")) | ||||
| 	} | ||||
|  | ||||
| 	createFFplay, err := newFFplay(path) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	u.ffplay = createFFplay | ||||
| 	u.setting.SetFFplayPath(path) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										29
									
								
								internal/gui/menu/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								internal/gui/menu/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| package menu | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| ) | ||||
|  | ||||
| func MainMenuSettings( | ||||
| 	actionMainSettings func(), | ||||
| 	actionFFPathSelection func(), | ||||
| ) *fyne.Menu { | ||||
| 	quit := fyne.NewMenuItem(lang.L("exit"), nil) | ||||
| 	quit.IsQuit = true | ||||
|  | ||||
| 	settingsSelection := fyne.NewMenuItem(lang.L("settings"), actionMainSettings) | ||||
| 	ffPathSelection := fyne.NewMenuItem(lang.L("changeFFPath"), actionFFPathSelection) | ||||
|  | ||||
| 	return fyne.NewMenu(lang.L("settings"), settingsSelection, ffPathSelection, quit) | ||||
| } | ||||
|  | ||||
| func MainMenuHelp( | ||||
| 	actionAbout func(), | ||||
| 	actionHelpFFplay func(), | ||||
| ) *fyne.Menu { | ||||
| 	about := fyne.NewMenuItem(lang.L("about"), actionAbout) | ||||
| 	helpFFplay := fyne.NewMenuItem(lang.L("helpFFplay"), actionHelpFFplay) | ||||
|  | ||||
| 	return fyne.NewMenu(lang.L("help"), helpFFplay, about) | ||||
| } | ||||
							
								
								
									
										607
									
								
								internal/gui/view/about.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										607
									
								
								internal/gui/view/about.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,607 @@ | ||||
| package view | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/resources" | ||||
| 	"golang.org/x/image/colornames" | ||||
| 	"net/url" | ||||
| ) | ||||
|  | ||||
| func About(appVersion string, ffmpegVersion string, ffprobeVersion string, ffplayVersion string) fyne.CanvasObject { | ||||
| 	programmName := canvas.NewText(" GUI for FFmpeg", colornames.Darkgreen) | ||||
| 	programmName.TextStyle = fyne.TextStyle{Bold: true} | ||||
| 	programmName.TextSize = 20 | ||||
|  | ||||
| 	programmLink := widget.NewHyperlink( | ||||
| 		lang.L("programmLink"), | ||||
| 		&url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "gui-for-ffmpeg.projects.kor-elf.net", | ||||
| 			Path:   "/", | ||||
| 		}, | ||||
| 	) | ||||
|  | ||||
| 	licenseLink := widget.NewHyperlink( | ||||
| 		lang.L("licenseLink"), | ||||
| 		&url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "git.kor-elf.net", | ||||
| 			Path:   "kor-elf/gui-for-ffmpeg/src/branch/main/LICENSE", | ||||
| 		}, | ||||
| 	) | ||||
|  | ||||
| 	licenseLinkOther := widget.NewHyperlink( | ||||
| 		lang.L("licenseLinkOther"), | ||||
| 		&url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "git.kor-elf.net", | ||||
| 			Path:   "kor-elf/gui-for-ffmpeg/src/branch/main/LICENSE-3RD-PARTY.txt", | ||||
| 		}, | ||||
| 	) | ||||
|  | ||||
| 	programmVersion := widget.NewRichTextFromMarkdown( | ||||
| 		lang.L( | ||||
| 			"programmVersion", | ||||
| 			map[string]any{"Version": appVersion}, | ||||
| 		), | ||||
| 	) | ||||
|  | ||||
| 	aboutText := widget.NewRichText( | ||||
| 		&widget.TextSegment{ | ||||
| 			Text: lang.L("aboutText"), | ||||
| 		}, | ||||
| 	) | ||||
| 	image := canvas.NewImageFromResource(resources.IconAppLogoResource()) | ||||
| 	image.SetMinSize(fyne.Size{Width: 100, Height: 100}) | ||||
| 	image.FillMode = canvas.ImageFillContain | ||||
|  | ||||
| 	ffmpegTrademark := widget.NewRichTextFromMarkdown(lang.L("ffmpegTrademark")) | ||||
| 	ffmpegLGPL := widget.NewRichTextFromMarkdown(lang.L("ffmpegLGPL")) | ||||
|  | ||||
| 	return container.NewScroll(container.NewVBox( | ||||
| 		container.NewBorder(nil, nil, container.NewVBox(image), nil, container.NewVBox( | ||||
| 			programmName, | ||||
| 			programmVersion, | ||||
| 			aboutText, | ||||
| 			ffmpegTrademark, | ||||
| 			ffmpegLGPL, | ||||
| 			widget.NewRichTextFromMarkdown("Copyright (c) 2024 **[Leonid Nikitin (kor-elf)](https://git.kor-elf.net/kor-elf/)**."), | ||||
| 			container.NewHBox(programmLink, licenseLink), | ||||
| 			container.NewHBox(licenseLinkOther), | ||||
| 		)), | ||||
| 		aboutFFmpeg(ffmpegVersion), | ||||
| 		aboutFFprobe(ffprobeVersion), | ||||
| 		aboutFFplay(ffplayVersion), | ||||
| 		widget.NewCard(lang.L("AlsoUsedProgram"), "", license3RDParty()), | ||||
| 	)) | ||||
| } | ||||
|  | ||||
| func aboutFFmpeg(version string) *fyne.Container { | ||||
| 	programmName := canvas.NewText(" FFmpeg", colornames.Darkgreen) | ||||
| 	programmName.TextStyle = fyne.TextStyle{Bold: true} | ||||
| 	programmName.TextSize = 20 | ||||
|  | ||||
| 	programmLink := widget.NewHyperlink(lang.L("programmLink"), &url.URL{ | ||||
| 		Scheme: "https", | ||||
| 		Host:   "ffmpeg.org", | ||||
| 		Path:   "", | ||||
| 	}) | ||||
|  | ||||
| 	licenseLink := widget.NewHyperlink(lang.L("licenseLink"), &url.URL{ | ||||
| 		Scheme: "https", | ||||
| 		Host:   "ffmpeg.org", | ||||
| 		Path:   "legal.html", | ||||
| 	}) | ||||
|  | ||||
| 	return container.NewVBox( | ||||
| 		programmName, | ||||
| 		widget.NewLabel(version), | ||||
| 		widget.NewRichTextFromMarkdown("**FFmpeg** is a trademark of **[Fabrice Bellard](https://bellard.org/)**, originator of the **[FFmpeg](https://ffmpeg.org/about.html)** project."), | ||||
| 		widget.NewRichTextFromMarkdown("This software uses libraries from the **FFmpeg** project under the **[LGPLv2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)**."), | ||||
| 		container.NewHBox(programmLink, licenseLink), | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func aboutFFprobe(version string) *fyne.Container { | ||||
| 	programmName := canvas.NewText(" FFprobe", colornames.Darkgreen) | ||||
| 	programmName.TextStyle = fyne.TextStyle{Bold: true} | ||||
| 	programmName.TextSize = 20 | ||||
|  | ||||
| 	programmLink := widget.NewHyperlink(lang.L("programmLink"), &url.URL{ | ||||
| 		Scheme: "https", | ||||
| 		Host:   "ffmpeg.org", | ||||
| 		Path:   "ffprobe.html", | ||||
| 	}) | ||||
|  | ||||
| 	licenseLink := widget.NewHyperlink(lang.L("licenseLink"), &url.URL{ | ||||
| 		Scheme: "https", | ||||
| 		Host:   "ffmpeg.org", | ||||
| 		Path:   "legal.html", | ||||
| 	}) | ||||
|  | ||||
| 	return container.NewVBox( | ||||
| 		programmName, | ||||
| 		widget.NewLabel(version), | ||||
| 		widget.NewRichTextFromMarkdown("**FFmpeg** is a trademark of **[Fabrice Bellard](https://bellard.org/)**, originator of the **[FFmpeg](https://ffmpeg.org/about.html)** project."), | ||||
| 		widget.NewRichTextFromMarkdown("This software uses libraries from the **FFmpeg** project under the **[LGPLv2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)**."), | ||||
| 		container.NewHBox(programmLink, licenseLink), | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func aboutFFplay(version string) *fyne.Container { | ||||
| 	programmName := canvas.NewText(" FFplay", colornames.Darkgreen) | ||||
| 	programmName.TextStyle = fyne.TextStyle{Bold: true} | ||||
| 	programmName.TextSize = 20 | ||||
|  | ||||
| 	programmLink := widget.NewHyperlink(lang.L("programmLink"), &url.URL{ | ||||
| 		Scheme: "https", | ||||
| 		Host:   "ffmpeg.org", | ||||
| 		Path:   "ffplay.html", | ||||
| 	}) | ||||
|  | ||||
| 	licenseLink := widget.NewHyperlink(lang.L("licenseLink"), &url.URL{ | ||||
| 		Scheme: "https", | ||||
| 		Host:   "ffmpeg.org", | ||||
| 		Path:   "legal.html", | ||||
| 	}) | ||||
|  | ||||
| 	return container.NewVBox( | ||||
| 		programmName, | ||||
| 		widget.NewLabel(version), | ||||
| 		widget.NewRichTextFromMarkdown("**FFmpeg** is a trademark of **[Fabrice Bellard](https://bellard.org/)**, originator of the **[FFmpeg](https://ffmpeg.org/about.html)** project."), | ||||
| 		widget.NewRichTextFromMarkdown("This software uses libraries from the **FFmpeg** project under the **[LGPLv2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)**."), | ||||
| 		container.NewHBox(programmLink, licenseLink), | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func license3RDParty() *fyne.Container { | ||||
| 	return container.NewVBox( | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("fyne.io/fyne/v2", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fyne-io/fyne", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("BSD 3-Clause License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fyne-io/fyne/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewRichTextFromMarkdown("Copyright (C) 2018 Fyne.io developers (see [AUTHORS](https://github.com/fyne-io/fyne/blob/master/AUTHORS))"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("fyne.io/systray", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fyne-io/systray", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("Apache License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fyne-io/systray/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/BurntSushi/toml", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "BurntSushi/toml", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("The MIT License (MIT)", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "BurntSushi/toml/blob/master/COPYING", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2013 TOML authors"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/davecgh/go-spew", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "davecgh/go-spew", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("ISC License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "davecgh/go-spew/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2012-2016 Dave Collins <dave@davec.name>"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/fredbi/uri", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fredbi/uri", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("The MIT License (MIT)", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fredbi/uri/blob/master/LICENSE.md", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2018 Frederic Bidon"), | ||||
| 		widget.NewLabel("Copyright (c) 2015 Trey Tacon"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/fsnotify/fsnotify", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fsnotify/fsnotify", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("BSD-3-Clause license", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fsnotify/fsnotify/blob/main/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright © 2012 The Go Authors. All rights reserved."), | ||||
| 		widget.NewLabel("Copyright © fsnotify Authors. All rights reserved."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/fyne-io/gl-js", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fyne-io/gl-js", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("BSD-3-Clause license", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fyne-io/gl-js/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2009 The Go Authors. All rights reserved."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/fyne-io/glfw-js", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fyne-io/glfw-js", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("MIT License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fyne-io/glfw-js/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2014 Dmitri Shuralyov"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/fyne-io/image", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fyne-io/image", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("BSD 3-Clause License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fyne-io/image/blob/main/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2022, Fyne.io"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/fyne-io/oksvg", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fyne-io/oksvg", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("BSD 3-Clause License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "fyne-io/oksvg/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2018, Steven R Wiley. All rights reserved."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/go-gl/gl", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "go-gl/gl", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("The MIT License (MIT)", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "go-gl/gl/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2014 Eric Woroshow"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/go-gl/glfw/v3.3/glfw", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "go-gl/glfw/", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("BSD-3-Clause license", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "go-gl/glfw/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2012 The glfw3-go Authors. All rights reserved."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/go-text/render", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "go-text/render", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("Unlicense OR BSD-3-Clause", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "go-text/render/blob/main/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright 2021 The go-text authors"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/go-text/typesetting", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "go-text/typesetting", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("Unlicense OR BSD-3-Clause", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "go-text/typesetting/blob/main/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright 2021 The go-text authors"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/godbus/dbus/v5", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "godbus/dbus", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("BSD 2-Clause \"Simplified\" License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "godbus/dbus/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2013, Georg Reinke (<guelfey at gmail dot com>), Google. All rights reserved."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/hack-pad/go-indexeddb", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "hack-pad/go-indexeddb", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("Apache License 2.0", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "hack-pad/go-indexeddb/blob/main/LICENSE", | ||||
| 		})), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/hack-pad/safejs", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "hack-pad/safejs", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("Apache License 2.0", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "hack-pad/safejs/blob/main/LICENSE", | ||||
| 		})), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/jeandeaual/go-locale", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "jeandeaual/go-locale", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("MIT License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "jeandeaual/go-locale/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2020 Alexis Jeandeau"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/jsummers/gobmp", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "jsummers/gobmp", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("The MIT License (MIT)", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "jsummers/gobmp/blob/master/COPYING.txt", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2012-2015 Jason Summers"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/nfnt/resize", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "nfnt/resize", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("ISC License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "nfnt/resize/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2012, Jan Schlicht <jan.schlicht@gmail.com>"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/nicksnyder/go-i18n/v2", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "nicksnyder/go-i18n", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("The MIT License (MIT)", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "nicksnyder/go-i18n/blob/main/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewRichTextFromMarkdown("Copyright (c) 2014 Nick Snyder [https://github.com/nicksnyder](https://github.com/nicksnyder)"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/pmezard/go-difflib", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "pmezard/go-difflib", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "pmezard/go-difflib/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2013, Patrick Mezard. All rights reserved."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/rymdport/portal", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "rymdport/portal", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("Apache License 2.0", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "rymdport/portal/blob/main/LICENSE", | ||||
| 		})), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/srwiley/oksvg", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "srwiley/oksvg", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("BSD 3-Clause License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "srwiley/oksvg/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2018, Steven R Wiley. All rights reserved."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/srwiley/rasterx", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "srwiley/rasterx", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("BSD 3-Clause License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "srwiley/rasterx/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2018, Steven R Wiley. All rights reserved."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/stretchr/testify", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "stretchr/testify", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("MIT License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "stretchr/testify/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/ulikunitz/xz", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "ulikunitz/xz", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "ulikunitz/xz/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2014-2022 Ulrich Kunitz. All rights reserved."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/yuin/goldmark", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "yuin/goldmark", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("MIT License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "yuin/goldmark/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2019 Yusuke Inuzuka"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("golang.org/x/image", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "pkg.go.dev", | ||||
| 			Path:   "golang.org/x/image", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "cs.opensource.google", | ||||
| 			Path:   "go/x/image/+/master:LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright 2009 The Go Authors."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("golang.org/x/net", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "pkg.go.dev", | ||||
| 			Path:   "golang.org/x/net", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "cs.opensource.google", | ||||
| 			Path:   "go/x/net/+/master:LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright 2009 The Go Authors."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("golang.org/x/sys", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "pkg.go.dev", | ||||
| 			Path:   "golang.org/x/sys", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "cs.opensource.google", | ||||
| 			Path:   "go/x/sys/+/master:LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright 2009 The Go Authors."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("golang.org/x/text", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "pkg.go.dev", | ||||
| 			Path:   "golang.org/x/text", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "cs.opensource.google", | ||||
| 			Path:   "go/x/text/+/master:LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright 2009 The Go Authors."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("gopkg.in/yaml.v3", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "go-yaml/yaml/tree/v3.0.1", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("MIT License and Apache License 2.0", &url.URL{ | ||||
| 			Scheme: "http", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "go-yaml/yaml/blob/v3.0.1/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright (c) 2006-2010 Kirill Simonov"), | ||||
| 		widget.NewLabel("Copyright (c) 2006-2011 Kirill Simonov"), | ||||
| 		widget.NewLabel("Copyright (c) 2011-2019 Canonical Ltd"), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
|  | ||||
| 		container.NewHBox(widget.NewHyperlink("github.com/golang/go", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "golang/go", | ||||
| 		})), | ||||
| 		container.NewHBox(widget.NewHyperlink("BSD 3-Clause \"New\" or \"Revised\" License", &url.URL{ | ||||
| 			Scheme: "https", | ||||
| 			Host:   "github.com", | ||||
| 			Path:   "golang/go/blob/master/LICENSE", | ||||
| 		})), | ||||
| 		widget.NewLabel("Copyright 2009 The Go Authors."), | ||||
| 		canvas.NewLine(colornames.Darkgreen), | ||||
| 	) | ||||
| } | ||||
							
								
								
									
										129
									
								
								internal/gui/view/configuring_ffmpeg_utilities.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								internal/gui/view/configuring_ffmpeg_utilities.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| package view | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/storage" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/window" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/utils" | ||||
| 	"image/color" | ||||
| 	"net/url" | ||||
| 	"path/filepath" | ||||
| ) | ||||
|  | ||||
| func ConfiguringFFmpegUtilities( | ||||
| 	window window.WindowContract, | ||||
| 	currentPathFFmpeg string, | ||||
| 	currentPathFFprobe string, | ||||
| 	currentPathFFplay string, | ||||
| 	save func(ffmpegPath string, ffprobePath string, ffplayPath string) error, | ||||
| 	cancel func(), | ||||
| 	donwloadFFmpeg fyne.CanvasObject, | ||||
| ) fyne.CanvasObject { | ||||
| 	errorMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255}) | ||||
| 	errorMessage.TextSize = 16 | ||||
| 	errorMessage.TextStyle = fyne.TextStyle{Bold: true} | ||||
|  | ||||
| 	link := widget.NewHyperlink("https://ffmpeg.org/download.html", &url.URL{ | ||||
| 		Scheme: "https", | ||||
| 		Host:   "ffmpeg.org", | ||||
| 		Path:   "download.html", | ||||
| 	}) | ||||
|  | ||||
| 	ffmpegPath, buttonFFmpeg, buttonFFmpegMessage := configuringFFmpegUtilitiesButtonSelectFile(window, currentPathFFmpeg) | ||||
| 	ffprobePath, buttonFFprobe, buttonFFprobeMessage := configuringFFmpegUtilitiesButtonSelectFile(window, currentPathFFprobe) | ||||
| 	ffplayPath, buttonFFplay, buttonFFplayMessage := configuringFFmpegUtilitiesButtonSelectFile(window, currentPathFFplay) | ||||
|  | ||||
| 	form := &widget.Form{ | ||||
| 		Items: []*widget.FormItem{ | ||||
| 			{ | ||||
| 				Text:   lang.L("titleDownloadLink"), | ||||
| 				Widget: link, | ||||
| 			}, | ||||
| 			{ | ||||
| 				Text:   lang.L("pathToFfmpeg"), | ||||
| 				Widget: buttonFFmpeg, | ||||
| 			}, | ||||
| 			{ | ||||
| 				Widget: container.NewHScroll(buttonFFmpegMessage), | ||||
| 			}, | ||||
| 			{ | ||||
| 				Text:   lang.L("pathToFfprobe"), | ||||
| 				Widget: buttonFFprobe, | ||||
| 			}, | ||||
| 			{ | ||||
| 				Widget: container.NewHScroll(buttonFFprobeMessage), | ||||
| 			}, | ||||
| 			{ | ||||
| 				Text:   lang.L("pathToFfplay"), | ||||
| 				Widget: buttonFFplay, | ||||
| 			}, | ||||
| 			{ | ||||
| 				Widget: container.NewHScroll(buttonFFplayMessage), | ||||
| 			}, | ||||
| 			{ | ||||
| 				Widget: container.NewHScroll(errorMessage), | ||||
| 			}, | ||||
| 		}, | ||||
| 		SubmitText: lang.L("save"), | ||||
| 		OnSubmit: func() { | ||||
| 			err := save(*ffmpegPath, *ffprobePath, *ffplayPath) | ||||
| 			if err != nil { | ||||
| 				errorMessage.Text = err.Error() | ||||
| 			} | ||||
| 		}, | ||||
| 	} | ||||
| 	if cancel != nil { | ||||
| 		form.OnCancel = cancel | ||||
| 		form.CancelText = lang.L("cancel") | ||||
| 	} | ||||
|  | ||||
| 	selectFFPathTitle := lang.L("selectFFPathTitle") | ||||
|  | ||||
| 	return widget.NewCard(selectFFPathTitle, "", container.NewVBox( | ||||
| 		form, | ||||
| 		donwloadFFmpeg, | ||||
| 	)) | ||||
| } | ||||
|  | ||||
| func configuringFFmpegUtilitiesButtonSelectFile(window window.WindowContract, path string) (filePath *string, button *widget.Button, buttonMessage *canvas.Text) { | ||||
| 	filePath = &path | ||||
|  | ||||
| 	buttonMessage = canvas.NewText(path, color.RGBA{R: 49, G: 127, B: 114, A: 255}) | ||||
| 	buttonMessage.TextSize = 16 | ||||
| 	buttonMessage.TextStyle = fyne.TextStyle{Bold: true} | ||||
|  | ||||
| 	buttonTitle := lang.L("choose") | ||||
|  | ||||
| 	var locationURI fyne.ListableURI | ||||
| 	if len(path) > 0 { | ||||
| 		listableURI := storage.NewFileURI(filepath.Dir(path)) | ||||
| 		locationURI, _ = storage.ListerForURI(listableURI) | ||||
| 	} | ||||
|  | ||||
| 	button = widget.NewButton(buttonTitle, func() { | ||||
| 		window.NewFileOpen(func(r fyne.URIReadCloser, err error) { | ||||
| 			if err != nil { | ||||
| 				buttonMessage.Text = err.Error() | ||||
| 				utils.SetStringErrorStyle(buttonMessage) | ||||
| 				return | ||||
| 			} | ||||
| 			if r == nil { | ||||
| 				return | ||||
| 			} | ||||
|  | ||||
| 			path = r.URI().Path() | ||||
|  | ||||
| 			buttonMessage.Text = r.URI().Path() | ||||
| 			utils.SetStringSuccessStyle(buttonMessage) | ||||
|  | ||||
| 			listableURI := storage.NewFileURI(filepath.Dir(r.URI().Path())) | ||||
| 			locationURI, _ = storage.ListerForURI(listableURI) | ||||
| 		}, locationURI) | ||||
| 	}) | ||||
|  | ||||
| 	return filePath, button, buttonMessage | ||||
| } | ||||
							
								
								
									
										414
									
								
								internal/gui/view/convertor.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										414
									
								
								internal/gui/view/convertor.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,414 @@ | ||||
| package view | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/storage" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/convertor/encoder" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg" | ||||
| 	encoder2 "git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/view/convertor/encoders" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/window" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/utils" | ||||
| 	"image/color" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| ) | ||||
|  | ||||
| type ConvertSetting struct { | ||||
| 	DirectoryForSave     string | ||||
| 	OverwriteOutputFiles bool | ||||
| 	Format               string | ||||
| 	Encoder              encoder2.EncoderContract | ||||
| } | ||||
|  | ||||
| func Convertor( | ||||
| 	window window.WindowContract, | ||||
| 	addFileForConversion func(file ffmpeg.File), | ||||
| 	directoryForSavingPath string, | ||||
| 	directoryForSaving func(path string), | ||||
| 	formats encoder.ConvertorFormatsContract, | ||||
| 	addToConversion func(convertSetting ConvertSetting) error, | ||||
| ) fyne.CanvasObject { | ||||
| 	conversionMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255}) | ||||
| 	conversionMessage.TextSize = 16 | ||||
| 	conversionMessage.TextStyle = fyne.TextStyle{Bold: true} | ||||
|  | ||||
| 	form := newFormConvertor( | ||||
| 		window, | ||||
| 		addFileForConversion, | ||||
| 		directoryForSavingPath, | ||||
| 		directoryForSaving, | ||||
| 		formats, | ||||
| 		addToConversion, | ||||
| 		conversionMessage, | ||||
| 	) | ||||
|  | ||||
| 	converterVideoFilesTitle := lang.L("converterVideoFilesTitle") | ||||
| 	return widget.NewCard(converterVideoFilesTitle, "", container.NewVScroll(form.getForm())) | ||||
| } | ||||
|  | ||||
| type formConvertor struct { | ||||
| 	form              *widget.Form | ||||
| 	items             []*widget.FormItem | ||||
| 	conversionMessage *canvas.Text | ||||
|  | ||||
| 	window               window.WindowContract | ||||
| 	addFileForConversion func(file ffmpeg.File) | ||||
| 	directoryForSaving   func(path string) | ||||
| } | ||||
|  | ||||
| func newFormConvertor( | ||||
| 	window window.WindowContract, | ||||
| 	addFileForConversion func(file ffmpeg.File), | ||||
| 	directoryForSavingPath string, | ||||
| 	directoryForSaving func(path string), | ||||
| 	formats encoder.ConvertorFormatsContract, | ||||
| 	addToConversion func(convertSetting ConvertSetting) error, | ||||
| 	conversionMessage *canvas.Text, | ||||
| ) *formConvertor { | ||||
| 	f := widget.NewForm() | ||||
| 	f.SubmitText = lang.L("converterVideoFilesSubmitTitle") | ||||
|  | ||||
| 	formConvertor := &formConvertor{ | ||||
| 		form:                 f, | ||||
| 		window:               window, | ||||
| 		addFileForConversion: addFileForConversion, | ||||
| 		directoryForSaving:   directoryForSaving, | ||||
| 		conversionMessage:    conversionMessage, | ||||
| 	} | ||||
|  | ||||
| 	fileForConversion := formConvertor.newFileForConversion() | ||||
| 	directoryForSavingButton := formConvertor.newDirectoryForSaving(directoryForSavingPath) | ||||
| 	isOverwriteOutputFiles := false | ||||
| 	checkboxOverwriteOutputFiles := widget.NewCheck(lang.L("checkboxOverwriteOutputFilesTitle"), func(b bool) { | ||||
| 		isOverwriteOutputFiles = b | ||||
| 	}) | ||||
| 	checkboxOverwriteOutputFiles.SetChecked(isOverwriteOutputFiles) | ||||
| 	selectEncoder := formConvertor.newSelectEncoder(formats) | ||||
|  | ||||
| 	items := []*widget.FormItem{ | ||||
| 		{ | ||||
| 			Text:   lang.L("fileForConversionTitle"), | ||||
| 			Widget: fileForConversion.button, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Widget: container.NewHScroll(fileForConversion.message), | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
| 			Text:   lang.L("buttonForSelectedDirTitle"), | ||||
| 			Widget: directoryForSavingButton.button, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Widget: container.NewHScroll(directoryForSavingButton.message), | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
| 			Widget: checkboxOverwriteOutputFiles, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Widget: selectEncoder.SelectFileType, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Text:   lang.L("selectFormat"), | ||||
| 			Widget: selectEncoder.SelectFormat, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Text:   lang.L("selectEncoder"), | ||||
| 			Widget: selectEncoder.SelectEncoder, | ||||
| 		}, | ||||
| 	} | ||||
| 	formConvertor.form.Items = items | ||||
| 	formConvertor.items = items | ||||
| 	formConvertor.changeEncoder(selectEncoder.Encoder) | ||||
| 	selectEncoder.ChangeEncoder = formConvertor.changeEncoder | ||||
|  | ||||
| 	formConvertor.form.OnSubmit = func() { | ||||
| 		formConvertor.conversionMessage.Text = "" | ||||
| 		if len(directoryForSavingButton.path) == 0 { | ||||
| 			formConvertor.conversionMessage.Text = lang.L("errorSelectedFolderSave") | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		if len(selectEncoder.SelectFormat.Selected) == 0 { | ||||
| 			formConvertor.conversionMessage.Text = lang.L("errorSelectedFormat") | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		if selectEncoder.Encoder == nil { | ||||
| 			formConvertor.conversionMessage.Text = lang.L("errorSelectedEncoder") | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		fileForConversion.button.Disable() | ||||
| 		directoryForSavingButton.button.Disable() | ||||
| 		formConvertor.form.Disable() | ||||
|  | ||||
| 		fyne.Do(func() { | ||||
| 			err := addToConversion(ConvertSetting{ | ||||
| 				DirectoryForSave:     directoryForSavingButton.path, | ||||
| 				OverwriteOutputFiles: isOverwriteOutputFiles, | ||||
| 				Format:               selectEncoder.SelectFormat.Selected, | ||||
| 				Encoder:              selectEncoder.Encoder, | ||||
| 			}) | ||||
| 			if err != nil { | ||||
| 				formConvertor.conversionMessage.Text = err.Error() | ||||
| 			} | ||||
| 			fileForConversion.button.Enable() | ||||
| 			directoryForSavingButton.button.Enable() | ||||
| 			formConvertor.form.Enable() | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	return formConvertor | ||||
| } | ||||
|  | ||||
| func (f *formConvertor) getForm() fyne.CanvasObject { | ||||
| 	return container.NewVBox( | ||||
| 		f.form, | ||||
| 		container.NewHScroll(f.conversionMessage), | ||||
| 	) | ||||
| } | ||||
|  | ||||
| type fileForConversion struct { | ||||
| 	button  *widget.Button | ||||
| 	message *canvas.Text | ||||
| 	file    *ffmpeg.File | ||||
| } | ||||
|  | ||||
| func (f *formConvertor) newFileForConversion() *fileForConversion { | ||||
| 	message := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255}) | ||||
| 	fileForConversion := &fileForConversion{ | ||||
| 		message: message, | ||||
| 	} | ||||
|  | ||||
| 	buttonTitle := lang.L("choose") + "\n" + | ||||
| 		lang.L("or") + "\n" + | ||||
| 		lang.L("dragAndDropFiles") | ||||
|  | ||||
| 	var locationURI fyne.ListableURI | ||||
|  | ||||
| 	fileForConversion.button = widget.NewButton(buttonTitle, func() { | ||||
| 		f.window.NewFileOpen(func(r fyne.URIReadCloser, err error) { | ||||
| 			fyne.Do(func() { | ||||
| 				fileForConversion.message.Text = "" | ||||
| 				fileForConversion.message.Refresh() | ||||
| 			}) | ||||
|  | ||||
| 			if err != nil { | ||||
| 				fyne.Do(func() { | ||||
| 					fileForConversion.message.Text = err.Error() | ||||
| 					fileForConversion.message.Refresh() | ||||
| 				}) | ||||
| 				return | ||||
| 			} | ||||
| 			if r == nil { | ||||
| 				return | ||||
| 			} | ||||
|  | ||||
| 			f.addFileForConversion(ffmpeg.File{ | ||||
| 				Path: r.URI().Path(), | ||||
| 				Name: r.URI().Name(), | ||||
| 				Ext:  r.URI().Extension(), | ||||
| 			}) | ||||
|  | ||||
| 			listableURI := storage.NewFileURI(filepath.Dir(r.URI().Path())) | ||||
| 			locationURI, _ = storage.ListerForURI(listableURI) | ||||
| 		}, locationURI) | ||||
| 	}) | ||||
|  | ||||
| 	f.window.SetOnDropped(func(position fyne.Position, uris []fyne.URI) { | ||||
| 		if len(uris) == 0 { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		isError := false | ||||
| 		for _, uri := range uris { | ||||
| 			info, err := os.Stat(uri.Path()) | ||||
| 			if err != nil { | ||||
| 				isError = true | ||||
| 				continue | ||||
| 			} | ||||
| 			if info.IsDir() { | ||||
| 				isError = true | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			f.addFileForConversion(ffmpeg.File{ | ||||
| 				Path: uri.Path(), | ||||
| 				Name: uri.Name(), | ||||
| 				Ext:  uri.Extension(), | ||||
| 			}) | ||||
|  | ||||
| 			listableURI := storage.NewFileURI(filepath.Dir(uri.Path())) | ||||
| 			locationURI, _ = storage.ListerForURI(listableURI) | ||||
| 		} | ||||
|  | ||||
| 		if isError { | ||||
| 			fileForConversion.message.Text = lang.L("errorDragAndDropFile") | ||||
| 			utils.SetStringErrorStyle(fileForConversion.message) | ||||
| 		} else { | ||||
| 			fyne.Do(func() { | ||||
| 				fileForConversion.message.Text = "" | ||||
| 				fileForConversion.message.Refresh() | ||||
| 			}) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	return fileForConversion | ||||
| } | ||||
|  | ||||
| type directoryForSaving struct { | ||||
| 	button  *widget.Button | ||||
| 	message *canvas.Text | ||||
| 	path    string | ||||
| } | ||||
|  | ||||
| func (f *formConvertor) newDirectoryForSaving(directoryForSavingPath string) *directoryForSaving { | ||||
| 	directoryForSaving := &directoryForSaving{ | ||||
| 		path: "", | ||||
| 	} | ||||
|  | ||||
| 	directoryForSaving.message = canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255}) | ||||
| 	directoryForSaving.message.TextSize = 16 | ||||
| 	directoryForSaving.message.TextStyle = fyne.TextStyle{Bold: true} | ||||
|  | ||||
| 	buttonTitle := lang.L("choose") | ||||
|  | ||||
| 	locationURI, err := utils.PathToListableURI(directoryForSavingPath) | ||||
| 	if err == nil { | ||||
| 		directoryForSaving.path = locationURI.Path() | ||||
| 		directoryForSaving.message.Text = locationURI.Path() | ||||
| 		utils.SetStringSuccessStyle(directoryForSaving.message) | ||||
| 	} | ||||
|  | ||||
| 	directoryForSaving.button = widget.NewButton(buttonTitle, func() { | ||||
| 		f.window.NewFolderOpen(func(r fyne.ListableURI, err error) { | ||||
| 			if err != nil { | ||||
| 				directoryForSaving.message.Text = err.Error() | ||||
| 				utils.SetStringErrorStyle(directoryForSaving.message) | ||||
| 				return | ||||
| 			} | ||||
| 			if r == nil { | ||||
| 				return | ||||
| 			} | ||||
|  | ||||
| 			directoryForSaving.path = r.Path() | ||||
|  | ||||
| 			directoryForSaving.message.Text = r.Path() | ||||
| 			utils.SetStringSuccessStyle(directoryForSaving.message) | ||||
| 			locationURI, err = storage.ListerForURI(r) | ||||
|  | ||||
| 			if err == nil { | ||||
| 				f.directoryForSaving(locationURI.Path()) | ||||
| 			} | ||||
|  | ||||
| 		}, locationURI) | ||||
| 	}) | ||||
|  | ||||
| 	return directoryForSaving | ||||
| } | ||||
|  | ||||
| type selectEncoder struct { | ||||
| 	SelectFileType *widget.RadioGroup | ||||
| 	SelectFormat   *widget.Select | ||||
| 	SelectEncoder  *widget.Select | ||||
| 	Encoder        encoder2.EncoderContract | ||||
|  | ||||
| 	ChangeEncoder func(encoder encoder2.EncoderContract) | ||||
| } | ||||
|  | ||||
| func (f *formConvertor) newSelectEncoder(formats encoder.ConvertorFormatsContract) *selectEncoder { | ||||
| 	selectEncoder := &selectEncoder{} | ||||
|  | ||||
| 	encoderMap := map[int]encoder2.EncoderDataContract{} | ||||
| 	selectEncoder.SelectEncoder = widget.NewSelect([]string{}, func(s string) { | ||||
| 		if encoderMap[selectEncoder.SelectEncoder.SelectedIndex()] == nil { | ||||
| 			return | ||||
| 		} | ||||
| 		selectEncoderData := encoderMap[selectEncoder.SelectEncoder.SelectedIndex()] | ||||
| 		selectEncoder.Encoder = selectEncoderData.NewEncoder() | ||||
| 		if selectEncoder.ChangeEncoder != nil { | ||||
| 			selectEncoder.ChangeEncoder(selectEncoder.Encoder) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	formatSelected := "" | ||||
| 	selectEncoder.SelectFormat = widget.NewSelect([]string{}, func(s string) { | ||||
| 		if formatSelected == s { | ||||
| 			return | ||||
| 		} | ||||
| 		formatSelected = s | ||||
| 		format, err := formats.GetFormat(s) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		var encoderOptions []string | ||||
| 		encoderMap = map[int]encoder2.EncoderDataContract{} | ||||
| 		for _, e := range format.GetEncoders() { | ||||
| 			encoderMap[len(encoderMap)] = e | ||||
| 			encoderOptions = append(encoderOptions, lang.L("encoder_"+e.GetTitle())) | ||||
| 		} | ||||
| 		selectEncoder.SelectEncoder.SetOptions(encoderOptions) | ||||
| 		selectEncoder.SelectEncoder.SetSelectedIndex(0) | ||||
| 	}) | ||||
|  | ||||
| 	var fileTypeOptions []string | ||||
| 	for _, fileType := range encoder2.GetListFileType() { | ||||
| 		fileTypeOptions = append(fileTypeOptions, fileType.Name()) | ||||
| 	} | ||||
|  | ||||
| 	encoderGroupVideo := lang.L("encoderGroupVideo") | ||||
| 	encoderGroupAudio := lang.L("encoderGroupAudio") | ||||
| 	encoderGroupImage := lang.L("encoderGroupImage") | ||||
| 	encoderGroup := map[string]string{ | ||||
| 		encoderGroupVideo: "video", | ||||
| 		encoderGroupAudio: "audio", | ||||
| 		encoderGroupImage: "image", | ||||
| 	} | ||||
| 	selectEncoder.SelectFileType = widget.NewRadioGroup([]string{encoderGroupVideo, encoderGroupAudio, encoderGroupImage}, func(s string) { | ||||
| 		groupCode := encoderGroup[s] | ||||
|  | ||||
| 		var formatOptions []string | ||||
| 		for _, f := range formats.GetFormats() { | ||||
| 			if groupCode != f.GetFileType().Name() { | ||||
| 				continue | ||||
| 			} | ||||
| 			formatOptions = append(formatOptions, f.GetTitle()) | ||||
| 		} | ||||
| 		selectEncoder.SelectFormat.SetOptions(formatOptions) | ||||
| 		if groupCode == encoder2.FileType(encoder2.Video).Name() { | ||||
| 			selectEncoder.SelectFormat.SetSelected("mp4") | ||||
| 		} else { | ||||
| 			selectEncoder.SelectFormat.SetSelectedIndex(0) | ||||
| 		} | ||||
| 	}) | ||||
| 	selectEncoder.SelectFileType.Horizontal = true | ||||
| 	selectEncoder.SelectFileType.Required = true | ||||
| 	selectEncoder.SelectFileType.SetSelected(encoderGroupVideo) | ||||
|  | ||||
| 	return selectEncoder | ||||
| } | ||||
|  | ||||
| func (f *formConvertor) changeEncoder(encoder encoder2.EncoderContract) { | ||||
| 	var items []*widget.FormItem | ||||
|  | ||||
| 	if encoders.Views[encoder.GetName()] != nil { | ||||
| 		items = encoders.Views[encoder.GetName()](encoder) | ||||
| 	} | ||||
|  | ||||
| 	f.changeItems(items) | ||||
| } | ||||
|  | ||||
| func (f *formConvertor) changeItems(items []*widget.FormItem) { | ||||
| 	fyne.Do(func() { | ||||
| 		f.form.Items = f.items | ||||
| 		f.form.Refresh() | ||||
| 		f.form.Items = append(f.form.Items, items...) | ||||
| 		f.form.Refresh() | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										15
									
								
								internal/gui/view/convertor/encoders/encoders.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								internal/gui/view/convertor/encoders/encoders.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| package encoders | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/view/convertor/encoders/h264_nvenc" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/view/convertor/encoders/libx264" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/view/convertor/encoders/libx265" | ||||
| ) | ||||
|  | ||||
| var Views = map[string]func(encoder encoder.EncoderContract) []*widget.FormItem{ | ||||
| 	"libx264":    libx264.View, | ||||
| 	"h264_nvenc": h264_nvenc.View, | ||||
| 	"libx265":    libx265.View, | ||||
| } | ||||
							
								
								
									
										64
									
								
								internal/gui/view/convertor/encoders/h264_nvenc/view.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								internal/gui/view/convertor/encoders/h264_nvenc/view.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| package h264_nvenc | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/h264_nvenc" | ||||
| ) | ||||
|  | ||||
| func View(encoder encoder.EncoderContract) []*widget.FormItem { | ||||
| 	items := []*widget.FormItem{} | ||||
|  | ||||
| 	items = append(items, presetParameter(encoder)...) | ||||
|  | ||||
| 	return items | ||||
| } | ||||
|  | ||||
| func presetParameter(encoder encoder.EncoderContract) []*widget.FormItem { | ||||
| 	parameter, err := encoder.GetParameter("preset") | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	presets := map[string]string{} | ||||
| 	presetsForSelect := []string{} | ||||
| 	presetDefault := "" | ||||
|  | ||||
| 	for _, name := range h264_nvenc.Presets { | ||||
| 		title := name | ||||
| 		presetsForSelect = append(presetsForSelect, name) | ||||
| 		presets[title] = name | ||||
| 		if name == parameter.Get() { | ||||
| 			presetDefault = title | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	elementSelect := widget.NewSelect(presetsForSelect, func(s string) { | ||||
| 		if presets[s] == "" { | ||||
| 			return | ||||
| 		} | ||||
| 		parameter.Set(presets[s]) | ||||
| 	}) | ||||
| 	elementSelect.SetSelected(presetDefault) | ||||
| 	elementSelect.Hide() | ||||
|  | ||||
| 	checkboxTitle := lang.L("parameterCheckbox") | ||||
| 	elementCheckbox := widget.NewCheck(checkboxTitle, func(b bool) { | ||||
| 		if b == true { | ||||
| 			parameter.SetEnable() | ||||
| 			elementSelect.Show() | ||||
| 			return | ||||
| 		} | ||||
| 		parameter.SetDisable() | ||||
| 		elementSelect.Hide() | ||||
| 	}) | ||||
|  | ||||
| 	return []*widget.FormItem{ | ||||
| 		{ | ||||
| 			Text:   lang.L("formPreset"), | ||||
| 			Widget: container.NewVBox(elementCheckbox, elementSelect), | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										64
									
								
								internal/gui/view/convertor/encoders/libx264/view.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								internal/gui/view/convertor/encoders/libx264/view.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| package libx264 | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/libx264" | ||||
| ) | ||||
|  | ||||
| func View(encoder encoder.EncoderContract) []*widget.FormItem { | ||||
| 	items := []*widget.FormItem{} | ||||
|  | ||||
| 	items = append(items, presetParameter(encoder)...) | ||||
|  | ||||
| 	return items | ||||
| } | ||||
|  | ||||
| func presetParameter(encoder encoder.EncoderContract) []*widget.FormItem { | ||||
| 	parameter, err := encoder.GetParameter("preset") | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	presets := map[string]string{} | ||||
| 	presetsForSelect := []string{} | ||||
| 	presetDefault := "" | ||||
|  | ||||
| 	for _, name := range libx264.Presets { | ||||
| 		title := lang.L("preset_" + name) | ||||
| 		presetsForSelect = append(presetsForSelect, title) | ||||
| 		presets[title] = name | ||||
| 		if name == parameter.Get() { | ||||
| 			presetDefault = title | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	elementSelect := widget.NewSelect(presetsForSelect, func(s string) { | ||||
| 		if presets[s] == "" { | ||||
| 			return | ||||
| 		} | ||||
| 		parameter.Set(presets[s]) | ||||
| 	}) | ||||
| 	elementSelect.SetSelected(presetDefault) | ||||
| 	elementSelect.Hide() | ||||
|  | ||||
| 	checkboxTitle := lang.L("parameterCheckbox") | ||||
| 	elementCheckbox := widget.NewCheck(checkboxTitle, func(b bool) { | ||||
| 		if b == true { | ||||
| 			parameter.SetEnable() | ||||
| 			elementSelect.Show() | ||||
| 			return | ||||
| 		} | ||||
| 		parameter.SetDisable() | ||||
| 		elementSelect.Hide() | ||||
| 	}) | ||||
|  | ||||
| 	return []*widget.FormItem{ | ||||
| 		{ | ||||
| 			Text:   lang.L("formPreset"), | ||||
| 			Widget: container.NewVBox(elementCheckbox, elementSelect), | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										64
									
								
								internal/gui/view/convertor/encoders/libx265/view.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								internal/gui/view/convertor/encoders/libx265/view.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| package libx265 | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg/encoder/libx265" | ||||
| ) | ||||
|  | ||||
| func View(encoder encoder.EncoderContract) []*widget.FormItem { | ||||
| 	items := []*widget.FormItem{} | ||||
|  | ||||
| 	items = append(items, presetParameter(encoder)...) | ||||
|  | ||||
| 	return items | ||||
| } | ||||
|  | ||||
| func presetParameter(encoder encoder.EncoderContract) []*widget.FormItem { | ||||
| 	parameter, err := encoder.GetParameter("preset") | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	presets := map[string]string{} | ||||
| 	presetsForSelect := []string{} | ||||
| 	presetDefault := "" | ||||
|  | ||||
| 	for _, name := range libx265.Presets { | ||||
| 		title := lang.L("preset_" + name) | ||||
| 		presetsForSelect = append(presetsForSelect, title) | ||||
| 		presets[title] = name | ||||
| 		if name == parameter.Get() { | ||||
| 			presetDefault = title | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	elementSelect := widget.NewSelect(presetsForSelect, func(s string) { | ||||
| 		if presets[s] == "" { | ||||
| 			return | ||||
| 		} | ||||
| 		parameter.Set(presets[s]) | ||||
| 	}) | ||||
| 	elementSelect.SetSelected(presetDefault) | ||||
| 	elementSelect.Hide() | ||||
|  | ||||
| 	checkboxTitle := lang.L("parameterCheckbox") | ||||
| 	elementCheckbox := widget.NewCheck(checkboxTitle, func(b bool) { | ||||
| 		if b == true { | ||||
| 			parameter.SetEnable() | ||||
| 			elementSelect.Show() | ||||
| 			return | ||||
| 		} | ||||
| 		parameter.SetDisable() | ||||
| 		elementSelect.Hide() | ||||
| 	}) | ||||
|  | ||||
| 	return []*widget.FormItem{ | ||||
| 		{ | ||||
| 			Text:   lang.L("formPreset"), | ||||
| 			Widget: container.NewVBox(elementCheckbox, elementSelect), | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										39
									
								
								internal/gui/view/error.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								internal/gui/view/error.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| package view | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/setting" | ||||
| ) | ||||
|  | ||||
| func StartWithError(err error, languages []setting.Lang, funcSelected func(lang setting.Lang)) fyne.CanvasObject { | ||||
| 	messageHead := lang.L("error") | ||||
|  | ||||
| 	listView := widget.NewList( | ||||
| 		func() int { | ||||
| 			return len(languages) | ||||
| 		}, | ||||
| 		func() fyne.CanvasObject { | ||||
| 			return widget.NewLabel("template") | ||||
| 		}, | ||||
| 		func(i widget.ListItemID, o fyne.CanvasObject) { | ||||
| 			block := o.(*widget.Label) | ||||
| 			block.SetText(languages[i].Title) | ||||
| 		}) | ||||
| 	listView.OnSelected = func(id widget.ListItemID) { | ||||
| 		funcSelected(languages[id]) | ||||
| 	} | ||||
|  | ||||
| 	return container.NewBorder( | ||||
| 		container.NewVBox( | ||||
| 			widget.NewLabel(messageHead), | ||||
| 			widget.NewLabel(err.Error()), | ||||
| 		), | ||||
| 		nil, | ||||
| 		nil, | ||||
| 		nil, | ||||
| 		listView, | ||||
| 	) | ||||
| } | ||||
							
								
								
									
										105
									
								
								internal/gui/view/help_ffplay.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								internal/gui/view/help_ffplay.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| package view | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/theme" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| ) | ||||
|  | ||||
| func HelpFFplay() fyne.CanvasObject { | ||||
| 	data := [][]string{ | ||||
| 		{ | ||||
| 			lang.L("helpFFplayKeys"), | ||||
| 			lang.L("helpFFplayDescription"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			"Q, ESC", | ||||
| 			lang.L("helpFFplayQuit"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			"F, " + lang.L("helpFFplayDoubleClickLeftMouseButton"), | ||||
| 			lang.L("helpFFplayToggleFullScreen"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			"P, " + lang.L("helpFFplayKeySpace"), | ||||
| 			lang.L("helpFFplayPause"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			"M", | ||||
| 			lang.L("helpFFplayToggleMute"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			"9, /", | ||||
| 			lang.L("helpFFplayDecreaseVolume"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			"0, *", | ||||
| 			lang.L("helpFFplayIncreaseVolume"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			lang.L("helpFFplayKeyLeft"), | ||||
| 			lang.L("helpFFplaySeekBackward10Seconds"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			lang.L("helpFFplayKeyRight"), | ||||
| 			lang.L("helpFFplaySeekForward10Seconds"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			lang.L("helpFFplayKeyDown"), | ||||
| 			lang.L("helpFFplaySeekBackward1Minute"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			lang.L("helpFFplayKeyUp"), | ||||
| 			lang.L("helpFFplaySeekBForward1Minute"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			"Page Down", | ||||
| 			lang.L("helpFFplaySeekBackward10Minutes"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			"Page Up", | ||||
| 			lang.L("helpFFplaySeekBForward10Minutes"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			"S, " + lang.L("helpFFplayKeyHoldS"), | ||||
| 			lang.L("helpFFplayActivateFrameStepMode"), | ||||
| 		}, | ||||
| 		{ | ||||
| 			"W", | ||||
| 			lang.L("helpFFplayCycleVideoFiltersOrShowModes"), | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	list := widget.NewTable( | ||||
| 		func() (int, int) { | ||||
| 			return len(data), len(data[0]) | ||||
| 		}, | ||||
| 		func() fyne.CanvasObject { | ||||
| 			return widget.NewLabel("") | ||||
| 		}, | ||||
| 		func(i widget.TableCellID, o fyne.CanvasObject) { | ||||
| 			label := o.(*widget.Label) | ||||
|  | ||||
| 			label.TextStyle.Bold = false | ||||
| 			label.SizeName = theme.SizeNameText | ||||
|  | ||||
| 			if i.Row == 0 { | ||||
| 				label.TextStyle.Bold = true | ||||
| 				label.SizeName = theme.SizeNameSubHeadingText | ||||
| 			} | ||||
|  | ||||
| 			if i.Col == 0 { | ||||
| 				label.TextStyle.Bold = true | ||||
| 			} | ||||
|  | ||||
| 			label.SetText(data[i.Row][i.Col]) | ||||
| 		}) | ||||
| 	list.SetRowHeight(0, 40) | ||||
| 	list.SetColumnWidth(0, 200) | ||||
| 	list.SetColumnWidth(1, 585) | ||||
| 	list.SetRowHeight(2, 55) | ||||
|  | ||||
| 	return container.NewScroll(list) | ||||
| } | ||||
							
								
								
									
										92
									
								
								internal/gui/view/mainSettings.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								internal/gui/view/mainSettings.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| package view | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/setting" | ||||
| 	"image/color" | ||||
| ) | ||||
|  | ||||
| type MainSettingForm struct { | ||||
| 	Language  setting.Lang | ||||
| 	ThemeInfo setting.ThemeInfoContract | ||||
| } | ||||
|  | ||||
| func MainSettings( | ||||
| 	currentLang setting.Lang, | ||||
| 	langList []setting.Lang, | ||||
|  | ||||
| 	themeInfo setting.ThemeInfoContract, | ||||
| 	themeList map[string]setting.ThemeInfoContract, | ||||
|  | ||||
| 	save func(form *MainSettingForm) error, | ||||
| 	cancel func(), | ||||
| ) fyne.CanvasObject { | ||||
|  | ||||
| 	errorMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255}) | ||||
| 	errorMessage.TextSize = 16 | ||||
| 	errorMessage.TextStyle = fyne.TextStyle{Bold: true} | ||||
|  | ||||
| 	viewSettingForm := &MainSettingForm{ | ||||
| 		Language:  currentLang, | ||||
| 		ThemeInfo: themeInfo, | ||||
| 	} | ||||
|  | ||||
| 	var languageItems []string | ||||
| 	langByTitle := map[string]setting.Lang{} | ||||
| 	for _, language := range langList { | ||||
| 		languageItems = append(languageItems, language.Title) | ||||
| 		langByTitle[language.Title] = language | ||||
| 	} | ||||
| 	selectLanguage := widget.NewSelect(languageItems, func(s string) { | ||||
| 		if lang, ok := langByTitle[s]; ok { | ||||
| 			viewSettingForm.Language = lang | ||||
| 		} | ||||
| 	}) | ||||
| 	selectLanguage.Selected = currentLang.Title | ||||
|  | ||||
| 	var themeItems []string | ||||
| 	themeByTitle := map[string]setting.ThemeInfoContract{} | ||||
| 	for _, themeInfo := range themeList { | ||||
| 		themeItems = append(themeItems, themeInfo.GetTitle()) | ||||
| 		themeByTitle[themeInfo.GetTitle()] = themeInfo | ||||
| 	} | ||||
| 	selectTheme := widget.NewSelect(themeItems, func(s string) { | ||||
| 		if themeInfo, ok := themeByTitle[s]; ok { | ||||
| 			viewSettingForm.ThemeInfo = themeInfo | ||||
| 		} | ||||
| 	}) | ||||
| 	selectTheme.Selected = themeInfo.GetTitle() | ||||
|  | ||||
| 	form := &widget.Form{ | ||||
| 		Items: []*widget.FormItem{ | ||||
| 			{ | ||||
| 				Text:   lang.L("menuSettingsLanguage"), | ||||
| 				Widget: selectLanguage, | ||||
| 			}, | ||||
| 			{ | ||||
| 				Text:   lang.L("menuSettingsTheme"), | ||||
| 				Widget: selectTheme, | ||||
| 			}, | ||||
| 			{ | ||||
| 				Widget: errorMessage, | ||||
| 			}, | ||||
| 		}, | ||||
| 		SubmitText: lang.L("save"), | ||||
| 		OnSubmit: func() { | ||||
| 			err := save(viewSettingForm) | ||||
| 			if err != nil { | ||||
| 				errorMessage.Text = err.Error() | ||||
| 			} | ||||
| 		}, | ||||
| 	} | ||||
| 	if cancel != nil { | ||||
| 		form.OnCancel = cancel | ||||
| 		form.CancelText = lang.L("cancel") | ||||
| 	} | ||||
|  | ||||
| 	messageHead := lang.L("settings") | ||||
| 	return widget.NewCard(messageHead, "", form) | ||||
| } | ||||
							
								
								
									
										28
									
								
								internal/gui/view/start_without_support_lang.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								internal/gui/view/start_without_support_lang.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| package view | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/setting" | ||||
| ) | ||||
|  | ||||
| func StartWithoutSupportLang(languages []setting.Lang, funcSelected func(lang setting.Lang)) fyne.CanvasObject { | ||||
| 	listView := widget.NewList( | ||||
| 		func() int { | ||||
| 			return len(languages) | ||||
| 		}, | ||||
| 		func() fyne.CanvasObject { | ||||
| 			return widget.NewLabel("template") | ||||
| 		}, | ||||
| 		func(i widget.ListItemID, o fyne.CanvasObject) { | ||||
| 			block := o.(*widget.Label) | ||||
| 			block.SetText(languages[i].Title) | ||||
| 		}) | ||||
| 	listView.OnSelected = func(id widget.ListItemID) { | ||||
| 		funcSelected(languages[id]) | ||||
| 	} | ||||
|  | ||||
| 	messageHead := lang.L("languageSelectionHead") | ||||
| 	return widget.NewCard(messageHead, "", listView) | ||||
| } | ||||
							
								
								
									
										172
									
								
								internal/gui/window/layout.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								internal/gui/window/layout.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,172 @@ | ||||
| package window | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/theme" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/convertor" | ||||
| ) | ||||
|  | ||||
| type LayoutContract interface { | ||||
| 	SetContent(content fyne.CanvasObject) fyne.CanvasObject | ||||
| 	GetRContainer() RightMainContainerContract | ||||
| } | ||||
|  | ||||
| type layout struct { | ||||
| 	layoutContainer *fyne.Container | ||||
| 	rContainer      RightMainContainerContract | ||||
| } | ||||
|  | ||||
| func NewLayout(progressBarService convertor.ProgressBarContract, itemsToConvert convertor.ItemsToConvertContract, queueLayout QueueLayoutContract) LayoutContract { | ||||
| 	rContainer := newRightContainer(progressBarService.GetContainer(), itemsToConvert, queueLayout) | ||||
| 	layoutContainer := container.NewAdaptiveGrid(2, widget.NewLabel(""), rContainer.GetCanvasObject()) | ||||
|  | ||||
| 	return &layout{ | ||||
| 		layoutContainer: layoutContainer, | ||||
| 		rContainer:      rContainer, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (l *layout) SetContent(content fyne.CanvasObject) fyne.CanvasObject { | ||||
| 	l.layoutContainer.Objects[0] = content | ||||
| 	return l.layoutContainer | ||||
| } | ||||
|  | ||||
| func (l *layout) GetRContainer() RightMainContainerContract { | ||||
| 	return l.rContainer | ||||
| } | ||||
|  | ||||
| type RightMainContainerContract interface { | ||||
| 	GetCanvasObject() fyne.CanvasObject | ||||
| 	GetTabs() *container.AppTabs | ||||
| 	SelectFileQueueTab() | ||||
| 	SelectAddedFilesTab() | ||||
| } | ||||
|  | ||||
| type rightMainContainer struct { | ||||
| 	container     fyne.CanvasObject | ||||
| 	tabs          *container.AppTabs | ||||
| 	addedFilesTab *container.TabItem | ||||
| 	fileQueueTab  *container.TabItem | ||||
| } | ||||
|  | ||||
| func newRightContainer(blockProgressbar *fyne.Container, itemsToConvert convertor.ItemsToConvertContract, queueLayout QueueLayoutContract) RightMainContainerContract { | ||||
| 	addedFilesTab := container.NewTabItem(lang.L("addedFilesTitle"), addedFilesContainer(itemsToConvert)) | ||||
| 	fileQueueTab := container.NewTabItem(lang.L("fileQueueTitle"), fileQueueContainer(queueLayout)) | ||||
|  | ||||
| 	tabs := container.NewAppTabs( | ||||
| 		addedFilesTab, | ||||
| 		fileQueueTab, | ||||
| 	) | ||||
|  | ||||
| 	rightContainer := container.NewBorder( | ||||
| 		container.NewVBox( | ||||
| 			blockProgressbar, | ||||
| 			widget.NewSeparator(), | ||||
| 		), | ||||
| 		nil, | ||||
| 		nil, | ||||
| 		nil, | ||||
| 		tabs, | ||||
| 	) | ||||
|  | ||||
| 	return &rightMainContainer{ | ||||
| 		container:     rightContainer, | ||||
| 		tabs:          tabs, | ||||
| 		addedFilesTab: addedFilesTab, | ||||
| 		fileQueueTab:  fileQueueTab, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (r *rightMainContainer) GetCanvasObject() fyne.CanvasObject { | ||||
| 	return r.container | ||||
| } | ||||
|  | ||||
| func (r *rightMainContainer) GetTabs() *container.AppTabs { | ||||
| 	return r.tabs | ||||
| } | ||||
|  | ||||
| func (r *rightMainContainer) SelectFileQueueTab() { | ||||
| 	fyne.Do(func() { | ||||
| 		r.tabs.Select(r.fileQueueTab) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (r *rightMainContainer) SelectAddedFilesTab() { | ||||
| 	fyne.Do(func() { | ||||
| 		r.tabs.Select(r.addedFilesTab) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func addedFilesContainer(itemsToConvert convertor.ItemsToConvertContract) *fyne.Container { | ||||
| 	line := canvas.NewLine(theme.Color(theme.ColorNameFocus)) | ||||
| 	line.StrokeWidth = 5 | ||||
| 	checkboxAutoRemove := widget.NewCheck( | ||||
| 		lang.L("autoClearAfterAddingToQueue"), | ||||
| 		func(checked bool) { | ||||
| 			itemsToConvert.SetIsAutoRemove(checked) | ||||
| 		}, | ||||
| 	) | ||||
| 	checkboxAutoRemove.SetChecked(itemsToConvert.GetIsAutoRemove()) | ||||
|  | ||||
| 	buttonClear := widget.NewButton( | ||||
| 		lang.L("clearAll"), | ||||
| 		func() { | ||||
| 			itemsToConvert.Clear() | ||||
| 		}, | ||||
| 	) | ||||
| 	buttonClear.Importance = widget.DangerImportance | ||||
| 	return container.NewBorder( | ||||
| 		container.NewVBox( | ||||
| 			container.NewPadded(), | ||||
| 			container.NewBorder(nil, nil, nil, buttonClear, container.NewHScroll(checkboxAutoRemove)), | ||||
| 			container.NewPadded(), | ||||
| 			line, | ||||
| 		), nil, nil, nil, | ||||
| 		container.NewVScroll( | ||||
| 			container.NewBorder( | ||||
| 				nil, nil, nil, container.NewPadded(), | ||||
| 				container.NewVBox( | ||||
| 					container.NewPadded(), | ||||
| 					itemsToConvert.GetItemsContainer(), | ||||
| 				), | ||||
| 			), | ||||
| 		), | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func fileQueueContainer(queueLayout QueueLayoutContract) *fyne.Container { | ||||
| 	title := widget.NewLabel(lang.L("queue")) | ||||
| 	title.TextStyle.Bold = true | ||||
|  | ||||
| 	line := canvas.NewLine(theme.Color(theme.ColorNameFocus)) | ||||
| 	line.StrokeWidth = 5 | ||||
|  | ||||
| 	queueLayout.GetQueueStatistics().GetWaiting().SetTitle(lang.L("waitingQueue")) | ||||
| 	queueLayout.GetQueueStatistics().GetInProgress().SetTitle(lang.L("inProgressQueue")) | ||||
| 	queueLayout.GetQueueStatistics().GetCompleted().SetTitle(lang.L("completedQueue")) | ||||
| 	queueLayout.GetQueueStatistics().GetError().SetTitle(lang.L("errorQueue")) | ||||
| 	queueLayout.GetQueueStatistics().GetTotal().SetTitle(lang.L("total")) | ||||
|  | ||||
| 	return container.NewBorder( | ||||
| 		container.NewVBox( | ||||
| 			container.NewPadded(), | ||||
| 			container.NewHBox(title, queueLayout.GetQueueStatistics().GetCompleted().GetCheckbox(), queueLayout.GetQueueStatistics().GetError().GetCheckbox()), | ||||
| 			container.NewHBox(queueLayout.GetQueueStatistics().GetInProgress().GetCheckbox(), queueLayout.GetQueueStatistics().GetWaiting().GetCheckbox(), queueLayout.GetQueueStatistics().GetTotal().GetCheckbox()), | ||||
| 			container.NewPadded(), | ||||
| 			line, | ||||
| 		), nil, nil, nil, | ||||
| 		container.NewVScroll( | ||||
| 			container.NewBorder( | ||||
| 				nil, nil, nil, container.NewPadded(), | ||||
| 				container.NewVBox( | ||||
| 					container.NewPadded(), | ||||
| 					queueLayout.GetItemsContainer(), | ||||
| 				), | ||||
| 			), | ||||
| 		), | ||||
| 	) | ||||
| } | ||||
							
								
								
									
										101
									
								
								internal/gui/window/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								internal/gui/window/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| package window | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/dialog" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/convertor" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/utils" | ||||
| ) | ||||
|  | ||||
| type WindowContract interface { | ||||
| 	SetContent(content fyne.CanvasObject) | ||||
| 	SetMainMenu(menu *fyne.MainMenu) | ||||
| 	Show() | ||||
| 	InitLayout() | ||||
| 	NewFileOpen(callback func(fyne.URIReadCloser, error), location fyne.ListableURI) *dialog.FileDialog | ||||
| 	NewFolderOpen(callback func(fyne.ListableURI, error), location fyne.ListableURI) *dialog.FileDialog | ||||
| 	SetOnDropped(callback func(position fyne.Position, uris []fyne.URI)) | ||||
| 	GetLayout() LayoutContract | ||||
| } | ||||
|  | ||||
| type mainWindow struct { | ||||
| 	fyneWindow         fyne.Window | ||||
| 	layout             LayoutContract | ||||
| 	itemsToConvert     convertor.ItemsToConvertContract | ||||
| 	progressBarService convertor.ProgressBarContract | ||||
| 	queueLayout        QueueLayoutContract | ||||
| } | ||||
|  | ||||
| func NewMainWindow( | ||||
| 	fyneWindow fyne.Window, | ||||
| 	progressBarService convertor.ProgressBarContract, | ||||
| 	itemsToConvert convertor.ItemsToConvertContract, | ||||
| 	queueLayout QueueLayoutContract, | ||||
| ) WindowContract { | ||||
| 	fyneWindow.Resize(fyne.Size{Width: 1039, Height: 599}) | ||||
| 	fyneWindow.CenterOnScreen() | ||||
|  | ||||
| 	return &mainWindow{ | ||||
| 		fyneWindow:         fyneWindow, | ||||
| 		progressBarService: progressBarService, | ||||
| 		itemsToConvert:     itemsToConvert, | ||||
| 		queueLayout:        queueLayout, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (w *mainWindow) SetMainMenu(menu *fyne.MainMenu) { | ||||
| 	fyne.Do(func() { | ||||
| 		w.fyneWindow.SetMainMenu(menu) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (w *mainWindow) InitLayout() { | ||||
| 	fyne.Do(func() { | ||||
| 		w.layout = NewLayout(w.progressBarService, w.itemsToConvert, w.queueLayout) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (w *mainWindow) GetLayout() LayoutContract { | ||||
| 	return w.layout | ||||
| } | ||||
|  | ||||
| func (w *mainWindow) NewFileOpen(callback func(fyne.URIReadCloser, error), location fyne.ListableURI) *dialog.FileDialog { | ||||
| 	fileDialog := dialog.NewFileOpen(callback, w.fyneWindow) | ||||
| 	utils.FileDialogResize(fileDialog, w.fyneWindow) | ||||
| 	fileDialog.Show() | ||||
| 	if location != nil { | ||||
| 		fileDialog.SetLocation(location) | ||||
| 	} | ||||
| 	return fileDialog | ||||
| } | ||||
|  | ||||
| func (w *mainWindow) NewFolderOpen(callback func(fyne.ListableURI, error), location fyne.ListableURI) *dialog.FileDialog { | ||||
| 	fileDialog := dialog.NewFolderOpen(callback, w.fyneWindow) | ||||
| 	utils.FileDialogResize(fileDialog, w.fyneWindow) | ||||
| 	fileDialog.Show() | ||||
| 	if location != nil { | ||||
| 		fileDialog.SetLocation(location) | ||||
| 	} | ||||
| 	return fileDialog | ||||
| } | ||||
|  | ||||
| func (w *mainWindow) SetContent(content fyne.CanvasObject) { | ||||
| 	fyne.Do(func() { | ||||
| 		if w.layout == nil { | ||||
| 			w.fyneWindow.SetContent(content) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		w.fyneWindow.SetContent(w.layout.SetContent(content)) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (w *mainWindow) Show() { | ||||
| 	w.fyneWindow.Show() | ||||
| } | ||||
|  | ||||
| func (w *mainWindow) SetOnDropped(callback func(position fyne.Position, uris []fyne.URI)) { | ||||
| 	fyne.Do(func() { | ||||
| 		w.fyneWindow.SetOnDropped(callback) | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										459
									
								
								internal/gui/window/queue.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										459
									
								
								internal/gui/window/queue.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,459 @@ | ||||
| package window | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/canvas" | ||||
| 	"fyne.io/fyne/v2/container" | ||||
| 	"fyne.io/fyne/v2/lang" | ||||
| 	"fyne.io/fyne/v2/theme" | ||||
| 	"fyne.io/fyne/v2/widget" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/convertor" | ||||
| 	"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg" | ||||
| 	"image/color" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type QueueLayoutContract interface { | ||||
| 	GetItemsContainer() *fyne.Container | ||||
| 	GetQueueStatistics() QueueStatisticsAllContract | ||||
|  | ||||
| 	AddQueue(key int, queue *convertor.Queue) | ||||
| 	ChangeQueue(key int, queue *convertor.Queue) | ||||
| 	RemoveQueue(key int, status convertor.StatusContract) | ||||
| } | ||||
|  | ||||
| type queueLayout struct { | ||||
| 	itemsContainer     *fyne.Container | ||||
| 	queueAllStatistics QueueStatisticsAllContract | ||||
| 	items              map[int]queueLayoutItem | ||||
| 	ffmpegService      ffmpeg.UtilitiesContract | ||||
| } | ||||
|  | ||||
| func NewQueueLayout(ffmpegService ffmpeg.UtilitiesContract) QueueLayoutContract { | ||||
| 	items := map[int]queueLayoutItem{} | ||||
|  | ||||
| 	return &queueLayout{ | ||||
| 		itemsContainer:     container.NewVBox(), | ||||
| 		queueAllStatistics: newQueueAllStatistics(&items), | ||||
| 		items:              items, | ||||
| 		ffmpegService:      ffmpegService, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (l *queueLayout) GetItemsContainer() *fyne.Container { | ||||
| 	return l.itemsContainer | ||||
| } | ||||
|  | ||||
| func (l *queueLayout) GetQueueStatistics() QueueStatisticsAllContract { | ||||
| 	return l.queueAllStatistics | ||||
| } | ||||
|  | ||||
| func (l *queueLayout) AddQueue(queueID int, queue *convertor.Queue) { | ||||
|  | ||||
| 	statusMessage := canvas.NewText(l.getStatusTitle(queue.Status), theme.Color(theme.ColorNamePrimary)) | ||||
| 	messageError := canvas.NewText("", theme.Color(theme.ColorNameError)) | ||||
| 	buttonPlay := widget.NewButtonWithIcon("", theme.Icon(theme.IconNameMediaPlay), func() { | ||||
|  | ||||
| 	}) | ||||
| 	buttonPlay.Hide() | ||||
| 	blockMessageError := container.NewHScroll(messageError) | ||||
| 	blockMessageError.Hide() | ||||
|  | ||||
| 	content := container.NewVBox( | ||||
| 		container.NewHScroll(widget.NewLabel(queue.Setting.FileInput.Name)), | ||||
| 		container.NewHBox( | ||||
| 			buttonPlay, | ||||
| 			statusMessage, | ||||
| 		), | ||||
| 		blockMessageError, | ||||
| 		container.NewPadded(), | ||||
| 		canvas.NewLine(theme.Color(theme.ColorNameFocus)), | ||||
| 		container.NewPadded(), | ||||
| 	) | ||||
|  | ||||
| 	l.addQueueStatistics() | ||||
| 	if l.GetQueueStatistics().IsChecked(queue.Status) == false { | ||||
| 		content.Hide() | ||||
| 	} | ||||
|  | ||||
| 	l.items[queueID] = queueLayoutItem{ | ||||
| 		CanvasObject:      content, | ||||
| 		StatusMessage:     statusMessage, | ||||
| 		BlockMessageError: blockMessageError, | ||||
| 		MessageError:      messageError, | ||||
| 		buttonPlay:        buttonPlay, | ||||
| 		status:            &queue.Status, | ||||
| 	} | ||||
| 	l.itemsContainer.Add(content) | ||||
| } | ||||
|  | ||||
| func (l *queueLayout) ChangeQueue(queueID int, queue *convertor.Queue) { | ||||
| 	if item, ok := l.items[queueID]; ok { | ||||
| 		statusColor := l.getStatusColor(queue.Status) | ||||
| 		fyne.Do(func() { | ||||
| 			item.StatusMessage.Text = l.getStatusTitle(queue.Status) | ||||
| 			item.StatusMessage.Color = statusColor | ||||
| 			item.StatusMessage.Refresh() | ||||
| 		}) | ||||
| 		if queue.Error != nil { | ||||
| 			fyne.Do(func() { | ||||
| 				item.MessageError.Text = queue.Error.Error() | ||||
| 				item.MessageError.Color = statusColor | ||||
| 				item.BlockMessageError.Show() | ||||
| 				item.MessageError.Refresh() | ||||
| 			}) | ||||
| 		} | ||||
| 		if queue.Status == convertor.StatusType(convertor.Completed) { | ||||
| 			item.buttonPlay.Show() | ||||
| 			item.buttonPlay.OnTapped = func() { | ||||
| 				item.buttonPlay.Disable() | ||||
| 				go func() { | ||||
| 					ffplay, err := l.ffmpegService.GetFFplay() | ||||
| 					if err == nil { | ||||
| 						_ = ffplay.Play(&queue.Setting.FileOut) | ||||
| 					} | ||||
| 					fyne.Do(func() { | ||||
| 						item.buttonPlay.Enable() | ||||
| 					}) | ||||
| 				}() | ||||
| 			} | ||||
| 		} | ||||
| 		if l.GetQueueStatistics().IsChecked(queue.Status) == false && item.CanvasObject.Visible() == true { | ||||
| 			item.CanvasObject.Hide() | ||||
| 		} | ||||
|  | ||||
| 		if l.GetQueueStatistics().IsChecked(queue.Status) == true && item.CanvasObject.Visible() == false { | ||||
| 			item.CanvasObject.Show() | ||||
| 		} | ||||
|  | ||||
| 		l.changeQueueStatistics(queue.Status) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (l *queueLayout) RemoveQueue(queueID int, status convertor.StatusContract) { | ||||
| 	if item, ok := l.items[queueID]; ok { | ||||
| 		l.itemsContainer.Remove(item.CanvasObject) | ||||
| 		l.removeQueueStatistics(status) | ||||
| 		l.items[queueID] = queueLayoutItem{} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (l *queueLayout) addQueueStatistics() { | ||||
| 	l.GetQueueStatistics().GetWaiting().Add() | ||||
| 	l.GetQueueStatistics().GetTotal().Add() | ||||
| } | ||||
|  | ||||
| func (l *queueLayout) changeQueueStatistics(status convertor.StatusContract) { | ||||
| 	if status == convertor.StatusType(convertor.InProgress) { | ||||
| 		l.GetQueueStatistics().GetWaiting().Remove() | ||||
| 		l.GetQueueStatistics().GetInProgress().Add() | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if status == convertor.StatusType(convertor.Completed) { | ||||
| 		l.GetQueueStatistics().GetInProgress().Remove() | ||||
| 		l.GetQueueStatistics().GetCompleted().Add() | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if status == convertor.StatusType(convertor.Error) { | ||||
| 		l.GetQueueStatistics().GetInProgress().Remove() | ||||
| 		l.GetQueueStatistics().GetError().Add() | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (l *queueLayout) removeQueueStatistics(status convertor.StatusContract) { | ||||
| 	l.GetQueueStatistics().GetTotal().Remove() | ||||
|  | ||||
| 	if status == convertor.StatusType(convertor.Completed) { | ||||
| 		l.GetQueueStatistics().GetCompleted().Remove() | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if status == convertor.StatusType(convertor.Error) { | ||||
| 		l.GetQueueStatistics().GetError().Remove() | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if status == convertor.StatusType(convertor.InProgress) { | ||||
| 		l.GetQueueStatistics().GetInProgress().Remove() | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if status == convertor.StatusType(convertor.Waiting) { | ||||
| 		l.GetQueueStatistics().GetWaiting().Remove() | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (l *queueLayout) getStatusTitle(status convertor.StatusContract) string { | ||||
| 	return lang.L(status.Name() + "Queue") | ||||
| } | ||||
|  | ||||
| func (l *queueLayout) getStatusColor(status convertor.StatusContract) color.Color { | ||||
| 	if status == convertor.StatusType(convertor.Error) { | ||||
| 		return theme.Color(theme.ColorNameError) | ||||
| 	} | ||||
|  | ||||
| 	if status == convertor.StatusType(convertor.Completed) { | ||||
| 		return color.RGBA{R: 49, G: 127, B: 114, A: 255} | ||||
| 	} | ||||
|  | ||||
| 	return theme.Color(theme.ColorNamePrimary) | ||||
| } | ||||
|  | ||||
| type QueueStatisticsAllContract interface { | ||||
| 	GetWaiting() QueueStatisticsContract | ||||
| 	GetInProgress() QueueStatisticsContract | ||||
| 	GetCompleted() QueueStatisticsContract | ||||
| 	GetError() QueueStatisticsContract | ||||
| 	GetTotal() QueueStatisticsContract | ||||
|  | ||||
| 	IsChecked(status convertor.StatusContract) bool | ||||
| } | ||||
|  | ||||
| type queueAllStatistics struct { | ||||
| 	waiting    QueueStatisticsContract | ||||
| 	inProgress QueueStatisticsContract | ||||
| 	completed  QueueStatisticsContract | ||||
| 	error      QueueStatisticsContract | ||||
| 	total      QueueStatisticsContract | ||||
| } | ||||
|  | ||||
| func newQueueAllStatistics(queueItems *map[int]queueLayoutItem) QueueStatisticsAllContract { | ||||
| 	checkboxWaiting := newQueueStatistics() | ||||
| 	checkboxInProgress := newQueueStatistics() | ||||
| 	checkboxCompleted := newQueueStatistics() | ||||
| 	checkboxError := newQueueStatistics() | ||||
| 	CheckboxTotal := newQueueStatistics() | ||||
|  | ||||
| 	queueAllStatistics := &queueAllStatistics{ | ||||
| 		waiting:    checkboxWaiting, | ||||
| 		inProgress: checkboxInProgress, | ||||
| 		completed:  checkboxCompleted, | ||||
| 		error:      checkboxError, | ||||
| 		total:      CheckboxTotal, | ||||
| 	} | ||||
|  | ||||
| 	CheckboxTotal.GetCheckbox().OnChanged = func(b bool) { | ||||
| 		if b == true { | ||||
| 			queueAllStatistics.allCheckboxChecked() | ||||
| 		} else { | ||||
| 			queueAllStatistics.allUnCheckboxChecked() | ||||
| 		} | ||||
| 		queueAllStatistics.redrawingQueueItems(queueItems) | ||||
| 	} | ||||
|  | ||||
| 	checkboxWaiting.GetCheckbox().OnChanged = func(b bool) { | ||||
| 		if b == true { | ||||
| 			queueAllStatistics.checkboxChecked() | ||||
| 		} else { | ||||
| 			queueAllStatistics.unCheckboxChecked() | ||||
| 		} | ||||
| 		queueAllStatistics.redrawingQueueItems(queueItems) | ||||
| 	} | ||||
|  | ||||
| 	checkboxInProgress.GetCheckbox().OnChanged = func(b bool) { | ||||
| 		if b == true { | ||||
| 			queueAllStatistics.checkboxChecked() | ||||
| 		} else { | ||||
| 			queueAllStatistics.unCheckboxChecked() | ||||
| 		} | ||||
| 		queueAllStatistics.redrawingQueueItems(queueItems) | ||||
| 	} | ||||
|  | ||||
| 	checkboxCompleted.GetCheckbox().OnChanged = func(b bool) { | ||||
| 		if b == true { | ||||
| 			queueAllStatistics.checkboxChecked() | ||||
| 		} else { | ||||
| 			queueAllStatistics.unCheckboxChecked() | ||||
| 		} | ||||
| 		queueAllStatistics.redrawingQueueItems(queueItems) | ||||
| 	} | ||||
|  | ||||
| 	checkboxError.GetCheckbox().OnChanged = func(b bool) { | ||||
| 		if b == true { | ||||
| 			queueAllStatistics.checkboxChecked() | ||||
| 		} else { | ||||
| 			queueAllStatistics.unCheckboxChecked() | ||||
| 		} | ||||
| 		queueAllStatistics.redrawingQueueItems(queueItems) | ||||
| 	} | ||||
|  | ||||
| 	return queueAllStatistics | ||||
| } | ||||
|  | ||||
| func (s *queueAllStatistics) GetWaiting() QueueStatisticsContract { | ||||
| 	return s.waiting | ||||
| } | ||||
|  | ||||
| func (s *queueAllStatistics) GetInProgress() QueueStatisticsContract { | ||||
| 	return s.inProgress | ||||
| } | ||||
|  | ||||
| func (s *queueAllStatistics) GetCompleted() QueueStatisticsContract { | ||||
| 	return s.completed | ||||
| } | ||||
|  | ||||
| func (s *queueAllStatistics) GetError() QueueStatisticsContract { | ||||
| 	return s.error | ||||
| } | ||||
|  | ||||
| func (s *queueAllStatistics) GetTotal() QueueStatisticsContract { | ||||
| 	return s.total | ||||
| } | ||||
|  | ||||
| func (s *queueAllStatistics) IsChecked(status convertor.StatusContract) bool { | ||||
| 	if status == convertor.StatusType(convertor.InProgress) { | ||||
| 		return s.inProgress.GetCheckbox().Checked | ||||
| 	} | ||||
| 	if status == convertor.StatusType(convertor.Completed) { | ||||
| 		return s.completed.GetCheckbox().Checked | ||||
| 	} | ||||
| 	if status == convertor.StatusType(convertor.Error) { | ||||
| 		return s.error.GetCheckbox().Checked | ||||
| 	} | ||||
| 	if status == convertor.StatusType(convertor.Waiting) { | ||||
| 		return s.waiting.GetCheckbox().Checked | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (s *queueAllStatistics) redrawingQueueItems(queueItems *map[int]queueLayoutItem) { | ||||
| 	for _, item := range *queueItems { | ||||
| 		if s.IsChecked(*item.status) == true && item.CanvasObject.Visible() == false { | ||||
| 			item.CanvasObject.Show() | ||||
| 			continue | ||||
| 		} | ||||
| 		if s.IsChecked(*item.status) == false && item.CanvasObject.Visible() == true { | ||||
| 			item.CanvasObject.Hide() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (s *queueAllStatistics) checkboxChecked() { | ||||
| 	if s.total.GetCheckbox().Checked == true { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if s.waiting.GetCheckbox().Checked == false { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if s.inProgress.GetCheckbox().Checked == false { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if s.completed.GetCheckbox().Checked == false { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if s.error.GetCheckbox().Checked == false { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	s.total.GetCheckbox().Checked = true | ||||
| 	s.total.GetCheckbox().Refresh() | ||||
| } | ||||
|  | ||||
| func (s *queueAllStatistics) unCheckboxChecked() { | ||||
| 	if s.total.GetCheckbox().Checked == false { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	s.total.GetCheckbox().Checked = false | ||||
| 	s.total.GetCheckbox().Refresh() | ||||
| } | ||||
|  | ||||
| func (s *queueAllStatistics) allCheckboxChecked() { | ||||
| 	s.waiting.GetCheckbox().Checked = true | ||||
| 	s.waiting.GetCheckbox().Refresh() | ||||
|  | ||||
| 	s.inProgress.GetCheckbox().Checked = true | ||||
| 	s.inProgress.GetCheckbox().Refresh() | ||||
|  | ||||
| 	s.completed.GetCheckbox().Checked = true | ||||
| 	s.completed.GetCheckbox().Refresh() | ||||
|  | ||||
| 	s.error.GetCheckbox().Checked = true | ||||
| 	s.error.GetCheckbox().Refresh() | ||||
| } | ||||
|  | ||||
| func (s *queueAllStatistics) allUnCheckboxChecked() { | ||||
| 	s.waiting.GetCheckbox().Checked = false | ||||
| 	s.waiting.GetCheckbox().Refresh() | ||||
|  | ||||
| 	s.inProgress.GetCheckbox().Checked = false | ||||
| 	s.inProgress.GetCheckbox().Refresh() | ||||
|  | ||||
| 	s.completed.GetCheckbox().Checked = false | ||||
| 	s.completed.GetCheckbox().Refresh() | ||||
|  | ||||
| 	s.error.GetCheckbox().Checked = false | ||||
| 	s.error.GetCheckbox().Refresh() | ||||
| } | ||||
|  | ||||
| type QueueStatisticsContract interface { | ||||
| 	SetTitle(title string) | ||||
| 	GetCheckbox() *widget.Check | ||||
| 	Add() | ||||
| 	Remove() | ||||
| } | ||||
|  | ||||
| type queueStatistics struct { | ||||
| 	checkbox *widget.Check | ||||
| 	title    string | ||||
| 	count    int64 | ||||
| } | ||||
|  | ||||
| func newQueueStatistics() QueueStatisticsContract { | ||||
| 	checkbox := widget.NewCheck(": 0", nil) | ||||
| 	checkbox.Checked = true | ||||
|  | ||||
| 	return &queueStatistics{ | ||||
| 		checkbox: checkbox, | ||||
| 		title:    "", | ||||
| 		count:    0, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (s *queueStatistics) SetTitle(title string) { | ||||
| 	s.title = strings.ToLower(title) | ||||
| 	s.checkbox.Text = title + ": " + strconv.FormatInt(s.count, 10) | ||||
| } | ||||
|  | ||||
| func (s *queueStatistics) GetCheckbox() *widget.Check { | ||||
| 	return s.checkbox | ||||
| } | ||||
|  | ||||
| func (s *queueStatistics) Add() { | ||||
| 	s.count += 1 | ||||
| 	s.formatText() | ||||
| } | ||||
|  | ||||
| func (s *queueStatistics) Remove() { | ||||
| 	if s.count == 0 { | ||||
| 		return | ||||
| 	} | ||||
| 	s.count -= 1 | ||||
| 	s.formatText() | ||||
| } | ||||
|  | ||||
| func (s *queueStatistics) formatText() { | ||||
| 	fyne.Do(func() { | ||||
| 		s.checkbox.Text = s.title + ": " + strconv.FormatInt(s.count, 10) | ||||
| 		s.checkbox.Refresh() | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| type queueLayoutItem struct { | ||||
| 	CanvasObject      fyne.CanvasObject | ||||
| 	BlockMessageError *container.Scroll | ||||
| 	StatusMessage     *canvas.Text | ||||
| 	MessageError      *canvas.Text | ||||
| 	buttonPlay        *widget.Button | ||||
| 	status            *convertor.StatusContract | ||||
| } | ||||
							
								
								
									
										13
									
								
								internal/resources/icon.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								internal/resources/icon.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| package resources | ||||
|  | ||||
| import ( | ||||
| 	_ "embed" | ||||
| 	"fyne.io/fyne/v2" | ||||
| ) | ||||
|  | ||||
| //go:embed icons/logo.png | ||||
| var iconAppLogo []byte | ||||
|  | ||||
| func IconAppLogoResource() *fyne.StaticResource { | ||||
| 	return fyne.NewStaticResource("icon.png", iconAppLogo) | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								internal/resources/icons/logo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								internal/resources/icons/logo.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 29 KiB | 
							
								
								
									
										12
									
								
								internal/resources/translation.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								internal/resources/translation.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| package resources | ||||
|  | ||||
| import ( | ||||
| 	"embed" | ||||
| ) | ||||
|  | ||||
| //go:embed translations | ||||
| var translations embed.FS | ||||
|  | ||||
| func GetTranslations() embed.FS { | ||||
| 	return translations | ||||
| } | ||||
							
								
								
									
										143
									
								
								internal/resources/translations/app.en.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								internal/resources/translations/app.en.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| { | ||||
|   "AlsoUsedProgram": "The program also uses:", | ||||
|   "about": "About", | ||||
|   "aboutText": "A simple interface for the FFmpeg console utility. \nBut I am not the author of the FFmpeg utility itself.", | ||||
|   "addedFilesTitle": "Added files", | ||||
|   "autoClearAfterAddingToQueue": "Auto-clear after adding to queue", | ||||
|   "buttonDownloadFFmpeg": "Download FFmpeg automatically", | ||||
|   "buttonForSelectedDirTitle": "Save to folder:", | ||||
|   "cancel": "Cancel", | ||||
|   "changeFFPath": "FFmpeg, FFprobe and FFplay", | ||||
|   "changeLanguage": "Change language", | ||||
|   "checkboxOverwriteOutputFilesTitle": "Allow file to be overwritten", | ||||
|   "choose": "choose", | ||||
|   "clearAll": "Clear List", | ||||
|   "completedQueue": "Completed", | ||||
|   "converterVideoFilesSubmitTitle": "Convert", | ||||
|   "converterVideoFilesTitle": "Video, audio and picture converter", | ||||
|   "download": "Download", | ||||
|   "downloadFFmpegFromSite": "Will be downloaded from the site:", | ||||
|   "downloadRun": "Downloading...", | ||||
|   "dragAndDropFiles": "drag and drop files", | ||||
|   "encoderGroupAudio": "Audio", | ||||
|   "encoderGroupImage": "Images", | ||||
|   "encoderGroupVideo": "Video", | ||||
|   "encoder_apng": "APNG image", | ||||
|   "encoder_bmp": "BMP image", | ||||
|   "encoder_flv": "FLV", | ||||
|   "encoder_gif": "GIF image", | ||||
|   "encoder_h264_nvenc": "H.264 with NVIDIA support", | ||||
|   "encoder_libmp3lame": "libmp3lame MP3 (MPEG audio layer 3)", | ||||
|   "encoder_libshine": "libshine MP3 (MPEG audio layer 3)", | ||||
|   "encoder_libtwolame": "libtwolame MP2 (MPEG audio layer 2)", | ||||
|   "encoder_libvpx": "libvpx VP8 (codec vp8)", | ||||
|   "encoder_libvpx-vp9": "libvpx VP9 (codec vp9)", | ||||
|   "encoder_libwebp": "libwebp WebP image", | ||||
|   "encoder_libwebp_anim": "libwebp_anim WebP image", | ||||
|   "encoder_libx264": "H.264 libx264", | ||||
|   "encoder_libx265": "H.265 libx265", | ||||
|   "encoder_libxvid": "libxvidcore MPEG-4 part 2", | ||||
|   "encoder_mjpeg": "MJPEG (Motion JPEG)", | ||||
|   "encoder_mp2": "MP2 (MPEG audio layer 2)", | ||||
|   "encoder_mp2fixed": "MP2 fixed point (MPEG audio layer 2)", | ||||
|   "encoder_mpeg1video": "MPEG-1", | ||||
|   "encoder_mpeg2video": "MPEG-2", | ||||
|   "encoder_mpeg4": "MPEG-4 part 2", | ||||
|   "encoder_msmpeg4": "MPEG-4 part 2 Microsoft variant version 3", | ||||
|   "encoder_msmpeg4v2": "MPEG-4 part 2 Microsoft variant version 2", | ||||
|   "encoder_msvideo1": "Microsoft Video-1", | ||||
|   "encoder_png": "PNG image", | ||||
|   "encoder_qtrle": "QuickTime Animation (RLE) video", | ||||
|   "encoder_sgi": "SGI image", | ||||
|   "encoder_tiff": "TIFF image", | ||||
|   "encoder_wmav1": "Windows Media Audio 1", | ||||
|   "encoder_wmav2": "Windows Media Audio 2", | ||||
|   "encoder_wmv1": "Windows Media Video 7", | ||||
|   "encoder_wmv2": "Windows Media Video 8", | ||||
|   "encoder_xbm": "XBM (X BitMap) image", | ||||
|   "error": "An error has occurred!", | ||||
|   "errorConverter": "Couldn't convert video", | ||||
|   "errorDragAndDropFile": "Not all files were added", | ||||
|   "errorFFmpeg": "this is not FFmpeg", | ||||
|   "errorFFmpegVersion": "Could not determine FFmpeg version", | ||||
|   "errorFFplay": "this is not FFplay", | ||||
|   "errorFFplayVersion": "Could not determine FFplay version", | ||||
|   "errorFFprobe": "this is not FFprobe", | ||||
|   "errorFFprobeVersion": "Failed to determine FFprobe version", | ||||
|   "errorNoFilesAddedForConversion": "There are no files to convert", | ||||
|   "errorQueue": "Error", | ||||
|   "errorSelectedEncoder": "Converter not selected", | ||||
|   "errorSelectedFolderSave": "No save folder selected!", | ||||
|   "errorSelectedFormat": "File extension not selected", | ||||
|   "exit": "Exit", | ||||
|   "ffmpegLGPL": "This software uses libraries from the **FFmpeg** project under the **[LGPLv2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)**.", | ||||
|   "ffmpegTrademark": "**FFmpeg** is a trademark of **[Fabrice Bellard](http://bellard.org/)**, originator of the **[FFmpeg](https://ffmpeg.org/about.html)** project.", | ||||
|   "fileForConversionTitle": "File:", | ||||
|   "fileQueueTitle": "Queue", | ||||
|   "formPreset": "Preset", | ||||
|   "gratitude": "Gratitude", | ||||
|   "gratitudeText": "I sincerely thank you for your invaluable\n\r and timely assistance:", | ||||
|   "help": "Help", | ||||
|   "helpFFplay": "FFplay Player Keys", | ||||
|   "helpFFplayActivateFrameStepMode": "Activate frame-by-frame mode.", | ||||
|   "helpFFplayCycleVideoFiltersOrShowModes": "A cycle of video filters or display modes.", | ||||
|   "helpFFplayDecreaseVolume": "Decrease the volume.", | ||||
|   "helpFFplayDescription": "Description", | ||||
|   "helpFFplayDoubleClickLeftMouseButton": "double click\nleft mouse button", | ||||
|   "helpFFplayIncreaseVolume": "Increase the volume.", | ||||
|   "helpFFplayKeyDown": "down", | ||||
|   "helpFFplayKeyHoldS": "hold S", | ||||
|   "helpFFplayKeyLeft": "left", | ||||
|   "helpFFplayKeyRight": "right", | ||||
|   "helpFFplayKeySpace": "SPACE", | ||||
|   "helpFFplayKeyUp": "up", | ||||
|   "helpFFplayKeys": "Keys", | ||||
|   "helpFFplayPause": "Pause or continue playing.", | ||||
|   "helpFFplayQuit": "Close the player.", | ||||
|   "helpFFplaySeekBForward10Minutes": "Fast forward 10 minutes.", | ||||
|   "helpFFplaySeekBForward1Minute": "Fast forward 1 minute.", | ||||
|   "helpFFplaySeekBackward10Minutes": "Rewind 10 minutes.", | ||||
|   "helpFFplaySeekBackward10Seconds": "Rewind 10 seconds.", | ||||
|   "helpFFplaySeekBackward1Minute": "Rewind 1 minute.", | ||||
|   "helpFFplaySeekForward10Seconds": "Fast forward 10 seconds.", | ||||
|   "helpFFplayToggleFullScreen": "Switch to full screen or exit full screen.", | ||||
|   "helpFFplayToggleMute": "Mute or unmute.", | ||||
|   "inProgressQueue": "In Progress", | ||||
|   "languageSelectionFormHead": "Switch language", | ||||
|   "languageSelectionHead": "Choose language", | ||||
|   "licenseLink": "License information", | ||||
|   "licenseLinkOther": "Licenses from other products used in the program", | ||||
|   "menuSettingsLanguage": "Language", | ||||
|   "menuSettingsTheme": "Theme", | ||||
|   "or": "or", | ||||
|   "parameterCheckbox": "Enable option", | ||||
|   "pathToFfmpeg": "Path to FFmpeg:", | ||||
|   "pathToFfplay": "Path to FFplay:", | ||||
|   "pathToFfprobe": "Path to FFprobe:", | ||||
|   "preset_fast": "fast (slower than \"faster\", but the file will weigh less)", | ||||
|   "preset_faster": "faster (slower than \"veryfast\", but the file will weigh less)", | ||||
|   "preset_medium": "medium (slower than \"fast\", but the file will weigh less)", | ||||
|   "preset_placebo": "placebo (not recommended)", | ||||
|   "preset_slow": "slow (slower than \"medium\", but the file will weigh less)", | ||||
|   "preset_slower": "slower (slower than \"slow\", but the file will weigh less)", | ||||
|   "preset_superfast": "superfast (slower than \"ultrafast\", but the file will weigh less)", | ||||
|   "preset_ultrafast": "ultrafast (fast, but the file will weigh a lot)", | ||||
|   "preset_veryfast": "veryfast (slower than \"superfast\", but the file will weigh less)", | ||||
|   "preset_veryslow": "veryslow (slower than \"slower\", but the file will weigh less)", | ||||
|   "programmLink": "Project website", | ||||
|   "programmVersion": "**Program version:** {{.Version}}", | ||||
|   "queue": "Queue", | ||||
|   "save": "Save", | ||||
|   "selectEncoder": "Encoder:", | ||||
|   "selectFFPathTitle": "Specify the path to FFmpeg and FFprobe", | ||||
|   "selectFormat": "File extension:", | ||||
|   "settings": "Settings", | ||||
|   "testFF": "Checking FFmpeg for serviceability...", | ||||
|   "themesNameDark": "Dark", | ||||
|   "themesNameDefault": "Default", | ||||
|   "themesNameLight": "Light", | ||||
|   "titleDownloadLink": "You can download it from here", | ||||
|   "total": "Total", | ||||
|   "unzipRun": "Unpacked...", | ||||
|   "waitingQueue": "Waiting" | ||||
| } | ||||
							
								
								
									
										143
									
								
								internal/resources/translations/app.kk.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								internal/resources/translations/app.kk.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| { | ||||
|   "AlsoUsedProgram": "Бағдарлама сонымен қатар пайдаланады:", | ||||
|   "about": "Бағдарлама туралы", | ||||
|   "aboutText": "FFmpeg консоль утилитасы үшін қарапайым интерфейс. \nБірақ мен FFmpeg утилитасының авторы емеспін.", | ||||
|   "addedFilesTitle": "Қосылған файлдар", | ||||
|   "autoClearAfterAddingToQueue": "Кезекке қосқаннан кейін тазалаңыз", | ||||
|   "buttonDownloadFFmpeg": "FFmpeg автоматты түрде жүктеп алыңыз", | ||||
|   "buttonForSelectedDirTitle": "Қалтаға сақтаңыз:", | ||||
|   "cancel": "Болдырмау", | ||||
|   "changeFFPath": "FFmpeg, FFprobe және FFplay", | ||||
|   "changeLanguage": "Тілді өзгерту", | ||||
|   "checkboxOverwriteOutputFilesTitle": "Файлды қайта жазуға рұқсат беріңіз", | ||||
|   "choose": "таңдау", | ||||
|   "clearAll": "Тізімді өшіру", | ||||
|   "completedQueue": "Дайын", | ||||
|   "converterVideoFilesSubmitTitle": "Файлды түрлендіру", | ||||
|   "converterVideoFilesTitle": "Бейне, аудио және суретті түрлендіргіш", | ||||
|   "download": "Жүктеп алу", | ||||
|   "downloadFFmpegFromSite": "Сайттан жүктеледі:", | ||||
|   "downloadRun": "Жүктеп алынуда...", | ||||
|   "dragAndDropFiles": "файлдарды сүйреп апарыңыз", | ||||
|   "encoderGroupAudio": "Аудио", | ||||
|   "encoderGroupImage": "Суреттер", | ||||
|   "encoderGroupVideo": "Бейне", | ||||
|   "encoder_apng": "APNG image", | ||||
|   "encoder_bmp": "BMP image", | ||||
|   "encoder_flv": "FLV", | ||||
|   "encoder_gif": "GIF image", | ||||
|   "encoder_h264_nvenc": "NVIDIA қолдауымен H.264", | ||||
|   "encoder_libmp3lame": "libmp3lame MP3 (MPEG audio layer 3)", | ||||
|   "encoder_libshine": "libshine MP3 (MPEG audio layer 3)", | ||||
|   "encoder_libtwolame": "libtwolame MP2 (MPEG audio layer 2)", | ||||
|   "encoder_libvpx": "libvpx VP8 (codec vp8)", | ||||
|   "encoder_libvpx-vp9": "libvpx VP9 (codec vp9)", | ||||
|   "encoder_libwebp": "libwebp WebP image", | ||||
|   "encoder_libwebp_anim": "libwebp_anim WebP image", | ||||
|   "encoder_libx264": "H.264 libx264", | ||||
|   "encoder_libx265": "H.265 libx265", | ||||
|   "encoder_libxvid": "libxvidcore MPEG-4 part 2", | ||||
|   "encoder_mjpeg": "MJPEG (Motion JPEG)", | ||||
|   "encoder_mp2": "MP2 (MPEG audio layer 2)", | ||||
|   "encoder_mp2fixed": "MP2 fixed point (MPEG audio layer 2)", | ||||
|   "encoder_mpeg1video": "MPEG-1", | ||||
|   "encoder_mpeg2video": "MPEG-2", | ||||
|   "encoder_mpeg4": "MPEG-4 part 2", | ||||
|   "encoder_msmpeg4": "MPEG-4 part 2 Microsoft variant version 3", | ||||
|   "encoder_msmpeg4v2": "MPEG-4 part 2 Microsoft variant version 2", | ||||
|   "encoder_msvideo1": "Microsoft Video-1", | ||||
|   "encoder_png": "PNG image", | ||||
|   "encoder_qtrle": "QuickTime Animation (RLE) video", | ||||
|   "encoder_sgi": "SGI image", | ||||
|   "encoder_tiff": "TIFF image", | ||||
|   "encoder_wmav1": "Windows Media Audio 1", | ||||
|   "encoder_wmav2": "Windows Media Audio 2", | ||||
|   "encoder_wmv1": "Windows Media Video 7", | ||||
|   "encoder_wmv2": "Windows Media Video 8", | ||||
|   "encoder_xbm": "XBM (X BitMap) image", | ||||
|   "error": "Қате орын алды!", | ||||
|   "errorConverter": "Бейнені түрлендіру мүмкін болмады", | ||||
|   "errorDragAndDropFile": "Барлық файлдар қосылмаған", | ||||
|   "errorFFmpeg": "бұл FFmpeg емес", | ||||
|   "errorFFmpegVersion": "FFmpeg нұсқасын анықтау мүмкін болмады", | ||||
|   "errorFFplay": "бұл FFplay емес", | ||||
|   "errorFFplayVersion": "FFplay нұсқасын анықтау мүмкін болмады", | ||||
|   "errorFFprobe": "бұл FFprobe емес", | ||||
|   "errorFFprobeVersion": "FFprobe нұсқасын анықтау мүмкін болмады", | ||||
|   "errorNoFilesAddedForConversion": "Түрлендіруге арналған файлдар жоқ", | ||||
|   "errorQueue": "Қате", | ||||
|   "errorSelectedEncoder": "Түрлендіргіш таңдалмаған", | ||||
|   "errorSelectedFolderSave": "Сақтау қалтасы таңдалмаған!", | ||||
|   "errorSelectedFormat": "Файл кеңейтімі таңдалмаған", | ||||
|   "exit": "Шығу", | ||||
|   "ffmpegLGPL": "Бұл бағдарламалық құрал **[LGPLv2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)** астында **FFmpeg** жобасының кітапханаларын пайдаланады.", | ||||
|   "ffmpegTrademark": "FFmpeg — **[FFmpeg](https://ffmpeg.org/about.html)** жобасын жасаушы **[Fabrice Bellard](http://bellard.org/)** сауда белгісі.", | ||||
|   "fileForConversionTitle": "Файл:", | ||||
|   "fileQueueTitle": "Кезек", | ||||
|   "formPreset": "Алдын ала орнатылған", | ||||
|   "gratitude": "Алғыс", | ||||
|   "gratitudeText": "Сізге баға жетпес және уақтылы көмектескеніңіз\n\r үшін шын жүректен алғыс айтамын:", | ||||
|   "help": "Анықтама", | ||||
|   "helpFFplay": "FFplay ойнатқышының пернелері", | ||||
|   "helpFFplayActivateFrameStepMode": "Уақыт аралығын іске қосыңыз.", | ||||
|   "helpFFplayCycleVideoFiltersOrShowModes": "Бейне сүзгілерінің немесе дисплей режимдерінің циклі.", | ||||
|   "helpFFplayDecreaseVolume": "Дыбыс деңгейін төмендетіңіз.", | ||||
|   "helpFFplayDescription": "Сипаттама", | ||||
|   "helpFFplayDoubleClickLeftMouseButton": "тінтуірдің сол жақ\nбатырмасын екі рет басу", | ||||
|   "helpFFplayIncreaseVolume": "Дыбыс деңгейін арттыру.", | ||||
|   "helpFFplayKeyDown": "төмен", | ||||
|   "helpFFplayKeyHoldS": "ұстау S", | ||||
|   "helpFFplayKeyLeft": "сол", | ||||
|   "helpFFplayKeyRight": "құқық", | ||||
|   "helpFFplayKeySpace": "SPACE (пробел)", | ||||
|   "helpFFplayKeyUp": "жоғары", | ||||
|   "helpFFplayKeys": "Кілттер", | ||||
|   "helpFFplayPause": "Кідіртіңіз немесе жоғалтуды жалғастырыңыз.", | ||||
|   "helpFFplayQuit": "Ойнатқышты жабыңыз.", | ||||
|   "helpFFplaySeekBForward10Minutes": "10 минутқа алға айналдырыңыз.", | ||||
|   "helpFFplaySeekBForward1Minute": "1 минутқа алға айналдырыңыз.", | ||||
|   "helpFFplaySeekBackward10Minutes": "10 минутқа артқа айналдырыңыз.", | ||||
|   "helpFFplaySeekBackward10Seconds": "10 секундқа артқа айналдырыңыз.", | ||||
|   "helpFFplaySeekBackward1Minute": "1 минутқа артқа айналдырыңыз.", | ||||
|   "helpFFplaySeekForward10Seconds": "10 секунд алға айналдырыңыз.", | ||||
|   "helpFFplayToggleFullScreen": "Толық экранға ауысу немесе толық экраннан шығу.", | ||||
|   "helpFFplayToggleMute": "Дыбысты өшіріңіз немесе дыбысты қосыңыз.", | ||||
|   "inProgressQueue": "Орындалуда", | ||||
|   "languageSelectionFormHead": "Тілді ауыстыру", | ||||
|   "languageSelectionHead": "Тілді таңдаңыз", | ||||
|   "licenseLink": "Лицензия туралы ақпарат", | ||||
|   "licenseLinkOther": "Бағдарламада пайдаланылатын басқа өнімдердің лицензиялары", | ||||
|   "menuSettingsLanguage": "Тіл", | ||||
|   "menuSettingsTheme": "Тақырып", | ||||
|   "or": "немесе", | ||||
|   "parameterCheckbox": "Опцияны қосу", | ||||
|   "pathToFfmpeg": "FFmpeg жол:", | ||||
|   "pathToFfplay": "FFplay жол:", | ||||
|   "pathToFfprobe": "FFprobe жол:", | ||||
|   "preset_fast": "fast («faster» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)", | ||||
|   "preset_faster": "faster («veryfast» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)", | ||||
|   "preset_medium": "medium («fast» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)", | ||||
|   "preset_placebo": "placebo (ұсынылмайды)", | ||||
|   "preset_slow": "slow («medium» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)", | ||||
|   "preset_slower": "slower («slow» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)", | ||||
|   "preset_superfast": "superfast («ultrafast» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)", | ||||
|   "preset_ultrafast": "ultrafast (жылдам, бірақ файлдың салмағы көп болады)", | ||||
|   "preset_veryfast": "veryfast («superfast» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)", | ||||
|   "preset_veryslow": "veryslow («slower» қарағанда баяуырақ, бірақ файлдың салмағы аз болады)", | ||||
|   "programmLink": "Жобаның веб-сайты", | ||||
|   "programmVersion": "**Бағдарлама нұсқасы:** {{.Version}}", | ||||
|   "queue": "Кезек", | ||||
|   "save": "Сақтау", | ||||
|   "selectEncoder": "Кодировщик:", | ||||
|   "selectFFPathTitle": "FFmpeg және FFprobe жолын көрсетіңіз", | ||||
|   "selectFormat": "Файл кеңейтімі:", | ||||
|   "settings": "Параметрлер", | ||||
|   "testFF": "FFmpeg функционалдығы тексерілуде...", | ||||
|   "themesNameDark": "Қараңғы тақырып", | ||||
|   "themesNameDefault": "Әдепкі бойынша", | ||||
|   "themesNameLight": "Жеңіл тақырып", | ||||
|   "titleDownloadLink": "Сіз оны осы жерден жүктей аласыз", | ||||
|   "total": "Барлығы", | ||||
|   "unzipRun": "Орамнан шығарылуда...", | ||||
|   "waitingQueue": "Күту" | ||||
| } | ||||
							
								
								
									
										143
									
								
								internal/resources/translations/app.ru.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								internal/resources/translations/app.ru.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| { | ||||
|   "AlsoUsedProgram": "Также в программе используется:", | ||||
|   "about": "О программе", | ||||
|   "aboutText": "Простенький интерфейс для консольной утилиты FFmpeg. \nНо я не являюсь автором самой утилиты FFmpeg.", | ||||
|   "addedFilesTitle": "Добавленные файлы", | ||||
|   "autoClearAfterAddingToQueue": "Очищать после добавления в очередь", | ||||
|   "buttonDownloadFFmpeg": "Скачать автоматически FFmpeg", | ||||
|   "buttonForSelectedDirTitle": "Сохранить в папку:", | ||||
|   "cancel": "Отмена", | ||||
|   "changeFFPath": "FFmpeg, FFprobe и FFplay", | ||||
|   "changeLanguage": "Поменять язык", | ||||
|   "checkboxOverwriteOutputFilesTitle": "Разрешить перезаписать файл", | ||||
|   "choose": "выбрать", | ||||
|   "clearAll": "Очистить список", | ||||
|   "completedQueue": "Готово", | ||||
|   "converterVideoFilesSubmitTitle": "Конвертировать", | ||||
|   "converterVideoFilesTitle": "Конвертер видео, аудио и картинок", | ||||
|   "download": "Скачать", | ||||
|   "downloadFFmpegFromSite": "Будет скачано с сайта:", | ||||
|   "downloadRun": "Скачивается...", | ||||
|   "dragAndDropFiles": "перетащить файлы", | ||||
|   "encoderGroupAudio": "Аудио", | ||||
|   "encoderGroupImage": "Картинки", | ||||
|   "encoderGroupVideo": "Видео", | ||||
|   "encoder_apng": "APNG image", | ||||
|   "encoder_bmp": "BMP image", | ||||
|   "encoder_flv": "FLV", | ||||
|   "encoder_gif": "GIF image", | ||||
|   "encoder_h264_nvenc": "H.264 с поддержкой NVIDIA", | ||||
|   "encoder_libmp3lame": "libmp3lame MP3 (MPEG audio layer 3)", | ||||
|   "encoder_libshine": "libshine MP3 (MPEG audio layer 3)", | ||||
|   "encoder_libtwolame": "libtwolame MP2 (MPEG audio layer 2)", | ||||
|   "encoder_libvpx": "libvpx VP8 (codec vp8)", | ||||
|   "encoder_libvpx-vp9": "libvpx VP9 (codec vp9)", | ||||
|   "encoder_libwebp": "libwebp WebP image", | ||||
|   "encoder_libwebp_anim": "libwebp_anim WebP image", | ||||
|   "encoder_libx264": "H.264 libx264", | ||||
|   "encoder_libx265": "H.265 libx265", | ||||
|   "encoder_libxvid": "libxvidcore MPEG-4 part 2", | ||||
|   "encoder_mjpeg": "MJPEG (Motion JPEG)", | ||||
|   "encoder_mp2": "MP2 (MPEG audio layer 2)", | ||||
|   "encoder_mp2fixed": "MP2 fixed point (MPEG audio layer 2)", | ||||
|   "encoder_mpeg1video": "MPEG-1", | ||||
|   "encoder_mpeg2video": "MPEG-2", | ||||
|   "encoder_mpeg4": "MPEG-4 part 2", | ||||
|   "encoder_msmpeg4": "MPEG-4 part 2 Microsoft variant version 3", | ||||
|   "encoder_msmpeg4v2": "MPEG-4 part 2 Microsoft variant version 2", | ||||
|   "encoder_msvideo1": "Microsoft Video-1", | ||||
|   "encoder_png": "PNG image", | ||||
|   "encoder_qtrle": "QuickTime Animation (RLE) video", | ||||
|   "encoder_sgi": "SGI image", | ||||
|   "encoder_tiff": "TIFF image", | ||||
|   "encoder_wmav1": "Windows Media Audio 1", | ||||
|   "encoder_wmav2": "Windows Media Audio 2", | ||||
|   "encoder_wmv1": "Windows Media Video 7", | ||||
|   "encoder_wmv2": "Windows Media Video 8", | ||||
|   "encoder_xbm": "XBM (X BitMap) image", | ||||
|   "error": "Произошла ошибка!", | ||||
|   "errorConverter": "не смогли отконвертировать видео", | ||||
|   "errorDragAndDropFile": "Не все файлы добавились", | ||||
|   "errorFFmpeg": "это не FFmpeg", | ||||
|   "errorFFmpegVersion": "Не смогли определить версию FFmpeg", | ||||
|   "errorFFplay": "это не FFplay", | ||||
|   "errorFFplayVersion": "Не смогли определить версию FFplay", | ||||
|   "errorFFprobe": "это не FFprobe", | ||||
|   "errorFFprobeVersion": "Не смогли определить версию FFprobe", | ||||
|   "errorNoFilesAddedForConversion": "Нет файлов для конвертации", | ||||
|   "errorQueue": "Ошибка", | ||||
|   "errorSelectedEncoder": "Конвертер не выбран", | ||||
|   "errorSelectedFolderSave": "Папка для сохранения не выбрана!", | ||||
|   "errorSelectedFormat": "Расширение файла не выбрана", | ||||
|   "exit": "Выход", | ||||
|   "ffmpegLGPL": "Это программное обеспечение использует библиотеки из проекта **FFmpeg** под **[LGPLv2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)**.", | ||||
|   "ffmpegTrademark": "**FFmpeg** — торговая марка **[Fabrice Bellard](http://bellard.org/)** , создателя проекта **[FFmpeg](https://ffmpeg.org/about.html)**.", | ||||
|   "fileForConversionTitle": "Файл:", | ||||
|   "fileQueueTitle": "Очередь", | ||||
|   "formPreset": "Предустановка", | ||||
|   "gratitude": "Благодарность", | ||||
|   "gratitudeText": "Я искренне благодарю вас за неоценимую\n\rи своевременную помощь:", | ||||
|   "help": "Справка", | ||||
|   "helpFFplay": "Клавиши проигрывателя FFplay", | ||||
|   "helpFFplayActivateFrameStepMode": "Активировать покадровый режим.", | ||||
|   "helpFFplayCycleVideoFiltersOrShowModes": "Цикл видеофильтров или режимов показа.", | ||||
|   "helpFFplayDecreaseVolume": "Уменьшить громкость.", | ||||
|   "helpFFplayDescription": "Описание", | ||||
|   "helpFFplayDoubleClickLeftMouseButton": "двойной щелчок\nлевой кнопкой мыши", | ||||
|   "helpFFplayIncreaseVolume": "Увеличить громкость.", | ||||
|   "helpFFplayKeyDown": "вниз", | ||||
|   "helpFFplayKeyHoldS": "держать S", | ||||
|   "helpFFplayKeyLeft": "лево", | ||||
|   "helpFFplayKeyRight": "право", | ||||
|   "helpFFplayKeySpace": "SPACE (пробел)", | ||||
|   "helpFFplayKeyUp": "вверх", | ||||
|   "helpFFplayKeys": "Клавиши", | ||||
|   "helpFFplayPause": "Поставить на паузу или продолжить проигрывать.", | ||||
|   "helpFFplayQuit": "Закрыть проигрыватель.", | ||||
|   "helpFFplaySeekBForward10Minutes": "Перемотать вперёд на 10 минут.", | ||||
|   "helpFFplaySeekBForward1Minute": "Перемотать вперёд на 1 минуту.", | ||||
|   "helpFFplaySeekBackward10Minutes": "Перемотать назад на 10 минут.", | ||||
|   "helpFFplaySeekBackward10Seconds": "Перемотать назад на 10 секунд.", | ||||
|   "helpFFplaySeekBackward1Minute": "Перемотать назад на 1 минуту.", | ||||
|   "helpFFplaySeekForward10Seconds": "Перемотать вперёд на 10 секунд.", | ||||
|   "helpFFplayToggleFullScreen": "Переключиться на полный экран или выйти с полного экрана.", | ||||
|   "helpFFplayToggleMute": "Отключить звук или включить звук.", | ||||
|   "inProgressQueue": "Выполняется", | ||||
|   "languageSelectionFormHead": "Переключить язык", | ||||
|   "languageSelectionHead": "Выберите язык", | ||||
|   "licenseLink": "Сведения о лицензии", | ||||
|   "licenseLinkOther": "Лицензии от других продуктов, которые используются в программе", | ||||
|   "menuSettingsLanguage": "Язык", | ||||
|   "menuSettingsTheme": "Тема", | ||||
|   "or": "или", | ||||
|   "parameterCheckbox": "Включить параметр", | ||||
|   "pathToFfmpeg": "Путь к FFmpeg:", | ||||
|   "pathToFfplay": "Путь к FFplay:", | ||||
|   "pathToFfprobe": "Путь к FFprobe:", | ||||
|   "preset_fast": "fast (медленней чем faster, но будет файл и меньше весить)", | ||||
|   "preset_faster": "faster (медленней чем veryfast, но будет файл и меньше весить)", | ||||
|   "preset_medium": "medium (медленней чем fast, но будет файл и меньше весить)", | ||||
|   "preset_placebo": "placebo (не рекомендуется)", | ||||
|   "preset_slow": "slow (медленней чем medium, но будет файл и меньше весить)", | ||||
|   "preset_slower": "slower (медленней чем slow, но будет файл и меньше весить)", | ||||
|   "preset_superfast": "superfast (медленней чем ultrafast, но будет файл и меньше весить)", | ||||
|   "preset_ultrafast": "ultrafast (быстро, но файл будет много весить)", | ||||
|   "preset_veryfast": "veryfast (медленней чем superfast, но будет файл и меньше весить)", | ||||
|   "preset_veryslow": "veryslow (медленней чем slower, но будет файл и меньше весить)", | ||||
|   "programmLink": "Сайт проекта", | ||||
|   "programmVersion": "**Версия программы:** {{.Version}}", | ||||
|   "queue": "Очередь", | ||||
|   "save": "Сохранить", | ||||
|   "selectEncoder": "Кодировщик:", | ||||
|   "selectFFPathTitle": "Укажите путь к FFmpeg и к FFprobe", | ||||
|   "selectFormat": "Расширение файла:", | ||||
|   "settings": "Настройки", | ||||
|   "testFF": "Проверка FFmpeg на работоспособность...", | ||||
|   "themesNameDark": "Тёмная", | ||||
|   "themesNameDefault": "По умолчанию", | ||||
|   "themesNameLight": "Светлая", | ||||
|   "titleDownloadLink": "Скачать можно от сюда", | ||||
|   "total": "Всего", | ||||
|   "unzipRun": "Распаковывается...", | ||||
|   "waitingQueue": "В очереди" | ||||
| } | ||||
							
								
								
									
										45
									
								
								internal/resources/translations/base.en.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								internal/resources/translations/base.en.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| { | ||||
|   "Advanced": "Advanced", | ||||
|   "Cancel": "Cancel", | ||||
|   "Confirm": "Confirm", | ||||
|   "Copy": "Copy", | ||||
|   "Create Folder": "Create Folder", | ||||
|   "Cut": "Cut", | ||||
|   "Enter filename": "Enter filename", | ||||
|   "Error": "Error", | ||||
|   "Favourites": "Favourites", | ||||
|   "File": "File", | ||||
|   "Folder": "Folder", | ||||
|   "New Folder": "New Folder", | ||||
|   "No": "No", | ||||
|   "OK": "OK", | ||||
|   "Open": "Open", | ||||
|   "Paste": "Paste", | ||||
|   "Quit": "Quit", | ||||
|   "Redo": "Redo", | ||||
|   "Save": "Save", | ||||
|   "Select all": "Select all", | ||||
|   "Show Hidden Files": "Show Hidden Files", | ||||
|   "Undo": "Undo", | ||||
|   "Yes": "Yes", | ||||
|   "file.name": { | ||||
|     "other": "Name" | ||||
|   }, | ||||
|   "file.parent": { | ||||
|     "other": "Parent" | ||||
|   }, | ||||
|   "friday": "Friday", | ||||
|   "friday.short": "Fri", | ||||
|   "monday": "Monday", | ||||
|   "monday.short": "Mon", | ||||
|   "saturday": "Saturday", | ||||
|   "saturday.short": "Sat", | ||||
|   "sunday": "Sunday", | ||||
|   "sunday.short": "Sun", | ||||
|   "thursday": "Thursday", | ||||
|   "thursday.short": "Thu", | ||||
|   "tuesday": "Tuesday", | ||||
|   "tuesday.short": "Tue", | ||||
|   "wednesday": "Wednesday", | ||||
|   "wednesday.short": "Wed" | ||||
| } | ||||
							
								
								
									
										45
									
								
								internal/resources/translations/base.kk.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								internal/resources/translations/base.kk.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| { | ||||
|   "Advanced": "Кеңейтілген", | ||||
|   "Cancel": "Бас тарту", | ||||
|   "Confirm": "Растау", | ||||
|   "Copy": "Көшіру", | ||||
|   "Create Folder": "Қалта жасау", | ||||
|   "Cut": "Кесу", | ||||
|   "Enter filename": "Файл атауын енгізіңіз", | ||||
|   "Error": "Қате", | ||||
|   "Favourites": "Таңдаулылар", | ||||
|   "File": "Файл", | ||||
|   "Folder": "Қалта", | ||||
|   "New Folder": "Жаңа қалта", | ||||
|   "No": "Жоқ", | ||||
|   "OK": "ОК", | ||||
|   "Open": "Ашу", | ||||
|   "Paste": "Кірістіру", | ||||
|   "Quit": "Шығу", | ||||
|   "Redo": "Қайталау", | ||||
|   "Save": "Сақтау", | ||||
|   "Select all": "Барлығын таңдаңыз", | ||||
|   "Show Hidden Files": "Жасырын файлдарды көрсету", | ||||
|   "Undo": "Бас тарту", | ||||
|   "Yes": "Иә", | ||||
|   "file.name": { | ||||
|     "other": "Аты" | ||||
|   }, | ||||
|   "file.parent": { | ||||
|     "other": "Жоғары" | ||||
|   }, | ||||
|   "friday": "Жұма", | ||||
|   "friday.short": "Жұ", | ||||
|   "monday": "Дүйсенбі", | ||||
|   "monday.short": "Дү", | ||||
|   "saturday": "Сенбі", | ||||
|   "saturday.short": "Сен", | ||||
|   "sunday": "Жексенбі", | ||||
|   "sunday.short": "Же", | ||||
|   "thursday": "Сейсенбі", | ||||
|   "thursday.short": "Се", | ||||
|   "tuesday": "Бейсенбі", | ||||
|   "tuesday.short": "Бе", | ||||
|   "wednesday": "Сәрсенбі", | ||||
|   "wednesday.short": "Сә" | ||||
| } | ||||
							
								
								
									
										45
									
								
								internal/resources/translations/base.ru.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								internal/resources/translations/base.ru.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| { | ||||
|   "Advanced": "Расширенные", | ||||
|   "Cancel": "Отмена", | ||||
|   "Confirm": "Подтвердить", | ||||
|   "Copy": "Копировать", | ||||
|   "Create Folder": "Создать папку", | ||||
|   "Cut": "Вырезать", | ||||
|   "Enter filename": "Введите имя файла", | ||||
|   "Error": "Ошибка", | ||||
|   "Favourites": "Избранное", | ||||
|   "File": "Файл", | ||||
|   "Folder": "Папка", | ||||
|   "New Folder": "Новая папка", | ||||
|   "No": "Нет", | ||||
|   "OK": "ОК", | ||||
|   "Open": "Открыть", | ||||
|   "Paste": "Вставить", | ||||
|   "Quit": "Выйти", | ||||
|   "Redo": "Повторить", | ||||
|   "Save": "Сохранить", | ||||
|   "Select all": "Выбрать всё", | ||||
|   "Show Hidden Files": "Показать скрытые файлы", | ||||
|   "Undo": "Отменить", | ||||
|   "Yes": "Да", | ||||
|   "file.name": { | ||||
|     "other": "Имя" | ||||
|   }, | ||||
|   "file.parent": { | ||||
|     "other": "Вверх" | ||||
|   }, | ||||
|   "friday": "Пятница", | ||||
|   "friday.short": "Пт", | ||||
|   "monday": "Понедельник", | ||||
|   "monday.short": "Пн", | ||||
|   "saturday": "Суббота", | ||||
|   "saturday.short": "Сб", | ||||
|   "sunday": "Воскресенье", | ||||
|   "sunday.short": "Вс", | ||||
|   "thursday": "Вторник", | ||||
|   "thursday.short": "Вт", | ||||
|   "tuesday": "Четверг", | ||||
|   "tuesday.short": "Чт", | ||||
|   "wednesday": "Среда", | ||||
|   "wednesday.short": "Ср" | ||||
| } | ||||
							
								
								
									
										11
									
								
								internal/utils/dialog.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								internal/utils/dialog.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| package utils | ||||
|  | ||||
| import ( | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/dialog" | ||||
| ) | ||||
|  | ||||
| func FileDialogResize(fileDialog *dialog.FileDialog, w fyne.Window) { | ||||
| 	contentSize := w.Content().Size() | ||||
| 	fileDialog.Resize(fyne.Size{Width: contentSize.Width - 50, Height: contentSize.Height - 50}) | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user