mpg123 aus C-Programm ansprechen - mit API?

Herakles

Profifragensteller
Moin!

Ich möchte gern auf einem Gerät ohne Bildschirm (Alix) einen mp3-Player ansteuern. Recht schnell fiel meine Aufmerksamkeit auf mpg123.

Nachdem ich ein wenig damit herumgespielt habe, frage ich mich nun, wie ich am cleversten auf diesen mp3-Dekodierer zugreife. Ich möchte die Software aus einem eigenen C-Programm ansprechen. Ist es da wohl da cleverste, die API von mpg123 zu nutzen?

Ich frage deswegen, weil ich dann ja eigentlich "das Rad neu erfinden müsste", denn im Prinzip macht ein fertig kompiliertes mpg123 ja schon das, was ich will - mp3 abspielen. Nur ansprechen kann ich es nicht aus meinem C-Programm heraus.

Ich habe bei anderen Projekten geschaut, die ebenfalls mpg123 nutzen (beispielweise musikcube2) und dort scheint es wirklich so zu sein, dass die API zum abspielen von mp3s verwand wird.

Das wäre allerdings viel Arbeit, weil ich mich komplett in die API von mpg123 einarbeiten müsste. Ich frage nur deswegen, weil ich befürchte, vor lauter Bäumen den Wald nicht zu sehen. Für mich wäre es doch einfacher, mpg123 fertig kompiliert zu nutzen, als die API zu bemühen, oder nicht?? :confused:

Ich bin dankbar für jede Idee an dieser Stelle.

Herzliche Grüße,
Herakles
 
Schau dir mal die exec-Familie an. Damit kannst eine Datei "ausführen". Das passiert dann in einem neuen Prozess, wenn ich mich recht entsinne.

man 3 exec

Wenn du wissenwillst, wann der Song zuende ist, also mpg123 sich beendet, dann ist wait/waitpid etwas für dich: man waitpid

(Die Manpages gibt es so auf meinem OSX)

Aber der Weg über die API ist sicherlich eleganter!

Sharoz
 
oder du rufst es per system(char *) auf. Die funktion gibt dann erst nen Wert zurück, wenn mpg123 beendet ist. Und zwar den Wert, mit dem mpg123 beendet wurde. Kommt halt drauf an in welchem Stil du es benutzen willst. Kannst ja noch stderr in 'ne Datei umleiten, und den Inhalt ausgeben, falls system 'nen Wert ungleich 0 zurückgibt. Mit waitpid kannst du glaube aber auch den Rückgabewert herausfinden und bei der Methode ist es halt der Vorteil, dass das Programm nicht geblockt wird.
 
Kannst dann halt nich mpg123 steuern. Schöner, und letztendlich wahrscheinlich auch einfacher ist es eine library (mit einer API) zu benutzen.
 
Genau das, was FreeBSDuser zuletzt anfügte, ist mein eigentliches Problem - ich will natürlich in der Lage sein, ein Lied während der Wiedergabe zu pausieren oder es vor- und zurückspulen. Das geht dann offenbar nur mit der API.

Die Sache mit exec(3) war mit auch schon in den Sinn gekommen, weil system(3) erst zurückkehrt, wenn mpg123 zuende ist, was ich ja nicht will.

Dass das der elegantere Weg sein würde, hatte ich mir schon gedacht, vor Allem, weil man mit der API eben die volle Kontrolle behält, nur ist der Weg eben steiniger. Hm. Na, da muss ich dann wohl durch. Danke für Eure Gedanken zum Thema!

Herakles
 
Grundsätzlich die API. Dafür ist sie da. system, exec, und Konsorten sind dafür gedacht Apps zu nutzen, für die es keine Schnittstellen gibt. Es kommt auch niemand auf die Idee system("echo -en \"Hallo Welt\n\") in ein Programm zu schreiben.
Äh, ich hoffe zumindest, das macht niemand ;-)
 
Danke, Xantus! Aber die Beispiele kannte ich schon - was ich suche, ist sowas wie "mp3-Datei in Sound umwandeln mit libmpg123 für Dummies". Denn eine mp3-Datei abspielen machen alle vier Beispiele auf der Seite eben nicht...

