Forum: Mikrocontroller und Digitale Elektronik MPD steuern und auslesen mit libmpdclient


von Stoffel (Gast)


Lesenswert?

Hallo,

hier habe ich bereits einen Anfang gefunden.
https://www.mikrocontroller.net/articles/MPD_Client_Programming

Da geht es lediglich um das steuern des MPD Servers mithilfe von C. Das 
klappt bei mir auch soweit schon ganz in Ordnung, habe nur ein bisschen 
getestet. Syntax ist nicht ganz wie dort angegeben zB. erwartet 
mpd_send_pause mehr als 1 Attribut.

Nun jedoch möchte ich auch den Status des Displays ablesen und auf ein 
LCD16x02/20x04 Display darstellen. Die Libery verfügt leider aber über 
kein übersichtliches Tutorial/ Wiki oder Dokumentation.

http://www.musicpd.org/libs/libmpdclient/
1
int main(void)
2
{
3
  struct mpd_status *status;
4
  printf("%03i\n", mpd_status_get_volume(status));
5
}
 geht es leider nicht.

von Nickname (Gast)


Lesenswert?

Hi,

schau Dir mal die Quellen von lcd4linux an, wo dies bereits 
implementiert wurde.

https://lcd4linux.bulix.org/browser/trunk/plugin_mpd.c


