Difference between revisions of "DAB/DAB+"
(→C API) |
(→C API) |
||
Line 137: | Line 137: | ||
=== C API === | === C API === | ||
− | This API works with Linux and MacOS. The Application needs to be linked against libmcsimple.[so/dylib] which connects via unix domain sockets to the driver service which runs as a server. | + | This API works with Linux and MacOS. The Application needs to be linked against libmcsimple.[so/dylib] which connects via unix domain sockets to the driver service which runs as a server. The driver accesses the native USB userspace interface on each system. |
It can be found in /opt/lib. | It can be found in /opt/lib. | ||
Revision as of 11:15, 29 July 2019
Contents
DAB/DAB+
The DAB/DAB+ USB Stick decodes DAB/DAB+ onchip and transfers the decoded audio data fully digital to the host system. Currently Linux and MacOS are supported.
Installation Linux
open a terminal and enter following commands:
sudo -s wget http://sundtek.de/media/sundtek_netinst.sh chmod 777 sundtek_netinst.sh ./sundtek_netinst.sh
In case you want to distribute the local stations digitally you can also install our streaming server (again on the commandline)
just run following commands: sudo -s /opt/bin/mediaclient --installstreamer
In case you want to use our DAB/DAB+ Player for X86-64 Bit Linux:
http://sundtek.de/media/Sundtek_DAB_FM_Radio-x86_64-2019-07-28_07_05.AppImage
Be sure you set the downloaded binary to executable before trying to run it (right mouse click, permissions, check executable)
Installation MacOSX
MacOSX:
- https://www.sundtek.de/media/sundtek_driver_macosx_190728.0349.dmg - https://www.sundtek.de/media/sundtek_dab_fm_player_190728.0245.dmg
First install the driver, afterwards run the DAB Player. The split driver also allows other application developer to integrate and use those devices.
Installation Raspberry PI
In case you don't want to use our radio application, the installation is the same as on a regular linux system
sudo -s wget http://sundtek.de/media/sundtek_netinst.sh chmod 777 sundtek_netinst.sh ./sundtek_netinst.sh
Radio Application:
cd $HOME sudo apt-get install qt5-default wget http://sundtek.de/media/dablet_raspbian.tar.gz tar xf dablet_raspbian.tar.gz ./dablet
DAB/DAB+ commandline interface
scan for transponders:
/opt/bin/mediaclient --scandabfrequencies /dev/dab0 scanning: 5A / 174928000 scanning: 5B / 176640000 scanning: 5C / 178352000 [LOCKED] scanning: 5D / 180064000 scanning: 6A / 181936000 scanning: 6B / 183648000 scanning: 6C / 185360000 scanning: 6D / 187072000 scanning: 7A / 188928000 scanning: 7B / 190640000 [LOCKED] scanning: 7C / 192352000 scanning: 7D / 194064000 [LOCKED] scanning: 8A / 195936000
tune to a transponder:
/opt/bin/mediaclient -m DAB -f 194064000 Using device: /dev/dab0 Tuning: 194064000 [LOCKED]
turn on direct audio playback in the driver (the driver will try to play back audio via alsa, pulseaudio or oss:
/opt/bin/mediaclient -m DAB -g off
scan a dab transponder:
/opt/bin/mediaclient --scandabservices /dev/dab0 Service Name, Service ID, Component ID BR-Klassik 0xd314 0xb Inforadio 0xd335 0x8 FH Europa 0xd496 0x3 radioeins 0xd332 0x1 radioBERLIN 88 8 0xd321 0x6 kulturradio 0xd323 0x5 Fritz 0xd333 0x7 Antenne 0xd431 0x0 SWR3 0xd3a3 0x4 Bayern 2 0xd412 0xc WDR2 0xd392 0x2 MDR JUMP 0xd3c2 0xd rbb TPEG 0xe0d11019 0xc00a rbb EPG 0xe0d01019 0xc009
Tune to a specific DAB station:
/opt/bin/mediaclient -m DAB -f 194064000 --sid 0xd321 Using device: /dev/dab0 Tuning: 194064000, 0xd321 [LOCKED]
Read signal statistics:
/opt/bin/mediaclient --readsignal=0 -d /dev/dab0 FREQUENCY: 178352000 LOCKED: YES RSSI: 172 SNR: 10 FIC_QUALITY: 100 CNR: 14 FREQUENCY: 178352000 LOCKED: YES RSSI: 173 SNR: 10 FIC_QUALITY: 100 CNR: 13 FREQUENCY: 178352000 LOCKED: YES RSSI: 172 SNR: 10 FIC_QUALITY: 100 CNR: 12 FREQUENCY: 178352000 LOCKED: YES RSSI: 173 SNR: 10 FIC_QUALITY: 100 CNR: 13 FREQUENCY: 178352000 LOCKED: YES RSSI: 173 SNR: 10 FIC_QUALITY: 100 CNR: 13 FREQUENCY: 178352000 LOCKED: YES RSSI: 173 SNR: 9 FIC_QUALITY: 100 CNR: 12 FREQUENCY: 178352000 LOCKED: YES RSSI: 173 SNR: 9 FIC_QUALITY: 100 CNR: 12
C API
This API works with Linux and MacOS. The Application needs to be linked against libmcsimple.[so/dylib] which connects via unix domain sockets to the driver service which runs as a server. The driver accesses the native USB userspace interface on each system. It can be found in /opt/lib.
The driver package uses LD_PRELOAD, /etc/ld.so.preload, for developers and integrators who directly access the driver this is not needed, be sure you install the driver with the -service flag ./sundtek_netinst.sh -service, full driver releases (no netinst versions) can be downloaded from https://sundtek.de/media The driver package also includes drivers for Sundtek TV devices.
All devices come with a unique serial number, the serial numbers can be used for handling multiple devices and storing unique channel lists.
Basically the API needs only a few commands:
fd = net_open("/dev/radio0", O_RDWR); // open device node net_ioctl(fd, command, parameter); net_close(fd);
Additional features are available, eg. detect connect/disconnect devices dynamically. Headers are available in /opt/include, libraries in /opt/lib
DAB Scan for Frequencies
example:
int media_scan_dabfrequencies(char *device, int devfd, int console, int running) { int fd; int rv; 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); rv=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) { rv=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) { rv=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; }
DAB Scan for Services
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; }
DAB Get Date
int media_dab_get_date(char *device) { int fd; struct dab_time t; printf("opening device: %s\n", device); fd = net_open(device, O_RDWR); memset(&t, 0x0, sizeof(struct dab_time)); if (fd>=0) { printf("GET DAB TIME:\n"); net_ioctl(fd, DAB_GET_TIME, &t); printf("%d-%d-%d %d:%d:%d\n", t.year, t.months, t.days, t.hours, t.minutes, t.seconds); net_close(fd); } return 0; }
DAB get Ensemble Info
int media_dab_get_ensemble_info(char *device) { int fd; struct dab_ensemble_info info; printf("opening device: %s\n", device); fd = net_open(device, O_RDWR); if (fd>=0) { printf("GET ENSEMBLE INFO:\n"); net_ioctl(fd, DAB_GET_ENSEMBLE_INFO, &info); printf("Ensemble Label: %s\n", info.label); net_close(fd); } return 0; }
DAB Tune Service
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; }
FM/DAB Mute
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; }
FM Scan Frequencies
int media_scan_fmfrequencies(char *device, int devfd, int console, int running) { int fd; int rv; int nlen; char tmp[30]; if (devfd>=0) fd = devfd; else { printf("opening device: %s\n", device); fd = net_open(device, O_RDWR); } if (fd>=0) { int i; int e; int current_scan_index=-1; struct fm_scan_setup setup; struct fm_scan_parameters parameters; memset(¶meters, 0x0, sizeof(struct fm_scan_parameters)); memset(&setup, 0x0, sizeof(struct fm_scan_setup)); printf("SCAN SETUP\n"); net_ioctl(fd, FM_SCAN_SETUP, &setup); do { net_ioctl(fd, FM_SCAN_NEXT_FREQUENCY, ¶meters); // printf("LOCK STAT: %x - %d - %d\n", parameters.status, parameters.VALID, parameters.READFREQ); switch(parameters.status) { case FM_SCAN_LOCKED: { if (console>=0) { printf("FREQUENCY: %d ", parameters.READFREQ); rv=write(console, "[LOCKED]\n", 9); } else { fprintf(stdout, "%d [LOCKED]\n", parameters.READFREQ); } break; } case FM_SCAN_SEARCHING: usleep(10000); break; case FM_SCAN_COMPLETE: { if (console>=0) { rv=write(console, "[FINISHED]\n", 11); } else { fprintf(stdout, "\nScan completed\n"); } break; } } if (console>=0 && running == 0) break; } while (parameters.status != FM_SCAN_COMPLETE); if (devfd == -1) net_close(fd); } return 0; }
FM Set Radio Frequency
int set_radio_channel(int fd, int frequency, int tuner) { struct v4l2_frequency freq; memset(&freq, 0x0, sizeof(struct v4l2_frequency)); freq.frequency = frequency/1000*16; freq.type = V4L2_TUNER_RADIO; freq.tuner = tuner; net_ioctl(fd, VIDIOC_S_FREQUENCY, &freq); return 0; }
FM Read RDS Data
net_ioctl(rdsfd, FM_RDS_STATUS, &data); struct fm_rds_data { uint8_t rdssync; /* rds synchronized */ uint8_t pivalid; /* program identification */ uint8_t tpptyvalid; /* traffic program / program type*/ uint16_t PI; /* program identification */ uint8_t PTY; /* program type */ uint8_t data[8]; /* representing the RDS blocks */ } __attribute__((packed));
etc.
There are a few more features, in case you need more details just contact us.