@wooper: Einwandfrei, naja. Wenn man eine Playlist abgespielt hat, dann bleibt die ja bestehen, das heisst man kann dann immer nur noch weitere Dateien hinzufügen, aber die alten werden auch immer wieder abgespielt.
Zudem ist die Playlist letztlich eine globale Variable. Das macht man nicht. Der Name `path` für eine Liste mehreren Pfaden ist auch falsch. Wenn der Benutzer Abspielen wählt bevor er Dateien zu der Liste (kein Array, wie im Kommentar fälschlicherweise behauptet) hinzugefügt hat, wird trotzdem versucht ``mplayer`` auszuführen, was keinen Sinn macht.
Den Rückgabewert von `App.run()` an den Namen `app` zu binden macht keinen Sinn.
Der `Object`-Zusatz in `FormObject` ist sinnlos. Klar ist das ein Objekt das man damit erstellt – in Python ist *alles* ein Objekt was man an einen Namen binden kann.
Bei `MyButtonPress` macht das `My` keinen Sinn. Am Namen sollte man erkennen können was das Objekt repräsentiert, nicht wem es ”gehört”. Nach der Logik müsste man ja vor jeden selbst definierten Namen ein `my` setzen.
Warum die Rückgabewerte von den `add()`-Aufrufen an das `Form`-Objekt gebunden werden ist mir jetzt nicht so wirklich ersichtlich.
Bei `selectFile()` beim `select_dir`-Argument eine leere Zeichenkette zu übergeben ist falsch. Da wird ein `bool` erwartet und eine leere Zeichenkette verwirrt bloss den Leser und hat zudem auch noch den Effekt vom Default-Wert `False`. An der Stelle würde es Sinn machen `must_exist` anzugeben, damit der Benutzer nur Dateien eingeben kann die auch tatsächlich existieren.
``for i in range(len(sequence)):`` nur um `i` dann als Index in das Sequenzobjekt zu verwenden, ist in Python ein „anti-pattern“. Das macht man nicht. Man kann direkt über die Elemente einer Sequenz iterieren, ohne den Umweg über einen Index. Falls man *zusätzlich* eine laufende Zahl benötigt, gibt es die `enumerate()`-Funktion.
Die Zahl wird hier aber nur verwendet um den ersten Schleifendurchlauf von allen anderen zu unterscheiden. Da sollte man den Code aber eher umschreiben, so dass das nicht mehr nötig ist. Die "&&" sollen zwischen alle ``mplayer``-Aufrufe, also würde man erst die ganzen Aufrufe formatieren und dann am Emde die "&&" per `str.join()`-Methode dazwischen setzen. Die ganze `play_vid()` würde dann nur noch so aussehen:
Code: Alles auswählen
def play_vid(self)
os.system(
" && ".join(
f"mplayer -really-quiet -vo caca {path}" for path in self.paths
)
)
Wie schon geschrieben wurde ist `os.system()` aber die falsche Funktion. Wenn man Glück hat, dann funktioniert es einfach nur nicht, beispielsweise wenn Dateinamen mit Leerzeichen oder Zeichen die eine besondere Bedeutung für die Shell haben vorkommen, wie Zeilenumbrüche, Klammern, Anführungszeichen (einzeln/doppelt), Dollarzeichen, Semikolons, &-Zeichen, …. Wenn man Pech hat, benennt jemand absichtlich eine Datei so, dass dem Benutzerkonto alle Dateien gelöscht werden.
Die ``&&`` sind etwas was eine Shell ausführt, die kann man natürlich nicht `subprocess.call()` mitgeben, weil das keine Shell zwischen Deinem Programm und ``mplayer`` setzt, sondern ``mplayer`` direkt startet und dem dann einfach die "&&" also normale Argumente mit gibt, womit ``mplayer`` aber nichts anfangen kann. Wenn Du mehrere ``mplayer``-Aufrufe nacheinander ausführen willst, dann musst Du das halt tun, in einer Schleife.
Nur sehr oberflächlich getestet:
Code: Alles auswählen
#!/usr/bin/env python3
import os
import subprocess
import npyscreen
class SelectMediaButton(npyscreen.ButtonPress):
def __init__(self, *args, **kwargs):
self.paths = kwargs.pop("paths")
npyscreen.ButtonPress.__init__(self, *args, **kwargs)
def whenPressed(self):
self.paths.append(
os.path.realpath(npyscreen.selectFile(must_exist=True))
)
class PlayButton(npyscreen.ButtonPress):
def __init__(self, *args, **kwargs):
self.paths = kwargs.pop("paths")
npyscreen.ButtonPress.__init__(self, *args, **kwargs)
def whenPressed(self):
try:
for path in self.paths:
subprocess.run(
["mplayer", "-really-quiet", "-vo", "caca", path],
check=True,
)
except subprocess.CalledProcessError:
#
# Beim ersten ``mplayer``-Aufruf der einen Fehlercode liefert
# abbrechhen, genau wie eine Verkettung der Aufrufe in einer Shell
# mit ``&&`` das tun würde.
#
pass
class Form(npyscreen.ActionFormMinimal, npyscreen.SplitForm):
def create(self):
self.paths = list()
self.show_atx = 10
self.show_aty = 2
self.add(SelectMediaButton, name="Select Media", paths=self.paths)
self.nextrely += 1
self.add(PlayButton, name="Play Media", paths=self.paths)
self.nextrely += 1
self.add(npyscreen.TitleFixedText, name="Press OK to exit")
def on_ok(self):
npyscreen.notify_confirm("Good Bye!", editw=1)
self.parentApp.setNextForm(None)
class App(npyscreen.NPSAppManaged):
def onStart(self):
self.addForm(
"MAIN",
Form,
name="Mediaplayer done simple",
lines=20,
columns=60,
draw_line_at=17,
)
if __name__ == "__main__":
App().run()