mkv2cast 1.2.7.post4__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.
@@ -0,0 +1,382 @@
1
+ # Italian translations for mkv2cast
2
+ # Copyright (C) 2024-2026 voldardard
3
+ # This file is distributed under the GPL-3.0 license.
4
+ #
5
+ msgid ""
6
+ msgstr ""
7
+ "Project-Id-Version: mkv2cast 1.1.0\n"
8
+ "Report-Msgid-Bugs-To: https://github.com/voldardard/mkv2cast/issues\n"
9
+ "POT-Creation-Date: 2026-01-18 00:00+0000\n"
10
+ "PO-Revision-Date: 2026-01-18 00:00+0000\n"
11
+ "Last-Translator: voldardard\n"
12
+ "Language-Team: Italian\n"
13
+ "Language: it\n"
14
+ "MIME-Version: 1.0\n"
15
+ "Content-Type: text/plain; charset=UTF-8\n"
16
+ "Content-Transfer-Encoding: 8bit\n"
17
+
18
+ # General
19
+ msgid "Processing file: {filename}"
20
+ msgstr "Elaborazione file: {filename}"
21
+
22
+ msgid "Conversion complete"
23
+ msgstr "Conversione completata"
24
+
25
+ msgid "Conversion failed"
26
+ msgstr "Conversione fallita"
27
+
28
+ msgid "Skipped: {reason}"
29
+ msgstr "Saltato: {reason}"
30
+
31
+ msgid "No MKV files to process."
32
+ msgstr "Nessun file MKV da elaborare."
33
+
34
+ msgid "Backend selected"
35
+ msgstr "Backend selezionato"
36
+
37
+ # Progress
38
+ msgid "Checking integrity..."
39
+ msgstr "Verifica integrità..."
40
+
41
+ msgid "Encoding..."
42
+ msgstr "Codifica..."
43
+
44
+ msgid "Waiting for file stability..."
45
+ msgstr "Attesa stabilità del file..."
46
+
47
+ msgid "Done"
48
+ msgstr "Fatto"
49
+
50
+ msgid "Failed"
51
+ msgstr "Fallito"
52
+
53
+ msgid "Skipped"
54
+ msgstr "Saltato"
55
+
56
+ # Summary
57
+ msgid "Summary"
58
+ msgstr "Riepilogo"
59
+
60
+ msgid "Total files seen"
61
+ msgstr "File totali visti"
62
+
63
+ msgid "Transcoded OK"
64
+ msgstr "Transcodificati OK"
65
+
66
+ msgid "Total time"
67
+ msgstr "Tempo totale"
68
+
69
+ # Notifications
70
+ msgid "mkv2cast - Conversion Complete"
71
+ msgstr "mkv2cast - Conversione completata"
72
+
73
+ msgid "Successfully converted 1 file in {time}"
74
+ msgstr "1 file convertito con successo in {time}"
75
+
76
+ msgid "Successfully converted {count} files in {time}"
77
+ msgstr "{count} file convertiti con successo in {time}"
78
+
79
+ msgid "mkv2cast - Conversion Failed"
80
+ msgstr "mkv2cast - Conversione fallita"
81
+
82
+ msgid "Failed to convert 1 file"
83
+ msgstr "Impossibile convertire 1 file"
84
+
85
+ msgid "Failed to convert {count} files"
86
+ msgstr "Impossibile convertire {count} file"
87
+
88
+ msgid "mkv2cast - Processing Complete"
89
+ msgstr "mkv2cast - Elaborazione completata"
90
+
91
+ msgid "{count} converted"
92
+ msgstr "{count} convertito/i"
93
+
94
+ msgid "{count} failed"
95
+ msgstr "{count} fallito/i"
96
+
97
+ msgid "{count} skipped"
98
+ msgstr "{count} saltato/i"
99
+
100
+ msgid "mkv2cast - Interrupted"
101
+ msgstr "mkv2cast - Interrotto"
102
+
103
+ msgid "Processing was interrupted by user"
104
+ msgstr "L'elaborazione è stata interrotta dall'utente"
105
+
106
+ # Errors
107
+ msgid "File not found"
108
+ msgstr "File non trovato"
109
+
110
+ msgid "Only .mkv files supported"
111
+ msgstr "Solo file .mkv supportati"
112
+
113
+ msgid "integrity check failed"
114
+ msgstr "verifica integrità fallita"
115
+
116
+ msgid "compatible"
117
+ msgstr "compatibile"
118
+
119
+ # CLI
120
+ msgid "Smart MKV -> Cast compatible converter with VAAPI/QSV hardware acceleration."
121
+ msgstr "Convertitore intelligente MKV -> Cast con accelerazione hardware VAAPI/QSV."
122
+
123
+ msgid "Optional .mkv file to process"
124
+ msgstr "File .mkv opzionale da elaborare"
125
+
126
+ msgid "Output settings"
127
+ msgstr "Impostazioni output"
128
+
129
+ msgid "Scan settings"
130
+ msgstr "Impostazioni scansione"
131
+
132
+ msgid "Debug/test"
133
+ msgstr "Debug/test"
134
+
135
+ msgid "Enable debug output"
136
+ msgstr "Abilita output di debug"
137
+
138
+ msgid "Dry run"
139
+ msgstr "Modalità simulazione"
140
+
141
+ msgid "Codec decisions"
142
+ msgstr "Decisioni codec"
143
+
144
+ msgid "Encoding quality"
145
+ msgstr "Qualità codifica"
146
+
147
+ msgid "Hardware acceleration"
148
+ msgstr "Accelerazione hardware"
149
+
150
+ msgid "Integrity checks"
151
+ msgstr "Verifiche integrità"
152
+
153
+ msgid "UI settings"
154
+ msgstr "Impostazioni interfaccia"
155
+
156
+ msgid "Pipeline mode"
157
+ msgstr "Modalità pipeline"
158
+
159
+ msgid "Parallelism"
160
+ msgstr "Parallelismo"
161
+
162
+ msgid "Notifications"
163
+ msgstr "Notifiche"
164
+
165
+ msgid "Send desktop notification when done (default: enabled)"
166
+ msgstr "Invia notifica desktop al termine (default: abilitato)"
167
+
168
+ msgid "Disable desktop notifications"
169
+ msgstr "Disabilita notifiche desktop"
170
+
171
+ msgid "Internationalization"
172
+ msgstr "Internazionalizzazione"
173
+
174
+ msgid "Force language (default: auto-detect)"
175
+ msgstr "Forza lingua (default: auto-rilevamento)"
176
+
177
+ msgid "Utility commands"
178
+ msgstr "Comandi utilità"
179
+
180
+ # Utility
181
+ msgid "Requirements Check"
182
+ msgstr "Verifica requisiti"
183
+
184
+ msgid "System requirements"
185
+ msgstr "Requisiti di sistema"
186
+
187
+ msgid "mandatory"
188
+ msgstr "obbligatorio"
189
+
190
+ msgid "Optional dependencies"
191
+ msgstr "Dipendenze opzionali"
192
+
193
+ msgid "All requirements satisfied"
194
+ msgstr "Tutti i requisiti soddisfatti"
195
+
196
+ msgid "Some requirements missing"
197
+ msgstr "Alcuni requisiti mancanti"
198
+
199
+ msgid "directories"
200
+ msgstr "directory"
201
+
202
+ msgid "User directories"
203
+ msgstr "Directory utente"
204
+
205
+ msgid "Removed"
206
+ msgstr "Rimosso"
207
+
208
+ msgid "temp files"
209
+ msgstr "file temporanei"
210
+
211
+ msgid "log files older than"
212
+ msgstr "file log più vecchi di"
213
+
214
+ msgid "days"
215
+ msgstr "giorni"
216
+
217
+ msgid "history entries"
218
+ msgstr "voci cronologia"
219
+
220
+ msgid "No conversion history found."
221
+ msgstr "Nessuna cronologia conversioni trovata."
222
+
223
+ msgid "Recent conversions"
224
+ msgstr "Conversioni recenti"
225
+
226
+ msgid "last"
227
+ msgstr "ultime"
228
+
229
+ msgid "Conversion statistics"
230
+ msgstr "Statistiche conversione"
231
+
232
+ msgid "Total conversions"
233
+ msgstr "Conversioni totali"
234
+
235
+ msgid "Average encode time"
236
+ msgstr "Tempo medio codifica"
237
+
238
+ msgid "Total encode time"
239
+ msgstr "Tempo totale codifica"
240
+
241
+ msgid "Stopping"
242
+ msgstr "Arresto"
243
+
244
+ msgid "processes"
245
+ msgstr "processi"
246
+
247
+ msgid "All processes stopped"
248
+ msgstr "Tutti i processi arrestati"
249
+
250
+ # Pipeline mode strings
251
+ msgid "Backend"
252
+ msgstr "Backend"
253
+
254
+ msgid "Workers"
255
+ msgstr "Worker"
256
+
257
+ msgid "encode"
258
+ msgstr "codifica"
259
+
260
+ msgid "integrity"
261
+ msgstr "integrità"
262
+
263
+ msgid "Files"
264
+ msgstr "File"
265
+
266
+ msgid "to process"
267
+ msgstr "da elaborare"
268
+
269
+ msgid "Found"
270
+ msgstr "Trovati"
271
+
272
+ msgid "file(s) to process"
273
+ msgstr "file da elaborare"
274
+
275
+ msgid "Converted"
276
+ msgstr "Convertiti"
277
+
278
+ # Rich UI strings
279
+ msgid "SKIP"
280
+ msgstr "SALTATO"
281
+
282
+ msgid "DONE"
283
+ msgstr "FATTO"
284
+
285
+ msgid "FAIL"
286
+ msgstr "FALLITO"
287
+
288
+ msgid "QUEUE"
289
+ msgstr "CODA"
290
+
291
+ msgid "CHECK"
292
+ msgstr "VERIF"
293
+
294
+ msgid "ENCODE"
295
+ msgstr "CODIF"
296
+
297
+ msgid "int"
298
+ msgstr "ver"
299
+
300
+ msgid "enc"
301
+ msgstr "cod"
302
+
303
+ msgid "tot"
304
+ msgstr "tot"
305
+
306
+ msgid "error"
307
+ msgstr "errore"
308
+
309
+ msgid "check"
310
+ msgstr "verif"
311
+
312
+ msgid "in queue"
313
+ msgstr "in coda"
314
+
315
+ msgid "Waiting for check"
316
+ msgstr "In attesa di verifica"
317
+
318
+ msgid "file(s)"
319
+ msgstr "file"
320
+
321
+ msgid "Initializing..."
322
+ msgstr "Inizializzazione..."
323
+
324
+ msgid "output exists"
325
+ msgstr "output esistente"
326
+
327
+ msgid "tmp exists"
328
+ msgstr "file temp esistente"
329
+
330
+ msgid "dryrun"
331
+ msgstr "simulazione"
332
+
333
+ msgid "integrity failed"
334
+ msgstr "integrità fallita"
335
+
336
+ msgid "integrity error"
337
+ msgstr "errore integrità"
338
+
339
+ msgid "analysis error"
340
+ msgstr "errore analisi"
341
+
342
+ msgid "encode error"
343
+ msgstr "errore codifica"
344
+
345
+ msgid "move error"
346
+ msgstr "errore spostamento"
347
+
348
+ msgid "interrupted"
349
+ msgstr "interrotto"
350
+
351
+ msgid "OK"
352
+ msgstr "OK"
353
+
354
+ msgid "in"
355
+ msgstr "in"
356
+
357
+ msgid "FAILED"
358
+ msgstr "FALLITO"
359
+
360
+ msgid "Already compatible"
361
+ msgstr "Già compatibile"
362
+
363
+ # Multi-user cleanup
364
+ msgid "Running as root - cleaning tmp for all users..."
365
+ msgstr "Esecuzione come root - pulizia tmp per tutti gli utenti..."
366
+
367
+ msgid "Running as root - cleaning logs for all users..."
368
+ msgstr "Esecuzione come root - pulizia log per tutti gli utenti..."
369
+
370
+ msgid "files removed"
371
+ msgstr "file rimossi"
372
+
373
+ msgid "Total removed"
374
+ msgstr "Totale rimossi"
375
+
376
+ # AMD AMF
377
+ msgid "AMD AMF quality (0-51)"
378
+ msgstr "Qualità AMD AMF (0-51)"
379
+
380
+ # JSON Progress
381
+ msgid "Output JSON progress for integration with other applications"
382
+ msgstr "Output JSON del progresso per integrazione con altre applicazioni"
@@ -0,0 +1,196 @@
1
+ """
2
+ Desktop notification support for mkv2cast.
3
+
4
+ Sends system notifications when conversions complete.
5
+ Uses notify-send (libnotify) as primary method with plyer as fallback.
6
+ """
7
+
8
+ import shutil
9
+ import subprocess
10
+ from typing import Literal, Optional
11
+
12
+ from mkv2cast.i18n import _
13
+
14
+
15
+ # Check for notification capabilities
16
+ def _has_notify_send() -> bool:
17
+ """Check if notify-send is available."""
18
+ return shutil.which("notify-send") is not None
19
+
20
+
21
+ def _has_plyer() -> bool:
22
+ """Check if plyer is available."""
23
+ try:
24
+ from plyer import notification # noqa: F401
25
+
26
+ return True
27
+ except ImportError:
28
+ return False
29
+
30
+
31
+ NOTIFY_SEND_AVAILABLE = _has_notify_send()
32
+ PLYER_AVAILABLE = _has_plyer()
33
+
34
+
35
+ def send_notification(
36
+ title: str,
37
+ message: str,
38
+ urgency: Literal["low", "normal", "critical"] = "normal",
39
+ icon: str = "video-x-generic",
40
+ timeout: int = 10,
41
+ ) -> bool:
42
+ """
43
+ Send a desktop notification.
44
+
45
+ Tries notify-send first (Linux standard), then falls back to plyer
46
+ if available.
47
+
48
+ Args:
49
+ title: Notification title.
50
+ message: Notification body text.
51
+ urgency: Urgency level - "low", "normal", or "critical".
52
+ icon: Icon name (XDG icon spec) or path.
53
+ timeout: Notification timeout in seconds.
54
+
55
+ Returns:
56
+ True if notification was sent successfully, False otherwise.
57
+ """
58
+ # Try notify-send first (Linux standard via libnotify)
59
+ if NOTIFY_SEND_AVAILABLE:
60
+ try:
61
+ cmd = [
62
+ "notify-send",
63
+ "--urgency",
64
+ urgency,
65
+ "--app-name",
66
+ "mkv2cast",
67
+ "--icon",
68
+ icon,
69
+ "--expire-time",
70
+ str(timeout * 1000), # Convert to ms
71
+ title,
72
+ message,
73
+ ]
74
+ subprocess.run(cmd, check=True, capture_output=True, timeout=5)
75
+ return True
76
+ except (subprocess.CalledProcessError, subprocess.TimeoutExpired):
77
+ pass
78
+
79
+ # Fallback to plyer
80
+ if PLYER_AVAILABLE:
81
+ try:
82
+ from plyer import notification
83
+
84
+ notification.notify(
85
+ title=title,
86
+ message=message,
87
+ app_name="mkv2cast",
88
+ app_icon=icon if icon.startswith("/") else None,
89
+ timeout=timeout,
90
+ )
91
+ return True
92
+ except Exception:
93
+ pass
94
+
95
+ return False
96
+
97
+
98
+ def notify_success(converted_count: int, total_time: str) -> bool:
99
+ """
100
+ Send a success notification.
101
+
102
+ Args:
103
+ converted_count: Number of files successfully converted.
104
+ total_time: Total processing time as formatted string.
105
+
106
+ Returns:
107
+ True if notification sent successfully.
108
+ """
109
+ title = _("mkv2cast - Conversion Complete")
110
+
111
+ if converted_count == 1:
112
+ message = _("Successfully converted 1 file in {time}").format(time=total_time)
113
+ else:
114
+ message = _("Successfully converted {count} files in {time}").format(count=converted_count, time=total_time)
115
+
116
+ return send_notification(title=title, message=message, urgency="normal", icon="dialog-information")
117
+
118
+
119
+ def notify_failure(failed_count: int, error_summary: Optional[str] = None) -> bool:
120
+ """
121
+ Send a failure notification.
122
+
123
+ Args:
124
+ failed_count: Number of files that failed.
125
+ error_summary: Optional brief error description.
126
+
127
+ Returns:
128
+ True if notification sent successfully.
129
+ """
130
+ title = _("mkv2cast - Conversion Failed")
131
+
132
+ if failed_count == 1:
133
+ message = _("Failed to convert 1 file")
134
+ else:
135
+ message = _("Failed to convert {count} files").format(count=failed_count)
136
+
137
+ if error_summary:
138
+ message += f"\n{error_summary}"
139
+
140
+ return send_notification(title=title, message=message, urgency="critical", icon="dialog-error")
141
+
142
+
143
+ def notify_partial(ok_count: int, failed_count: int, skipped_count: int, total_time: str) -> bool:
144
+ """
145
+ Send a notification for partial success (some files converted, some failed/skipped).
146
+
147
+ Args:
148
+ ok_count: Number of successful conversions.
149
+ failed_count: Number of failed conversions.
150
+ skipped_count: Number of skipped files.
151
+ total_time: Total processing time as formatted string.
152
+
153
+ Returns:
154
+ True if notification sent successfully.
155
+ """
156
+ title = _("mkv2cast - Processing Complete")
157
+
158
+ parts = []
159
+ if ok_count > 0:
160
+ parts.append(_("{count} converted").format(count=ok_count))
161
+ if failed_count > 0:
162
+ parts.append(_("{count} failed").format(count=failed_count))
163
+ if skipped_count > 0:
164
+ parts.append(_("{count} skipped").format(count=skipped_count))
165
+
166
+ message = ", ".join(parts)
167
+ message += f" ({total_time})"
168
+
169
+ urgency: Literal["low", "normal", "critical"] = "normal" if failed_count == 0 else "critical"
170
+ icon = "dialog-information" if failed_count == 0 else "dialog-warning"
171
+
172
+ return send_notification(title=title, message=message, urgency=urgency, icon=icon)
173
+
174
+
175
+ def notify_interrupted() -> bool:
176
+ """Send a notification when processing was interrupted by the user."""
177
+ return send_notification(
178
+ title=_("mkv2cast - Interrupted"),
179
+ message=_("Processing was interrupted by user"),
180
+ urgency="normal",
181
+ icon="dialog-warning",
182
+ )
183
+
184
+
185
+ def check_notification_support() -> dict:
186
+ """
187
+ Check available notification methods.
188
+
189
+ Returns:
190
+ Dict with 'notify_send' and 'plyer' boolean keys indicating availability.
191
+ """
192
+ return {
193
+ "notify_send": NOTIFY_SEND_AVAILABLE,
194
+ "plyer": PLYER_AVAILABLE,
195
+ "any": NOTIFY_SEND_AVAILABLE or PLYER_AVAILABLE,
196
+ }