]> git.poda.fr Git - converter.git/commitdiff
refactor queue processing + remove unused functions
authorJulien <None>
Sun, 11 Oct 2026 12:50:02 +0000 (14:50 +0200)
committerJulien <None>
Sun, 11 Oct 2026 12:50:02 +0000 (14:50 +0200)
converter.py

index f5d8c856ebe201cd1a36d3398523deb6a05f1729..9c513d62743e53a34744969267471000f581c93a 100755 (executable)
@@ -185,13 +185,11 @@ class Converter:
 
     def _check(self, playlistDir: str, libraryDir: str) -> None:
         if not os.path.isdir(playlistDir):
-            self._log("Error: Invalid playlist directory \""
-                      + playlistDir + "\".")
+            self._log("Error: Invalid playlist directory \"" + playlistDir + "\".")
             return
 
         if not os.path.isdir(libraryDir):
-            self._log("Error: Invalid library directory \""
-                      + libraryDir + "\".")
+            self._log("Error: Invalid library directory \"" + libraryDir + "\".")
             return
 
         # List of albums/directories from library directory.
@@ -216,8 +214,7 @@ class Converter:
             libPlaylist = self._createLibraryPlaylistFromFile(os.path.join(playlistDir,
                                                                            playlistFile))
             for track in libPlaylist.tracks:
-                trackFilePath = os.path.join(track.trackDir,
-                                             track.trackFile)
+                trackFilePath = os.path.join(track.trackDir, track.trackFile)
 
                 if not os.path.isfile(trackFilePath):
                     self._log("Warning: \"" + trackFilePath
@@ -244,26 +241,21 @@ class Converter:
 
     def _convert(self, convertParams: ConvertParams) -> None:
         if not os.path.isdir(convertParams.playlistDir):
-            self._log("Error: Invalid playlist directory \""
-                      + convertParams.playlistDir + "\".")
+            self._log("Error: Invalid playlist directory \"" + convertParams.playlistDir + "\".")
             return
 
         if not os.path.isdir(convertParams.targetDir):
-            self._log("Error: Invalid target directory \""
-                      + convertParams.targetDir + "\".")
+            self._log("Error: Invalid target directory \"" + convertParams.targetDir + "\".")
             return
 
         convertProfile: ConvertProfile = ConvertProfile()
 
         if not convertProfile.init(convertParams.convertProfile):
-            self._log("Error: Invalid convert profile \""
-                      + convertParams.convertProfile + "\".")
+            self._log("Error: Invalid convert profile \"" + convertParams.convertProfile + "\".")
             return
 
-        if not self.checkConverter(convertParams.converterPath,
-                                   self._CONVERTER_CHECK):
-            self._log("Error: Could not start converter \""
-                      + convertParams.converterPath + "\".")
+        if not self.checkConverter(convertParams.converterPath, self._CONVERTER_CHECK):
+            self._log("Error: Could not start converter \"" + convertParams.converterPath + "\".")
             return
 
         if convertParams.jobs < 1:
@@ -293,14 +285,12 @@ class Converter:
 
         # Build existing file sets from target directory.
         for tFile in os.listdir(convertParams.targetDir):
-            if not os.path.isfile(os.path.join(convertParams.targetDir,
-                                               tFile)):
+            if not os.path.isfile(os.path.join(convertParams.targetDir, tFile)):
                 continue
 
             tExt: str = self.getFileExtension(tFile).lower()
 
-            if (convertProfile.isTargetExtension(tExt)
-                or convertProfile.isCopyExtension(tExt)):
+            if (convertProfile.isTargetExtension(tExt) or convertProfile.isCopyExtension(tExt)):
                 unmatchedFiles.add(tFile)
             elif tExt == self._TARGET_PLAYLIST_EXT:
                 unmatchedPlaylistFiles.add(tFile)
@@ -308,21 +298,19 @@ class Converter:
 
         # Build task queue and update playlist files.
         for p in libPlaylists:
-            if self._getStopSignal() == True:
+            if self._getStopSignal():
                 self._log("Stopped.")
                 return
 
             playlist: LibraryPlaylist = libPlaylists[p]
-            targetPlaylistFile: str = (playlist.name
-                                       + self._TARGET_PLAYLIST_EXT)
+            targetPlaylistFile: str = (playlist.name + self._TARGET_PLAYLIST_EXT)
             targetFileList: list[str] = []
 
             if targetPlaylistFile in unmatchedPlaylistFiles:
                 unmatchedPlaylistFiles.remove(targetPlaylistFile)
 
             for track in playlist.tracks:
-                trackFilePath: str = os.path.join(track.trackDir,
-                                                  track.trackFile)
+                trackFilePath: str = os.path.join(track.trackDir, track.trackFile)
 
                 if not os.path.isfile(trackFilePath):
                     self._log("Error: \"" + trackFilePath + "\" in playlist \""
@@ -356,8 +344,7 @@ class Converter:
                     targetFileName = self.trimTrackFileName(targetFileName)
 
                 targetFile: str = targetFileName + targetExt
-                targetFilePath: str = os.path.join(convertParams.targetDir,
-                                                   targetFile)
+                targetFilePath: str = os.path.join(convertParams.targetDir, targetFile)
 
                 targetFileList.append(targetFile)
 
@@ -444,8 +431,7 @@ class Converter:
 
     # Main function started by threads. Process queue elements
     # until "None" is found or stop signal is received.
-    def _processQueue(self, q: queue.SimpleQueue,
-                      converterPath: str, stats: Stats) -> None:
+    def _processQueue(self, q: queue.SimpleQueue, converterPath: str, stats: Stats) -> None:
         self._statsLock.acquire()
         totalTasks: int = stats.tasks
         self._statsLock.release()
@@ -468,11 +454,9 @@ class Converter:
         self._statsLock.release()
 
     # Copy or convert a music file.
-    def _processTask(self, task: Task, converterPath: str, totalTasks: int,
-                     stats: Stats) -> None:
+    def _processTask(self, task: Task, converterPath: str, totalTasks: int, stats: Stats) -> None:
         if not os.path.isfile(task.inputFilePath):
-            self._log("Error: Playlist element \"" + task.inputFilePath
-                      + "\" is not a file.")
+            self._log("Error: Playlist element \"" + task.inputFilePath + "\" is not a file.")
             stats.errors += 1
             return
 
@@ -492,19 +476,28 @@ class Converter:
             self._log(str(task.taskId) + "/" + str(totalTasks)
                       + ": Copying \"" + task.inputFilePath
                       + "\" into \"" + task.outputFilePath + "\".")
-            self.copyFile(task.inputFilePath, outputFilePathWip)
-            os.rename(outputFilePathWip, task.outputFilePath)
+
+            try:
+                shutil.copy(task.inputFilePath, outputFilePathWip)
+                os.rename(outputFilePathWip, task.outputFilePath)
+            except:
+                self._log("Error copying file \"" + task.inputFilePath
+                          + "\" into \"" + task.outputFilePath + "\".")
+                stats.errors += 1
+                return
+
             stats.copied += 1
 
             if update:
                 stats.updated +=1
         elif task.taskType == "convert":
-            command: list[str] = ([converterPath] + [self._CONVERTER_IN]
-                                  + [task.inputFilePath] + task.converterArgs
-                                  + [outputFilePathWip])
             self._log(str(task.taskId) + "/" + str(totalTasks)
                       + ": Converting \"" + task.inputFilePath
                       + "\" to \"" + task.outputFilePath + "\".")
+
+            command: list[str] = ([converterPath] + [self._CONVERTER_IN]
+                                  + [task.inputFilePath] + task.converterArgs
+                                  + [outputFilePathWip])
             result: subprocess.CompletedProcess = subprocess.run(
                 command, capture_output=True, text=True)
 
@@ -512,18 +505,25 @@ class Converter:
                 self._log("Error from converter on file \""
                           + task.inputFilePath + "\": " + result.stderr)
                 stats.errors += 1
-            else:
-                if len(result.stderr) != 0:
-                    self._log("Warning from converter on file \""
-                              + task.inputFilePath + "\": " + result.stderr)
-                    stats.warnings += 1
+                return
 
+            try:
                 os.rename(outputFilePathWip, task.outputFilePath)
-                stats.converted += 1
+            except:
+                self._log("Error converting file \"" + task.inputFilePath
+                          + "\" into \"" + task.outputFilePath + "\".")
+                stats.errors += 1
+                return
+
+            if len(result.stderr) != 0:
+                self._log("Warning from converter on file \""
+                          + task.inputFilePath + "\": " + result.stderr)
+                stats.warnings += 1
 
-                if update:
-                    stats.updated +=1
+            stats.converted += 1
 
+            if update:
+                stats.updated +=1
         else: # Unknown task
             self._log("Error: Skipping non valid task type \"" + task.taskType
                       + "\" file \"" + task.inputFilePath + "\".")
@@ -545,14 +545,12 @@ class Converter:
                 playlistName: str = self.trimFileExtension(element)
 
                 if playlistName in libPlaylists:
-                    self._log("Warning: Duplicate playlist name \""
-                              + playlistName + "\".")
+                    self._log("Warning: Duplicate playlist name \"" + playlistName + "\".")
                 else:
                     libPlaylist: LibraryPlaylist = self._createLibraryPlaylistFromFile(path)
 
                     if len(libPlaylist.tracks) == 0:
-                        self._log("Warning: Empty library playlist \""
-                                  + libPlaylist.name + "\".")
+                        self._log("Warning: Empty library playlist \"" + libPlaylist.name + "\".")
                     else:
                         libPlaylists[playlistName] = libPlaylist
 
@@ -569,14 +567,13 @@ class Converter:
         elif self.getFileExtension(filePath).lower() == ".xspf":
             self._loadTracksFromXspf(filePath, playlist)
         else:
-            self._log("Warning: Unsupported playlist extension for file \""
-                      + filePath + "\".")
+            self._log("Warning: Unsupported playlist extension for file \"" + filePath + "\".")
 
         return playlist
 
     # Read m3u playlist file to get all its tracks.
     def _loadTracksFromM3u(self, filePath: str, playlist: LibraryPlaylist) -> None:
-        m3uFile: typing.IO[str] = self.openFile(filePath, "rt")
+        m3uFile: typing.IO[str] = open(filePath, "rt", encoding="utf8")
 
         # Each line is an string path.
         for line in m3uFile:
@@ -611,8 +608,7 @@ class Converter:
                 if decodedString.startswith("file://"):
                     decodedString = decodedString[7:]
 
-                playlist.add(os.path.dirname(decodedString),
-                             os.path.basename(decodedString))
+                playlist.add(os.path.dirname(decodedString), os.path.basename(decodedString))
 
     # Create or update playlist file from a directory.
     def _updatePlaylistFile(self, playlist: list[str], playlistPath: str) -> None:
@@ -637,7 +633,7 @@ class Converter:
 
     # Build a m3u file from a playlist.
     def _buildM3uPlaylistFile(self, playlist: list[str], filePath: str) -> None:
-        plFile: typing.IO[str] = self.openFile(filePath, "wt")
+        plFile: typing.IO[str] = open(filePath, "wt", encoding="utf8")
 
         # Build new playlist file.
         for track in playlist:
@@ -716,28 +712,14 @@ class Converter:
     def getFileExtension(self, filePath: str) -> str:
         return os.path.splitext(filePath)[1]
 
-    def openFile(self, path: str, args: str) -> typing.IO[str]:
-        return open(path, args, encoding="utf8")
-
-    def makeDir(self, dirPath: str) -> None:
-        os.makedirs(dirPath, exist_ok=True)
+    # Compare last modification date.
+    def isFileChanged(self, sourceFilePath: str, targetFilePath: str) -> bool:
+        return os.path.getmtime(sourceFilePath) > os.path.getmtime(targetFilePath)
 
-    def copyFile(self, oriFilePath: str, newFilePath: str) -> None:
-        shutil.copy(oriFilePath, newFilePath)
+    def isFileIdentical(self, firstFilePath: str, secondFilePath: str) -> bool:
+        return filecmp.cmp(firstFilePath, secondFilePath, shallow=False)
 
-    # Compare last modification date.
-    def isFileChanged(self, sourceFilePath: str,
-                      targetFilePath: str) -> bool:
-        return (os.path.getmtime(sourceFilePath)
-                > os.path.getmtime(targetFilePath))
-
-    def isFileIdentical(self, firstFilePath: str,
-                        secondFilePath: str) -> bool:
-        return filecmp.cmp(firstFilePath, secondFilePath,
-                           shallow=False)
-
-    def checkConverter(self, converterPath: str,
-                       converterArg: str) -> bool:
+    def checkConverter(self, converterPath: str, converterArg: str) -> bool:
         try:
             return subprocess.run([converterPath, converterArg],
                                   stdout=subprocess.DEVNULL,
@@ -776,20 +758,17 @@ class GUI:
         self.runButton: tk.Button = tk.Button(self.runFrame,
             command=self.run, text="Run Configuration")
 
-        self.cancelButton: tk.Button = tk.Button(self.runFrame,
-            command=self.cancel, text="Cancel")
+        self.cancelButton: tk.Button = tk.Button(self.runFrame, command=self.cancel, text="Cancel")
         self.cancelButton["state"] = "disabled"
 
-        self.actionLabel: tk.Label = tk.Label(self.runFrame,
-            text="Action")
+        self.actionLabel: tk.Label = tk.Label(self.runFrame, text="Action")
         self.action: tk.StringVar = tk.StringVar(self.runFrame)
         self.action.set("convert")
         self.actionOption: tk.OptionMenu = tk.OptionMenu(self.runFrame,
             self.action, "convert", "check")
         self.actionOption.config(width=8)
 
-        self.profileLabel: tk.Label = tk.Label(self.runFrame,
-            text="Profile")
+        self.profileLabel: tk.Label = tk.Label(self.runFrame, text="Profile")
         self.profile: tk.StringVar = tk.StringVar(self.runFrame)
         self.profile.set("mp3")
         self.profileOption: tk.OptionMenu = tk.OptionMenu(self.runFrame,
@@ -800,8 +779,7 @@ class GUI:
         self.trimCheck: tk.Checkbutton = tk.Checkbutton(self.runFrame,
             text="Trim track N", variable=self.trim)
 
-        self.jobsLabel: tk.Label = tk.Label(self.runFrame,
-            text="Jobs")
+        self.jobsLabel: tk.Label = tk.Label(self.runFrame, text="Jobs")
         self.jobs: tk.StringVar = tk.StringVar(value="1")
         self.jobsOption: tk.OptionMenu = tk.OptionMenu(self.runFrame,
             self.jobs, "1", "2", "3", "4", "5", "6", "7", "8", "9", "10")
@@ -932,18 +910,14 @@ def cli_main() -> None:
         description="Music Library Converter",
         formatter_class=argparse.ArgumentDefaultsHelpFormatter)
 
-    parser.add_argument("playlist-dir", help="Playlist directory",
-                        type=str)
-    parser.add_argument("target-dir", help="Target directory",
-                        type=str)
-    parser.add_argument("--profile", "-p", help="Conversion profile",
-                        type=str, default="mp3")
+    parser.add_argument("playlist-dir", help="Playlist directory", type=str)
+    parser.add_argument("target-dir", help="Target directory", type=str)
+    parser.add_argument("--profile", "-p", help="Conversion profile", type=str, default="mp3")
     parser.add_argument("--converter", "-c", help="Converter path",
                         type=str, default=CONVERTER_NAME)
     parser.add_argument("--trim", "-t", help="Trim track numbers in file names",
                         action="store_true")
-    parser.add_argument("--jobs", "-j", help="Number of concurrent jobs",
-                        type=int, default=1)
+    parser.add_argument("--jobs", "-j", help="Number of concurrent jobs", type=int, default=1)
     parser.add_argument("--check", help="Check mode", action="store_true")
 
     args: dict = vars(parser.parse_args())