Vom Prinzip her sind folgende Lib-Aufrufe notwendig, (auf die schnelle 
ohne eine Fehlerbehandlung)
1
conn = mpd_connection_new(host, iport, TIMEOUT_IN_S * 1000);
2
if (*pw && !mpd_run_password(conn, pw) { ... }
3
4
mpd_command_list_begin(conn, true);
5
mpd_send_status(conn);
6
mpd_command_list_end(conn);
7
status = mpd_recv_status(conn);
8
l_volume = mpd_status_get_volume(status);
9
10
mpd_connection_free(conn);

MfG, Nick

von musical native (Gast)


Lesenswert?

wäre mpc keine handliche Alternative?

von Stoffel (Gast)


Lesenswert?

Hallo musical native,

ja wäre es. Damit habe ich mich zu anfang mit beschäftigt. Aber es wird 
immer wieder gesagt, dass man nicht zwingend mit fopen alles abfragen 
soll. Die Ausgaben gibt es ja teilweise gut formatiert.

von Stoffel (Gast)


Lesenswert?

Könnte mir wer hier einen einfachen Code in C bereit stellen, der einen 
Linux Shell Befehl an die Console abgibt und den Rückgabewert einließt?
1
[root@alarmpi mpd]# mpc -f "%artist%"
1
Fall Out Boy
2
[playing] #4/24   1:42/3:52 (43%)
3
volume: 65%   repeat: on    random: on    single: off   consume: off

von Stoffel (Gast)


Lesenswert?

Hab es nun mal so versucht,
1
  char command[] = "mpc -f \"\%artist\%\"";
2
  char Buffer[200];
3
  FILE *f = popen("mpc", "r");
4
  if (f != NULL) {
5
    while (fgets(Buffer, sizeof(Buffer), f) != NULL) printf("%s\n", Buffer);
6
    pclose(f);
7
  }
8
9
  int i = 0;
10
  while (Buffer[i] != '\n') {
11
    title[i] += Buffer[i]; i++;
12
  }
13
  title[i + 1] = '\0';
14
  printf(":%s:\n", title);

Die Ausgabe passt leider nicht zu [*]mpc -f "%artist"[/*]
1
Slipknot - Duality
2
3
[playing] #2/24   1:17/4:15 (30%)
4
5
volume: 36%   repeat: on    random: on    single: off   consume: off
6
7
:volume: 36%   repeat: on    random: on    single: off   consume: off:

von Stoffel (Gast)


Lesenswert?

1
void getInfo(void)
2
{
3
  char command[] = "mpc -f \"\%artist\%\"";
4
  char Buffer[200];
5
  FILE *f = popen("mpc", "r");
6
  
7
  if (f != NULL) {
8
    while (fgets(Buffer, sizeof(Buffer), f) != NULL); // printf("%s", Buffer);
9
    pclose(f);
10
  }
11
  else printf("File konnte nicht geoeffnet werden\n");
12
13
  printf("<\n%s>\n", Buffer);
14
}

Das Problem scheint zu sein, dass hier nur die letzte Zeile ausgelesen 
wird, bzw. übergeben wird. Leider kann ich mit mpc nicht einzelne Zeilen 
ausgeben, die letzten beiden kommen immer, egal welches Format ich 
verwende.

von Stoffel (Gast)


Lesenswert?

Ich bin nun ein ganzes Stück weitergekommen. Nun habe ich die 
Möglichkeit, Titel und Künstler auszulesen.
1
int readStream(void)
2
{
3
4
  readLine(0, "mpc -f \"\%artist\%\"");
5
  strncpy(artist, buffer, MAX_BUFFER);
6
  artist[sizeof(artist) - 2] = ' ';
7
8
  readLine(0, "mpc -f \"\%title\%\"");
9
  strncpy(title, buffer, MAX_BUFFER);
10
11
  readLine(2, "mpc -f \" \"");  // Platzhalter
12
  strncpy(line1, buffer, MAX_BUFFER);
13
  if (strstr(line1, "[playing]")) state = 2;
14
  else if (strstr(line1, "[paused]")) state = 1;
15
  else state = 0;
16
17
  readLine(3, "mpc");
18
  strncpy(line2, buffer, MAX_BUFFER);
19
}
20
21
int readLine(int line, char* cmd)
22
{
23
  char Buffer[200];
24
  FILE *f = popen(cmd, "r");
25
  char *ptr;
26
  int i;
27
28
  // verwerfen
29
  for (i = 0; i < line - 1; i++) if (fgets(tempBuffer, MAX_BUFFER, f) == NULL) return (int)NULL;
30
  // schreiben
31
  if (fgets(buffer, MAX_BUFFER, f))
32
  {
33
    ptr = strchr(buffer, '\n');
34
    if (ptr) *ptr = '\0';
35
    return (int)NULL;
36
  }
37
}

Nun die Frage, wie kann ich folgende Zeilen am besten splitten, sodass 
ich folgende Werte erhalte
1
[playing] #8/24   3:23/3:27 (98%)
2
volume:  9%   repeat: on    random: on    single: off   consume: off

Nach playing und pause kann ich bereits suchen.
Nun müsste ich noch folgende Werte erhalten

#8/24 -> int actTrack = 8; int maxTrack = 24;
3:23/3:27 -> char chElapTime[] = {"3:23"}; char chTotalTime = {"3:27"};
volume:  9% -> int vol = 9;
repeat: on -> int repeat = 1;
....

von neuer PIC Freund (Gast)


Lesenswert?

Mit
http://libmpdclient.sourcearchive.com/documentation/2.2/example_8c-source.html

und
1
gcc example.c -lmpdclient && ./a.out

ergibt sich innerhalb 1 Minute spielend leicht:
1
version[0]: 0
2
version[1]: 19
3
version[2]: 0
4
volume: 97
5
repeat: 0
6
queue version: 2
7
queue length: 14
8
song: 6
9
elaspedTime: 56
10
elasped_ms: 55511
11
totalTime: 345
12
bitRate: 192
13
sampleRate: 44100
14
bits: 24
15
channels: 2
16
uri: Iron Maiden - 06 - Strange World.mp3
17
artist: Iron Maiden
18
album: Iron Maiden
19
title: Strange World
20
date: 1981
21
time: 345
22
pos: 6

Du kannst natürlich auch den output von mpc mit RE zerfleischen. Viel 
Spass.

von Stoffel (Gast)


Lesenswert?

Hallo,

ja ich hab nochmals die lib angeschaut. Hab nun auch alles soweit 
auslesen können, solange es keine Zeichenkette ist.

Folgendes Problem, ich würde gerne die MP3-Tags auslesen und in ein 
struct speichern, um es entsprechend aufrufen zu können.

1
#define MAX 30
2
struct mpd_tags {
3
  char artist[MAX];
4
  char title[MAX];
5
};
6
7
static void mpd_get_tags(struct mpd_tags *tags, const struct mpd_song *song) {
8
  unsigned i = 0;
9
  const char *value;
10
11
  while ((artist = mpd_song_get_tag(song, MPD_TAG_ARTIST, i++)) != NULL)
12
  {
13
  strcpy(tags->artist, value);
14
  }
15
  i = 0;
16
17
  while ((title = mpd_song_get_tag(song, MPD_TAG_TITLE, i++)) != NULL)
18
  {
19
  strcpy(tags->title, value);
20
21
  }
22
  printf(tags->artist); printf("\n");
23
  printf(tags->title); printf("\n");
24
}
25
26
int main (void)
27
{
28
  struct mpd_tags *tags;
29
  while (1) {
30
    if (state == MPD_STATE_PLAY || state == MPD_STATE_PAUSE) {
31
      mpd_get_tags(tags, song);
32
      if (song != NULL) {
33
        lcdPosition(lcd, 0, 0);
34
        lcdPuts(lcd, tags->artist);
35
        lcdPosition(lcd, 0, 1);
36
        lcdPuts(lcd, tags->title);
37
38
        mpd_song_free(song);
39
      }
40
    }
41
  }
42
}

Hier erhalte ich den Fehler

lcd.c: In function 'mpd_get_tags':
error: 'artist' undeclared (first use in this function)
  while ((artist = mpd_song_get_tag(song, MPD_TAG_ARTIST, i++)) != NULL)
          ^
note: each undeclared identifier is reported only once for each function 
it appears in
error: 'title' undeclared (first use in this function)
  while ((title = mpd_song_get_tag(song, MPD_TAG_TITLE, i++)) != NULL)
          ^

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.