Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3.9
- # Simple drag and drop converter app
- import wx
- from wx.adv import AboutDialogInfo, GenericAboutBox
- from threading import Thread
- from pathlib import Path
- import os
- import sys
- import numpy as np
- import subprocess
- choices = ['.m4a', '.mp3', '.acc']
- if os.name == 'nt':
- import ctypes
- ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('UniConv_v0.0.0')
- class RedirectStdoutToTextCtrl():
- def __init__(self, widget):
- sys.stdout = self
- sys.stderr = self
- self.widget = widget
- def write(self, message):
- self.widget.WriteText(message)
- return len(message)
- def read(self):
- pass
- def __del__(self):
- sys.stdout = sys.__stdout__
- class GUI(wx.Frame):
- def __init__(self, parent, id, title):
- wx.Frame.__init__(self, parent, id, title)
- self.SetSize((300, 200))
- # pretty icon
- def getIcon():
- x, y = 256, 256
- img = np.zeros((x*y), dtype='uint8')
- for i in range(y):
- for j in range(x):
- f = j/x
- img[i*y+j] = int((4*f**3 if f < 0.5 else 1-(-2*f+2)**3/2)*256) # cubic ease function
- img = np.repeat(img, 3)
- icon = wx.Bitmap.FromBuffer(x, y, img)
- return icon
- self.SetIcon(wx.Icon(getIcon()))
- # main panel
- self.panel = wx.Panel(self)
- self.panel.SetDropTarget(self.FileDrop(self)) # set DND
- # main sizer
- vSizer = wx.BoxSizer(wx.VERTICAL)
- self.panel.SetSizer(vSizer)
- # dropdown list
- self.comboBox = wx.ComboBox(self.panel, choices=choices)
- vSizer.Add(self.comboBox, flag=wx.EXPAND|wx.ALL, border=5)
- self.comboBox.SetSelection(0)
- # logger panel
- self.loggerPanel = wx.Panel(self.panel)
- vSizer.Add(self.loggerPanel, flag=wx.EXPAND, proportion=1)
- self.logsUI(self.loggerPanel)
- self.Centre()
- self.panel.Layout()
- def logsUI(self, panel):
- sizer = wx.BoxSizer(wx.VERTICAL)
- panel.SetSizer(sizer)
- self.logsTextCtrl = wx.TextCtrl(panel, style=wx.TE_MULTILINE, size=(222, 0))
- sizer.Add(self.logsTextCtrl, flag=wx.ALL|wx.EXPAND, border=5, proportion=1)
- self.logsTextCtrl.WriteText('Right click to clear the logs.\n\n')
- self.stdout = RedirectStdoutToTextCtrl(self.logsTextCtrl)
- def onContextMenu(evt):
- menu = wx.Menu()
- clearLog = menu.Append(wx.ID_ANY, "Clear log")
- menu.Bind(wx.EVT_MENU, lambda _: self.logsTextCtrl.Clear(), id=clearLog.GetId())
- self.logsTextCtrl.PopupMenu(menu)
- self.logsTextCtrl.Bind(wx.EVT_CONTEXT_MENU, onContextMenu)
- def workerThread(self, files, extension):
- failed_files = []
- for i, file in enumerate(files):
- print(f'\nFile {i+1}/{len(files)}')
- file_path = Path(file).resolve()
- output_path = str(file_path.parent)
- file_name = f'%s{extension}' % str(file_path.stem)
- output_file = os.path.join(output_path, file_name)
- # process file
- result = False
- try:
- result = subprocess.run(['ffmpeg', '-i', file, '-vn', '-acodec', 'copy', output_file]) # redirecting is a bit harder. https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate
- result = result.returncode == 0
- except:
- print('An error has occured!')
- if not result:
- failed_files.append(file)
- if failed_files:
- failMsg = f'\n{len(failed_files)} file(s) failed to process:'
- print(failMsg)
- for failed_file in failed_files:
- print(failed_file)
- wx.MessageDialog(self, 'An error has occurred. Please check the log.', 'Error', wx.OK|wx.ICON_ERROR).ShowModal()
- else:
- print('\nAll files converted.')
- class FileDrop(wx.FileDropTarget):
- def __init__(self, parent):
- wx.FileDropTarget.__init__(self)
- self.parent = parent
- def OnDropFiles(self, x, y, filenames):
- extension = self.parent.comboBox.GetString(self.parent.comboBox.GetSelection())
- Thread(target=self.parent.workerThread, daemon=True, args=(filenames, extension)).start()
- return True
- def main():
- app = wx.App()
- gui = GUI(None, wx.ID_ANY, 'UniConv')
- gui.Show(True)
- app.MainLoop()
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement