TonieToolbox 0.6.0a2__py3-none-any.whl → 0.6.0a3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- TonieToolbox/__init__.py +1 -1
- TonieToolbox/constants.py +18 -0
- TonieToolbox/dependency_manager.py +6 -1
- TonieToolbox/integration_macos.py +192 -66
- {tonietoolbox-0.6.0a2.dist-info → tonietoolbox-0.6.0a3.dist-info}/METADATA +1 -1
- {tonietoolbox-0.6.0a2.dist-info → tonietoolbox-0.6.0a3.dist-info}/RECORD +10 -10
- {tonietoolbox-0.6.0a2.dist-info → tonietoolbox-0.6.0a3.dist-info}/WHEEL +0 -0
- {tonietoolbox-0.6.0a2.dist-info → tonietoolbox-0.6.0a3.dist-info}/entry_points.txt +0 -0
- {tonietoolbox-0.6.0a2.dist-info → tonietoolbox-0.6.0a3.dist-info}/licenses/LICENSE.md +0 -0
- {tonietoolbox-0.6.0a2.dist-info → tonietoolbox-0.6.0a3.dist-info}/top_level.txt +0 -0
TonieToolbox/__init__.py
CHANGED
TonieToolbox/constants.py
CHANGED
@@ -95,6 +95,24 @@ SUPPORTED_EXTENSIONS = [
|
|
95
95
|
'.ape', '.wma', '.aiff', '.mp2', '.mp4', '.webm', '.mka'
|
96
96
|
]
|
97
97
|
|
98
|
+
UTI_MAPPINGS = {
|
99
|
+
'mp3': 'public.mp3',
|
100
|
+
'wav': 'public.wav',
|
101
|
+
'flac': 'org.xiph.flac',
|
102
|
+
'ogg': 'org.xiph.ogg',
|
103
|
+
'opus': 'public.opus',
|
104
|
+
'aac': 'public.aac-audio',
|
105
|
+
'm4a': 'public.m4a-audio',
|
106
|
+
'wma': 'com.microsoft.windows-media-wma',
|
107
|
+
'aiff': 'public.aiff-audio',
|
108
|
+
'mp2': 'public.mp2',
|
109
|
+
'mp4': 'public.mpeg-4-audio',
|
110
|
+
'mka': 'public.audio',
|
111
|
+
'webm': 'public.webm-audio',
|
112
|
+
'ape': 'public.audio',
|
113
|
+
'taf': 'public.audio'
|
114
|
+
}
|
115
|
+
|
98
116
|
ARTWORK_NAMES = [
|
99
117
|
'cover', 'folder', 'album', 'front', 'artwork', 'image',
|
100
118
|
'albumart', 'albumartwork', 'booklet'
|
@@ -35,7 +35,7 @@ DEPENDENCIES = {
|
|
35
35
|
'extract_dir': 'ffmpeg'
|
36
36
|
},
|
37
37
|
'darwin': {
|
38
|
-
'url': 'https://evermeet.cx/ffmpeg/
|
38
|
+
'url': 'https://evermeet.cx/ffmpeg/get/zip',
|
39
39
|
'bin_path': 'ffmpeg',
|
40
40
|
'extract_dir': 'ffmpeg'
|
41
41
|
}
|
@@ -112,6 +112,11 @@ def download_file(url, destination):
|
|
112
112
|
return True
|
113
113
|
except Exception as e:
|
114
114
|
logger.error("Failed to download %s: %s", url, e)
|
115
|
+
# On macOS, provide more helpful error message for SSL certificate issues
|
116
|
+
if platform.system() == 'Darwin' and 'CERTIFICATE_VERIFY_FAILED' in str(e):
|
117
|
+
logger.error("SSL certificate verification failed on macOS. This is a known issue.")
|
118
|
+
logger.error("You can solve this by running: /Applications/Python 3.x/Install Certificates.command")
|
119
|
+
logger.error("Or by using the --auto-download flag which will bypass certificate verification.")
|
115
120
|
return False
|
116
121
|
|
117
122
|
def extract_archive(archive_path, extract_dir):
|
@@ -1,11 +1,10 @@
|
|
1
|
-
# filepath: d:\Repository\TonieToolbox\TonieToolbox\integration_macos.py
|
2
1
|
import os
|
3
2
|
import sys
|
4
3
|
import json
|
5
4
|
import plistlib
|
6
5
|
import subprocess
|
7
6
|
from pathlib import Path
|
8
|
-
from .constants import SUPPORTED_EXTENSIONS, CONFIG_TEMPLATE
|
7
|
+
from .constants import SUPPORTED_EXTENSIONS, CONFIG_TEMPLATE,UTI_MAPPINGS
|
9
8
|
from .logger import get_logger
|
10
9
|
|
11
10
|
logger = get_logger('integration_macos')
|
@@ -22,15 +21,9 @@ class MacOSContextMenuIntegration:
|
|
22
21
|
self.services_dir = os.path.join(os.path.expanduser('~'), 'Library', 'Services')
|
23
22
|
self.icon_path = os.path.join(self.output_dir, 'icon.png')
|
24
23
|
os.makedirs(self.output_dir, exist_ok=True)
|
25
|
-
|
26
|
-
# Error handling and success messages for shell scripts
|
27
24
|
self.error_handling = 'if [ $? -ne 0 ]; then\n echo "Error: Command failed with error code $?"\n read -p "Press any key to close this window..." key\n exit 1\nfi'
|
28
25
|
self.success_handling = 'echo "Command completed successfully"\nsleep 2'
|
29
|
-
|
30
|
-
# Load configuration
|
31
26
|
self.config = self._apply_config_template()
|
32
|
-
|
33
|
-
# Ensure these attributes always exist
|
34
27
|
self.upload_url = ''
|
35
28
|
self.log_level = self.config.get('log_level', 'SILENT')
|
36
29
|
self.log_to_file = self.config.get('log_to_file', False)
|
@@ -40,14 +33,19 @@ class MacOSContextMenuIntegration:
|
|
40
33
|
|
41
34
|
logger.debug(f"Upload enabled: {self.upload_enabled}")
|
42
35
|
logger.debug(f"Upload URL: {self.upload_url}")
|
43
|
-
logger.debug(f"Authentication: {'Basic Authentication' if self.basic_authentication else ('None' if self.none_authentication else ('Client Cert' if self.client_cert_authentication else 'Unknown'))}")
|
44
|
-
|
45
|
-
|
46
|
-
|
36
|
+
logger.debug(f"Authentication: {'Basic Authentication' if self.basic_authentication else ('None' if self.none_authentication else ('Client Cert' if self.client_cert_authentication else 'Unknown'))}")
|
37
|
+
self._setup_commands()
|
38
|
+
|
47
39
|
def _build_cmd(self, base_args, file_placeholder='$1', output_to_source=True, use_upload=False, use_artwork=False, use_json=False, use_compare=False, use_info=False, is_recursive=False, is_split=False, is_folder=False, keep_open=False, log_to_file=False):
|
48
40
|
"""Dynamically build command strings for quick actions."""
|
49
41
|
exe = self.exe_path
|
50
42
|
cmd = '#!/bin/bash\n\n'
|
43
|
+
# Debug output to see what's being passed to the script
|
44
|
+
cmd += 'echo "Arguments received: $@"\n'
|
45
|
+
cmd += 'echo "Number of arguments: $#"\n'
|
46
|
+
cmd += 'if [ $# -gt 0 ]; then\n'
|
47
|
+
cmd += ' echo "First argument: $1"\n'
|
48
|
+
cmd += 'fi\n\n'
|
51
49
|
|
52
50
|
# Add a description of what's being executed
|
53
51
|
cmd += 'echo "Running TonieToolbox'
|
@@ -70,12 +68,117 @@ class MacOSContextMenuIntegration:
|
|
70
68
|
else:
|
71
69
|
cmd += ' convert'
|
72
70
|
cmd += ' command..."\n\n'
|
71
|
+
# Properly handle paths from macOS Services
|
72
|
+
if is_folder or is_recursive:
|
73
|
+
# Handle multiple arguments and ensure we get a valid folder
|
74
|
+
cmd += '# Handle paths from macOS Services\n'
|
75
|
+
cmd += '# First, try to get paths from stdin (macOS passes paths this way)\n'
|
76
|
+
cmd += 'if [ -p /dev/stdin ]; then\n'
|
77
|
+
cmd += ' PATHS=$(cat /dev/stdin)\n'
|
78
|
+
cmd += ' echo "Found paths from stdin: $PATHS"\n'
|
79
|
+
cmd += 'fi\n\n'
|
80
|
+
cmd += '# If no paths from stdin, check command line arguments\n'
|
81
|
+
cmd += 'FOLDER_PATH=""\n'
|
82
|
+
cmd += 'if [ -z "$PATHS" ]; then\n'
|
83
|
+
cmd += ' for arg in "$@"; do\n'
|
84
|
+
cmd += ' if [ -d "$arg" ]; then\n'
|
85
|
+
cmd += ' FOLDER_PATH="$arg"\n'
|
86
|
+
cmd += ' echo "Processing folder from args: $FOLDER_PATH"\n'
|
87
|
+
cmd += ' break\n'
|
88
|
+
cmd += ' fi\n'
|
89
|
+
cmd += ' done\n'
|
90
|
+
cmd += 'else\n'
|
91
|
+
cmd += ' for path in $PATHS; do\n'
|
92
|
+
cmd += ' if [ -d "$path" ]; then\n'
|
93
|
+
cmd += ' FOLDER_PATH="$path"\n'
|
94
|
+
cmd += ' echo "Processing folder from stdin: $FOLDER_PATH"\n'
|
95
|
+
cmd += ' break\n'
|
96
|
+
cmd += ' fi\n'
|
97
|
+
cmd += ' done\n'
|
98
|
+
cmd += 'fi\n\n'
|
99
|
+
cmd += 'if [ -z "$FOLDER_PATH" ]; then\n'
|
100
|
+
cmd += ' echo "Error: No valid folder path found in arguments or stdin"\n'
|
101
|
+
cmd += ' read -p "Press any key to close this window..." key\n'
|
102
|
+
cmd += ' exit 1\n'
|
103
|
+
cmd += 'fi\n\n'
|
104
|
+
|
105
|
+
# Use the variable for the command
|
106
|
+
file_placeholder='$FOLDER_PATH'
|
107
|
+
elif use_compare:
|
108
|
+
# For compare operation, we need two file paths
|
109
|
+
cmd += '# Compare requires two files\n'
|
110
|
+
cmd += 'if [ $# -lt 2 ]; then\n'
|
111
|
+
cmd += ' echo "Error: Compare operation requires two files."\n'
|
112
|
+
cmd += ' read -p "Press any key to close this window..." key\n'
|
113
|
+
cmd += ' exit 1\n'
|
114
|
+
cmd += 'fi\n\n'
|
115
|
+
else:
|
116
|
+
# For regular file operations, handle paths correctly
|
117
|
+
cmd += '# Handle file paths correctly - try multiple methods for macOS\n'
|
118
|
+
cmd += 'FILE_PATH=""\n'
|
119
|
+
|
120
|
+
# First, try to get paths from stdin (macOS passes paths this way sometimes)
|
121
|
+
cmd += '# Method 1: Try to read from stdin if available\n'
|
122
|
+
cmd += 'if [ -p /dev/stdin ]; then\n'
|
123
|
+
cmd += ' STDIN_PATHS=$(cat)\n'
|
124
|
+
cmd += ' if [ -n "$STDIN_PATHS" ]; then\n'
|
125
|
+
cmd += ' for path in $STDIN_PATHS; do\n'
|
126
|
+
cmd += ' if [ -f "$path" ]; then\n'
|
127
|
+
cmd += ' FILE_PATH="$path"\n'
|
128
|
+
cmd += ' echo "Found file path from stdin: $FILE_PATH"\n'
|
129
|
+
cmd += ' break\n'
|
130
|
+
cmd += ' fi\n'
|
131
|
+
cmd += ' done\n'
|
132
|
+
cmd += ' fi\n'
|
133
|
+
cmd += 'fi\n\n'
|
134
|
+
|
135
|
+
# Method 2: Try command line arguments
|
136
|
+
cmd += '# Method 2: Check command line arguments\n'
|
137
|
+
cmd += 'if [ -z "$FILE_PATH" ]; then\n'
|
138
|
+
cmd += ' for arg in "$@"; do\n'
|
139
|
+
cmd += ' if [ -f "$arg" ]; then\n'
|
140
|
+
cmd += ' FILE_PATH="$arg"\n'
|
141
|
+
cmd += ' echo "Found file path from arguments: $FILE_PATH"\n'
|
142
|
+
cmd += ' break\n'
|
143
|
+
cmd += ' fi\n'
|
144
|
+
cmd += ' done\n'
|
145
|
+
cmd += 'fi\n\n'
|
146
|
+
|
147
|
+
# Method 3: Try to handle case where path might be in $1
|
148
|
+
cmd += '# Method 3: Try first argument directly\n'
|
149
|
+
cmd += 'if [ -z "$FILE_PATH" ] && [ -n "$1" ] && [ -f "$1" ]; then\n'
|
150
|
+
cmd += ' FILE_PATH="$1"\n'
|
151
|
+
cmd += ' echo "Using first argument directly as file path: $FILE_PATH"\n'
|
152
|
+
cmd += 'fi\n\n'
|
153
|
+
|
154
|
+
# Method 4: Parse automator's encoded path format
|
155
|
+
cmd += '# Method 4: Try to decode special format macOS might use\n'
|
156
|
+
cmd += 'if [ -z "$FILE_PATH" ] && [ -n "$1" ]; then\n'
|
157
|
+
cmd += ' # Sometimes macOS passes paths with "file://" prefix\n'
|
158
|
+
cmd += ' DECODED_PATH=$(echo "$1" | sed -e "s|^file://||" -e "s|%20| |g")\n'
|
159
|
+
cmd += ' if [ -f "$DECODED_PATH" ]; then\n'
|
160
|
+
cmd += ' FILE_PATH="$DECODED_PATH"\n'
|
161
|
+
cmd += ' echo "Using decoded path: $FILE_PATH"\n'
|
162
|
+
cmd += ' fi\n'
|
163
|
+
cmd += 'fi\n\n'
|
164
|
+
|
165
|
+
# Final check
|
166
|
+
cmd += 'if [ -z "$FILE_PATH" ]; then\n'
|
167
|
+
cmd += ' echo "Error: Could not find a valid file path. Tried:"\n'
|
168
|
+
cmd += ' echo "- Reading from stdin"\n'
|
169
|
+
cmd += ' echo "- Command arguments: $@"\n'
|
170
|
+
cmd += ' echo "- Decoding URL format"\n'
|
171
|
+
cmd += ' read -p "Press any key to close this window..." key\n'
|
172
|
+
cmd += ' exit 1\n'
|
173
|
+
cmd += 'fi\n\n'
|
174
|
+
|
175
|
+
# Use the variable for the command
|
176
|
+
file_placeholder='$FILE_PATH'
|
73
177
|
|
74
178
|
# Build the actual command
|
75
179
|
cmd_line = f'"{exe}" {base_args}'
|
76
180
|
if log_to_file:
|
77
|
-
cmd_line += ' --log-file'
|
78
|
-
if is_recursive:
|
181
|
+
cmd_line += ' --log-file' if is_recursive:
|
79
182
|
cmd_line += ' --recursive'
|
80
183
|
if output_to_source:
|
81
184
|
cmd_line += ' --output-to-source'
|
@@ -84,7 +187,28 @@ class MacOSContextMenuIntegration:
|
|
84
187
|
if is_split:
|
85
188
|
cmd_line += ' --split'
|
86
189
|
if use_compare:
|
87
|
-
|
190
|
+
# For compare, we need to handle two files
|
191
|
+
cmd += '# Find two TAF files for comparison\n'
|
192
|
+
cmd += 'FILE1=""\n'
|
193
|
+
cmd += 'FILE2=""\n'
|
194
|
+
cmd += 'for arg in "$@"; do\n'
|
195
|
+
cmd += ' if [ -f "$arg" ]; then\n'
|
196
|
+
cmd += ' if [ -z "$FILE1" ]; then\n'
|
197
|
+
cmd += ' FILE1="$arg"\n'
|
198
|
+
cmd += ' echo "First TAF file: $FILE1"\n'
|
199
|
+
cmd += ' elif [ -z "$FILE2" ]; then\n'
|
200
|
+
cmd += ' FILE2="$arg"\n'
|
201
|
+
cmd += ' echo "Second TAF file: $FILE2"\n'
|
202
|
+
cmd += ' break\n'
|
203
|
+
cmd += ' fi\n'
|
204
|
+
cmd += ' fi\n'
|
205
|
+
cmd += 'done\n\n'
|
206
|
+
cmd += 'if [ -z "$FILE1" ] || [ -z "$FILE2" ]; then\n'
|
207
|
+
cmd += ' echo "Error: Need two TAF files for comparison."\n'
|
208
|
+
cmd += ' read -p "Press any key to close this window..." key\n'
|
209
|
+
cmd += ' exit 1\n'
|
210
|
+
cmd += 'fi\n\n'
|
211
|
+
cmd_line += ' --compare "$FILE1" "$FILE2"'
|
88
212
|
else:
|
89
213
|
cmd_line += f' "{file_placeholder}"'
|
90
214
|
if use_upload:
|
@@ -101,6 +225,7 @@ class MacOSContextMenuIntegration:
|
|
101
225
|
cmd_line += ' --create-custom-json'
|
102
226
|
|
103
227
|
# Add the command to the script
|
228
|
+
cmd += f'echo "Executing: {cmd_line}"\n'
|
104
229
|
cmd += f'{cmd_line}\n\n'
|
105
230
|
|
106
231
|
# Add error and success handling
|
@@ -174,7 +299,6 @@ class MacOSContextMenuIntegration:
|
|
174
299
|
|
175
300
|
def _setup_upload(self):
|
176
301
|
"""Set up upload functionality based on config.json settings"""
|
177
|
-
# Always initialize authentication flags
|
178
302
|
self.basic_authentication = False
|
179
303
|
self.client_cert_authentication = False
|
180
304
|
self.none_authentication = False
|
@@ -210,22 +334,16 @@ class MacOSContextMenuIntegration:
|
|
210
334
|
return bool(self.upload_url)
|
211
335
|
except Exception as e:
|
212
336
|
logger.debug(f"Unexpected error while loading configuration: {e}")
|
213
|
-
return False
|
214
|
-
|
337
|
+
return False
|
215
338
|
def _create_quick_action(self, name, command, file_types=None, directory_based=False):
|
216
339
|
"""Create a macOS Quick Action (Service) with the given name and command."""
|
217
|
-
# Create Quick Action directory
|
218
340
|
action_dir = os.path.join(self.services_dir, f"{name}.workflow")
|
219
341
|
os.makedirs(action_dir, exist_ok=True)
|
220
|
-
|
221
|
-
# Create Contents directory
|
222
342
|
contents_dir = os.path.join(action_dir, "Contents")
|
223
343
|
os.makedirs(contents_dir, exist_ok=True)
|
224
|
-
|
225
|
-
# Create document.wflow file with plist content
|
226
344
|
document_path = os.path.join(contents_dir, "document.wflow")
|
227
345
|
|
228
|
-
#
|
346
|
+
# Set up the plist to ensure the service appears in context menus
|
229
347
|
info_plist = {
|
230
348
|
"NSServices": [
|
231
349
|
{
|
@@ -237,30 +355,27 @@ class MacOSContextMenuIntegration:
|
|
237
355
|
"NSApplicationIdentifier": "com.apple.finder"
|
238
356
|
},
|
239
357
|
"NSSendFileTypes": file_types if file_types else [],
|
240
|
-
"NSSendTypes": ["NSFilenamesPboardType"]
|
358
|
+
"NSSendTypes": ["NSFilenamesPboardType"], # Always include this to ensure paths are passed correctly
|
359
|
+
"NSUserData": name,
|
360
|
+
"NSExecutable": "script", # Ensure macOS knows which script to run
|
361
|
+
"NSReturnTypes": []
|
241
362
|
}
|
242
363
|
]
|
243
364
|
}
|
244
365
|
|
245
366
|
info_path = os.path.join(contents_dir, "Info.plist")
|
246
367
|
with open(info_path, "wb") as f:
|
247
|
-
plistlib.dump(info_plist, f)
|
248
|
-
|
249
|
-
# Create script file
|
368
|
+
plistlib.dump(info_plist, f)
|
250
369
|
script_dir = os.path.join(contents_dir, "MacOS")
|
251
370
|
os.makedirs(script_dir, exist_ok=True)
|
252
371
|
script_path = os.path.join(script_dir, "script")
|
253
372
|
|
254
373
|
with open(script_path, "w") as f:
|
255
|
-
f.write(command)
|
256
|
-
|
257
|
-
# Make the script executable
|
374
|
+
f.write(command)
|
258
375
|
os.chmod(script_path, 0o755)
|
259
|
-
|
260
|
-
# Create document.wflow file with a basic workflow definition
|
261
376
|
workflow = {
|
262
377
|
"AMApplication": "Automator",
|
263
|
-
"AMCanShowSelectedItemsWhenRun":
|
378
|
+
"AMCanShowSelectedItemsWhenRun": True,
|
264
379
|
"AMCanShowWhenRun": True,
|
265
380
|
"AMDockBadgeLabel": "",
|
266
381
|
"AMDockBadgeStyle": "badge",
|
@@ -272,7 +387,11 @@ class MacOSContextMenuIntegration:
|
|
272
387
|
"parameters": {
|
273
388
|
"shell": "/bin/bash",
|
274
389
|
"script": command,
|
275
|
-
"input": "as arguments"
|
390
|
+
"input": "as arguments",
|
391
|
+
"showStdout": True,
|
392
|
+
"showStderr": True,
|
393
|
+
"showOutput": True,
|
394
|
+
"runAsAdmin": False
|
276
395
|
}
|
277
396
|
}
|
278
397
|
],
|
@@ -283,107 +402,113 @@ class MacOSContextMenuIntegration:
|
|
283
402
|
},
|
284
403
|
"AMWorkflowSchemeVersion": 2.0,
|
285
404
|
}
|
286
|
-
|
287
405
|
with open(document_path, "wb") as f:
|
288
406
|
plistlib.dump(workflow, f)
|
289
407
|
|
290
408
|
return action_dir
|
291
|
-
|
409
|
+
|
410
|
+
def _extension_to_uti(self, extension):
|
411
|
+
"""Convert a file extension to macOS UTI (Uniform Type Identifier)."""
|
412
|
+
uti_map = UTI_MAPPINGS
|
413
|
+
ext = extension.lower().lstrip('.')
|
414
|
+
return uti_map.get(ext, f'public.{ext}')
|
415
|
+
|
292
416
|
def _generate_audio_extension_actions(self):
|
293
417
|
"""Generate Quick Actions for supported audio file extensions."""
|
294
418
|
extensions = [ext.lower().lstrip('.') for ext in SUPPORTED_EXTENSIONS]
|
295
|
-
|
296
|
-
|
419
|
+
# Convert extensions to UTIs (Uniform Type Identifiers)
|
420
|
+
utis = [self._extension_to_uti(ext) for ext in extensions]
|
297
421
|
self._create_quick_action(
|
298
422
|
"TonieToolbox - Convert to TAF",
|
299
423
|
self.convert_cmd,
|
300
|
-
file_types=
|
424
|
+
file_types=utis
|
301
425
|
)
|
302
426
|
|
303
427
|
if self.upload_enabled:
|
304
428
|
self._create_quick_action(
|
305
429
|
"TonieToolbox - Convert and Upload",
|
306
430
|
self.upload_cmd,
|
307
|
-
file_types=
|
431
|
+
file_types=utis
|
308
432
|
)
|
309
433
|
|
310
434
|
self._create_quick_action(
|
311
435
|
"TonieToolbox - Convert, Upload with Artwork",
|
312
436
|
self.upload_artwork_cmd,
|
313
|
-
file_types=
|
437
|
+
file_types=utis
|
314
438
|
)
|
315
439
|
|
316
440
|
self._create_quick_action(
|
317
441
|
"TonieToolbox - Convert, Upload with Artwork and JSON",
|
318
442
|
self.upload_artwork_json_cmd,
|
319
|
-
file_types=
|
443
|
+
file_types=utis
|
320
444
|
)
|
321
|
-
|
445
|
+
|
322
446
|
def _generate_taf_file_actions(self):
|
323
447
|
"""Generate Quick Actions for .taf files."""
|
448
|
+
taf_uti = self._extension_to_uti("taf") # Use UTI for TAF files
|
449
|
+
|
324
450
|
self._create_quick_action(
|
325
451
|
"TonieToolbox - Show Info",
|
326
452
|
self.show_info_cmd,
|
327
|
-
file_types=[
|
453
|
+
file_types=[taf_uti]
|
328
454
|
)
|
329
455
|
|
330
456
|
self._create_quick_action(
|
331
457
|
"TonieToolbox - Extract Opus Tracks",
|
332
458
|
self.extract_opus_cmd,
|
333
|
-
file_types=[
|
459
|
+
file_types=[taf_uti]
|
334
460
|
)
|
335
461
|
|
336
462
|
if self.upload_enabled:
|
337
463
|
self._create_quick_action(
|
338
464
|
"TonieToolbox - Upload",
|
339
465
|
self.upload_taf_cmd,
|
340
|
-
file_types=[
|
466
|
+
file_types=[taf_uti]
|
341
467
|
)
|
342
|
-
|
343
468
|
self._create_quick_action(
|
344
469
|
"TonieToolbox - Upload with Artwork",
|
345
470
|
self.upload_taf_artwork_cmd,
|
346
|
-
file_types=[
|
471
|
+
file_types=[taf_uti]
|
347
472
|
)
|
348
473
|
|
349
474
|
self._create_quick_action(
|
350
475
|
"TonieToolbox - Upload with Artwork and JSON",
|
351
476
|
self.upload_taf_artwork_json_cmd,
|
352
|
-
file_types=[
|
477
|
+
file_types=[taf_uti]
|
478
|
+
)
|
479
|
+
|
480
|
+
self._create_quick_action(
|
481
|
+
"TonieToolbox - Compare with another TAF file",
|
482
|
+
self.compare_taf_cmd,
|
483
|
+
file_types=[taf_uti]
|
353
484
|
)
|
354
485
|
|
355
|
-
self._create_quick_action(
|
356
|
-
"TonieToolbox - Compare with another TAF file",
|
357
|
-
self.compare_taf_cmd,
|
358
|
-
file_types=["taf"]
|
359
|
-
)
|
360
|
-
|
361
486
|
def _generate_folder_actions(self):
|
362
487
|
"""Generate Quick Actions for folders."""
|
363
488
|
self._create_quick_action(
|
364
|
-
"TonieToolbox - Convert Folder to TAF (recursive)",
|
489
|
+
"TonieToolbox - 1. Convert Folder to TAF (recursive)",
|
365
490
|
self.convert_folder_cmd,
|
366
491
|
directory_based=True
|
367
492
|
)
|
368
493
|
|
369
494
|
if self.upload_enabled:
|
370
495
|
self._create_quick_action(
|
371
|
-
"TonieToolbox - Convert Folder and Upload (recursive)",
|
496
|
+
"TonieToolbox - 2. Convert Folder and Upload (recursive)",
|
372
497
|
self.upload_folder_cmd,
|
373
498
|
directory_based=True
|
374
499
|
)
|
375
500
|
|
376
501
|
self._create_quick_action(
|
377
|
-
"TonieToolbox - Convert Folder, Upload with Artwork (recursive)",
|
502
|
+
"TonieToolbox - 3. Convert Folder, Upload with Artwork (recursive)",
|
378
503
|
self.upload_folder_artwork_cmd,
|
379
504
|
directory_based=True
|
380
505
|
)
|
381
506
|
|
382
507
|
self._create_quick_action(
|
383
|
-
"TonieToolbox - Convert Folder, Upload with Artwork and JSON (recursive)",
|
508
|
+
"TonieToolbox - 4. Convert Folder, Upload with Artwork and JSON (recursive)",
|
384
509
|
self.upload_folder_artwork_json_cmd,
|
385
510
|
directory_based=True
|
386
|
-
)
|
511
|
+
)
|
387
512
|
|
388
513
|
def install_quick_actions(self):
|
389
514
|
"""
|
@@ -409,15 +534,14 @@ class MacOSContextMenuIntegration:
|
|
409
534
|
# Refresh the Services menu by restarting the Finder
|
410
535
|
result = subprocess.run(["killall", "-HUP", "Finder"], check=False,
|
411
536
|
capture_output=True, text=True)
|
412
|
-
|
413
|
-
|
414
|
-
print("You'll find them in the Services menu when right-clicking on audio files, TAF files, or folders.")
|
537
|
+
logger.info("TonieToolbox Quick Actions installed successfully.")
|
538
|
+
logger.info("You'll find them in the Services menu when right-clicking on audio files, TAF files, or folders.")
|
415
539
|
|
416
540
|
return True
|
417
541
|
except Exception as e:
|
418
542
|
logger.error(f"Failed to install Quick Actions: {e}")
|
419
543
|
return False
|
420
|
-
|
544
|
+
|
421
545
|
def uninstall_quick_actions(self):
|
422
546
|
"""
|
423
547
|
Uninstall all TonieToolbox Quick Actions.
|
@@ -444,7 +568,9 @@ class MacOSContextMenuIntegration:
|
|
444
568
|
return not any_failures
|
445
569
|
except Exception as e:
|
446
570
|
logger.error(f"Failed to uninstall Quick Actions: {e}")
|
447
|
-
return False
|
571
|
+
return False
|
572
|
+
|
573
|
+
@classmethod
|
448
574
|
def install(cls):
|
449
575
|
"""
|
450
576
|
Generate Quick Actions and install them.
|
@@ -1,12 +1,12 @@
|
|
1
|
-
TonieToolbox/__init__.py,sha256=
|
1
|
+
TonieToolbox/__init__.py,sha256=03DkelZsljyJIZJPxhaIrnGaLVecnU_C3sxGmHN3a_0,98
|
2
2
|
TonieToolbox/__main__.py,sha256=pD-goy-ke-M3Z8zkbUgW1IF94UQPGQSHql15yeBBDzk,34040
|
3
3
|
TonieToolbox/artwork.py,sha256=fOlYx1cffVq-2u1e_qiW5bd3LpPCGMmIfZAxIwC05tA,4451
|
4
4
|
TonieToolbox/audio_conversion.py,sha256=0GpC6mSRYikIjf_A1w26LAnYtCP2gpHLEKozOISapnM,17190
|
5
|
-
TonieToolbox/constants.py,sha256=
|
6
|
-
TonieToolbox/dependency_manager.py,sha256=
|
5
|
+
TonieToolbox/constants.py,sha256=4L-lOX0_UBt3Xo5_Y2tVKhlHCRysjTIbC-cdlE7lNl0,8104
|
6
|
+
TonieToolbox/dependency_manager.py,sha256=GB1RlXNkRHsEd4m7x45-uqly6kVbnyr9wlOmxHzAzgc,28392
|
7
7
|
TonieToolbox/filename_generator.py,sha256=ATCG4w8uN1vyAqvmdhOtpJLlb9QFKCnYIdBViYqpHjw,3464
|
8
8
|
TonieToolbox/integration.py,sha256=NEQpKQSwLa6el7DoIqWbscBUGmRrYls_UiSmmvpSpxw,2785
|
9
|
-
TonieToolbox/integration_macos.py,sha256=
|
9
|
+
TonieToolbox/integration_macos.py,sha256=bWAQ-vWrQK-KluL3NYdZexEUBwnkL_-tasFgkHL3yK4,26907
|
10
10
|
TonieToolbox/integration_ubuntu.py,sha256=MU6W0xRCdoHBxrIiOIHePqYTF5Wvn4JxBnDQUPf6fgg,33
|
11
11
|
TonieToolbox/integration_windows.py,sha256=SSVg-9bf8wDQMuJgg-j_6cUczcx7H1-C1mbEIlNJlzs,23691
|
12
12
|
TonieToolbox/logger.py,sha256=Q_cXbCWfzNmt5q6fvVzeM8IugkD24CSZAVjuf16n6b4,3120
|
@@ -22,9 +22,9 @@ TonieToolbox/tonie_header.proto,sha256=WaWfwO4VrwGtscK2ujfDRKtpeBpaVPoZhI8iMmR-C
|
|
22
22
|
TonieToolbox/tonie_header_pb2.py,sha256=s5bp4ULTEekgq6T61z9fDkRavyPM-3eREs20f_Pxxe8,3665
|
23
23
|
TonieToolbox/tonies_json.py,sha256=YGS2wtaDudxxSy7QuRLWaE5n4bf_AyoSvVLH1Vdh8SE,60754
|
24
24
|
TonieToolbox/version_handler.py,sha256=MLpJ9mSEHkcSoyePnACpfINHTSB1q1_4iEgcT1tGqNU,10028
|
25
|
-
tonietoolbox-0.6.
|
26
|
-
tonietoolbox-0.6.
|
27
|
-
tonietoolbox-0.6.
|
28
|
-
tonietoolbox-0.6.
|
29
|
-
tonietoolbox-0.6.
|
30
|
-
tonietoolbox-0.6.
|
25
|
+
tonietoolbox-0.6.0a3.dist-info/licenses/LICENSE.md,sha256=rGoga9ZAgNco9fBapVFpWf6ri7HOBp1KRnt1uIruXMk,35190
|
26
|
+
tonietoolbox-0.6.0a3.dist-info/METADATA,sha256=N6HxrJmWGLbiTvwXInNLMHsptNPJagYkg3TACTODc0M,26849
|
27
|
+
tonietoolbox-0.6.0a3.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
|
28
|
+
tonietoolbox-0.6.0a3.dist-info/entry_points.txt,sha256=oqpeyBxel7aScg35Xr4gZKnf486S5KW9okqeBwyJxxc,60
|
29
|
+
tonietoolbox-0.6.0a3.dist-info/top_level.txt,sha256=Wkkm-2p7I3ENfS7ZbYtYUB2g-xwHrXVlERHfonsOPuE,13
|
30
|
+
tonietoolbox-0.6.0a3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|