(13.07.2018, 06:12)Der kleine Punky schrieb: @sundtek
Hätte auch Interesse am Stick. Aber ich benutze keine Kodi sondern C++ vielleicht hilft das.
Die Tuner sind ja eh bestellbar, Versand ist ab Anfang nächster Woche.
net_open -> open
net_close -> close
net_ioctl -> ioctl
Sicherer ist aber net_* und dann gegen /opt/bin/libmcsimple.so zu linken, dann funktioniert der Code auch unter MacOSX oder über JNI unter Android (oder sobald unser Windows Compatibility Layer mal freigegeben wird auch unter Windows).
DAB Client code:
Parameter:
device ... Gerätepfad
devfd ... Filehandle vom Tuner
running ... sollte -1 sein
Code:
int media_scan_dabfrequencies(char *device, int devfd, int console, int running) {
int fd;
int nlen;
char tmp[30];
if (devfd>=0)
fd = devfd;
else
fd = net_open(device, O_RDWR);
if (fd>=0) {
struct dab_frequency dabf;
struct dab_tuner dabt;
int i;
int e;
int current_scan_index=-1;
struct dab_scan_setup setup;
struct dab_scan_parameters parameters;
memset(¶meters, 0x0, sizeof(struct dab_scan_parameters));
memset(&setup, 0x0, sizeof(struct dab_scan_setup));
net_ioctl(fd, DAB_SCAN_SETUP, &setup);
do {
net_ioctl(fd, DAB_SCAN_NEXT_FREQUENCY, ¶meters);
if (current_scan_index != parameters.scan_index) {
if (console>=0) {
sprintf(tmp, "%s %d\n", dab_frequency_list[parameters.scan_index].channel, dab_frequency_list[parameters.scan_index].freq*1000);
write(console, tmp, nlen);
} else {
fprintf(stdout, "%s %d\n", dab_frequency_list[parameters.scan_index].channel, dab_frequency_list[parameters.scan_index].freq*1000);
fflush(stdout);
}
}
switch(parameters.status) {
case DAB_SCAN_LOCKED:
{
if (console>=0) {
write(console, "[LOCKED]\n", 9);
} else {
fprintf(stdout, "[LOCKED]\n");
}
break;
}
case DAB_SCAN_SEARCHING:
usleep(10000);
break;
case DAB_SCAN_COMPLETE:
{
if (console>=0) {
write(console, "[FINISHED]\n", 11);
} else {
fprintf(stdout, "\nScan completed\n");
}
break;
}
}
current_scan_index = parameters.scan_index;
if (console>=0 && running == 0)
break;
} while (parameters.status != DAB_SCAN_COMPLETE);
if (devfd == -1)
net_close(fd);
}
return 0;
}
Scanne DAB Services (gibt SID Und Component ID zurück):
Code:
int media_scan_dabservices(char *device) {
int fd;
int rv;
int i=0;
fd = net_open(device, O_RDWR);
if (fd>=0) {
struct dab_service service;
printf("Service Name, Service ID, Component ID\n");
while(1) {
service.id=i++;
rv = net_ioctl(fd, DAB_GET_SERVICE, &service);
if (rv == -1)
break;
printf("%16s\t0x%x\t0x%x\n", service.service_name, service.sid, service.comp[0]);
}
net_close(fd);
}
return 0;
}
Sender konfigurieren:
Code:
int set_dab_channel(int fd, uint32_t frequency, uint32_t sid, uint8_t sid_set, uint32_t comp, uint8_t comp_set) {
struct dab_frequency dabf;
memset(&dabf, 0x0, sizeof(struct dab_frequency));
if (sid_set && comp_set)
printf("Tuning: %d, 0x%x, 0x%x\n", frequency, sid, comp);
else if (sid_set)
printf("Tuning: %d, 0x%x\n", frequency, sid);
else
printf("Tuning: %d\n", frequency);
dabf.frequency = frequency;
if (sid_set) {
dabf.sid_set = 1;
dabf.sid = sid;
}
if (comp_set) {
dabf.comp = comp;
dabf.comp_set = 1;
}
net_ioctl(fd, DAB_SET_FREQUENCY, &dabf);
return 0;
}
Code:
int get_dab_lock(int fd) {
int i=5;
struct dab_tuner dabt;
memset(&dabt, 0x0, sizeof(struct dab_tuner));
for (i=0;i<10;i++) {
net_ioctl(fd, DAB_GET_TUNER, &dabt);
if (dabt.status & DAB_HAS_LOCK) {
printf("[LOCKED]");
break;
} else {
printf(".");
}
usleep(10000);
}
printf("\n");
return 0;
}
Folgende Funktion startet das Playback von Audio direkt im Treiber.
fd sollte der Filehandle zu /dev/dab0 sein (oder /dev/dabX bei mehreren Empfängern).
Code:
int set_mute(int fd, char *arg) {
int type = 0;
struct v4l2_control control;
if (strcmp(arg, "off") == 0) {
control.id = V4L2_CID_AUDIO_MUTE;
control.value = 0;
fprintf(stdout, "Enabling audiostream\n");
net_ioctl(fd, VIDIOC_S_CTRL, &control);
} else if (strcmp(arg, "on") == 0) {
fprintf(stdout, "Disabling audiostream\n");
control.id = V4L2_CID_AUDIO_MUTE;
control.value = 1;
net_ioctl(fd, VIDIOC_S_CTRL, &control);
} else
fprintf(stdout, "Wrong argument [%s] choose between on|off\n", arg);
return 0;
}
Die PCM Samples kann man mittels read() von /dev/dab0 auslesen, by default Spielt ja der Treiber Audio ab, dieses Verhalten kann man auch ausschalten.
Eine Besonderheit hier ist dass die PCM Samples auch WAV Header beinhalten, wer keine WAV Header benötigt sollte die Samples von /dev/dsp0 auslesen.
Das war jetzt nur mal der DAB Bereich, FM Radio kann über /dev/radio0 ausgelesen und konfiguriert werden, wir halten uns hierbei an den offiziellen Video4Linux Standard.
Die DAB Schnittstelle ist eine Eigenentwicklung da Linux dafür keine offiziellen Schnittstellen hat.
Wer sich etwas mit der FM Radio Video4Linux API auskennt wird hier Ähnlichkeiten sehen. Die Befehle sind in /opt/include/mediacmds.h definiert.
Einfacher geht's über unseren Streamingserver "rtspd"
/opt/bin/mediaclient --installstreamer
dann im Web http://localhost:22000 die DAB Frequenzen scannen / Playlisten konfigurieren - und via HTTP streamen.
Das ist dann komplett unabhängig von jeder Spezial-API.