Ich hexe schon seit Stunden herum und finde einfach nicht den Weg zum Ziel :(
 
Ob C oder Python - ich denke, es geht eher darum zu wissen, welche Bibliotheksfunktionen von der mpg123-lib in welcher Reihenfolge angesprochen werden müssen und wie ich eine Ausgabe von dekodierten mp3-Daten auf der Soundkarte hinbekomme.

Herakles
 
nutzt der mpg123 player denn nicht auch die lib ? - in dem source könnte man doch nachschauen, sollte ja (hoffentlich) nich all zu viel code sein.

EDIT: mpg123 ist ja nicht die einzige mp3-decoder lib.
 
Danke, Xantus! Aber die Beispiele kannte ich schon - was ich suche, ist sowas wie "mp3-Datei in Sound umwandeln mit libmpg123 für Dummies". Denn eine mp3-Datei abspielen machen alle vier Beispiele auf der Seite eben nicht...

Ich hexe schon seit Stunden herum und finde einfach nicht den Weg zum Ziel :(

Ich hab nochmal deinen ersten Post überflogen - warum schaust du nicht im Source von mpg123 nach? Oder bau dir eine Binary von mpg123 mit Debugsymbolen und schau dir im Debugger an, was aufgerufen wird, wenn du eine mp3 abspielst. Und dann schaust du dir die Funktionen noch genauer im Quelltext an.
 
Das hatte ich mal vor nen paar Wochen zusammengehauen, vorsichet dreckeliger code:

Code:
from threading import Thread
import mad
import ao

class madplayer(object):
	def __init__(self, path):
		self.pauseit = False
		self.stopit = False
		self.thread = None
		self.path = path
		self.status = 0
		self.madfile = mad.MadFile(path)
		self.dev = ao.AudioDevice('oss', rate=self.madfile.samplerate())
	
	def play(self):
		if not self.status == 1:
			self.stopit = False
			self.pauseit = False
			self.thread = Thread(target=self.player)
			self.thread.start()
	
	def player(self):
		self.status = 1
		while True:
			buf = self.madfile.read()
			if buf != None:
				self.dev.play(buf)
			else:
				print "End of Input"
				self.status = 0
				self.madfile.seek_time(0)
				break
			if self.pauseit == True:
				self.status = 2
				print "Paused"
				break
			elif self.stopit == True:
				self.status = 0
				self.madfile.seek_time(0)
				self.madfile.read()
				print "Stopped"
				break
	
	def forward(self, secs):
		self.madfile.seek_time(min((self.madfile.total_time() - self.madfile.current_time()), secs*1000)+self.madfile.current_time())
	
	def backward(self, secs):
			self.madfile.seek_time(self.madfile.current_time() - min(self.madfile.current_time(), secs*1000))
	
	def pause(self):
		self.pauseit = True
	
	def stop(self):
		if self.status == 1:
			self.stopit = True
		else:
			self.madfile.seek_time(0)
			self.madfile.read()
 
Danke, Xantus! Aber die Beispiele kannte ich schon - was ich suche, ist sowas wie "mp3-Datei in Sound umwandeln mit libmpg123 für Dummies". Denn eine mp3-Datei abspielen machen alle vier Beispiele auf der Seite eben nicht...

Eine verbreitet Fehleinschätzung scheint zu sein, dass libmpg123 eine Koplettbibliothek für einen "MP3-Player" ist.
http://mpg123.org/api ist für eine Sache da: Das Dekodieren von MPEG-Audio Datenströmen (z.B. Dateien) zu rohen PCM Samples.
Diese Samples kann man an die Standardausgabe weiterleiten (und von dort gar UNIX-artig einfach nach /dev/dsp oder /dev/audio schreiben, wenn das Format passt!) oder in eine WAV-Datei schreiben (was eines der Beispiele mit libsndfile macht).

Was dir fehlt, ist die Ausgabe auf die Soundkarte. Das ist eine Sache, die so direkt nix mit libmpg123 zu tun hat. Dazu ist u.a. die Hauptanwendung mpg123 da. Man siehe sich src/audio.c und src/output/sun.c für Ausgabe auf einem BSD-System an (bzw. src/output/oss.c).
Spätestens, wenn du ein Programm schreibst, das ein paar Formate wiedegeben kann, wird auffallen, dass die Ausgaberoutinen in der MPEG Dekodierbibliothek falsch aufgehoben sind.

So, um aber zum Punkt zu kommen: Am einfachsten mag es sein, die Kontrollschnittstelle von mpg123 zu benutzen:

mpg123 -R

liest Komandos von der Standardeingabe... z.B.

LOAD track.mp3
PAUSE
PAUSE
JUMP 200

Bei neueren Versionen gibt es auch
mpg123 --fifo /tmp/mpg123-command

Mit dem gehorcht mpg123 auf sowas:
echo "LOAD track.mp3" > /tmp/mpg123-command

Ich denke, damit sollte sich ein einfacher interaktiver Player am schnellsten bewerkstelligen lassen. Ansonsten: Frag doch auch im IRC auf freenode #mpg123 oder der mpg123-users mailingliste.
 
@sobukus: Danke für die tolle Antwort!

Inzwischen mache ich etwas ähnliches, wie Du es vorgeschlagen hast - ich nutze den "Slave"-Modus vom mplayer. Der kann auch genau das, was ich will. Auch dort arbeite ich mit FIFOs, mit zweien, einem für Befehle an mplayer und einem anderen für output vom mplayer zurück.

Herakles
 
Zurück
Oben