/***************************************************************** * \brief step channel up or down * \parameter direction RADIO_CHANNEL_LOWER - go to prev channel,RADIO_CHANNEL_HIGHER - to next * \return 1 if success,0 - otherwise * * if channel parameter is NULL function prints error message and does nothing, otherwise * changes channel to prev or next in list */ int radio_step_channel(struct stream *stream, int direction) { radio_priv_t* priv=(radio_priv_t*)stream->priv; if (priv->radio_channel_list) { switch (direction) { case RADIO_CHANNEL_HIGHER: if (priv->radio_channel_current->next) priv->radio_channel_current = priv->radio_channel_current->next; else priv->radio_channel_current = priv->radio_channel_list; if(!radio_set_freq(stream,priv->radio_channel_current->freq)) return 0; mp_tmsg(MSGT_RADIO, MSGL_V, "[radio] Selected channel: %d - %s (freq: %.2f)\n", priv->radio_channel_current->index, priv->radio_channel_current->name, priv->radio_channel_current->freq); break; case RADIO_CHANNEL_LOWER: if (priv->radio_channel_current->prev) priv->radio_channel_current = priv->radio_channel_current->prev; else while (priv->radio_channel_current->next) priv->radio_channel_current = priv->radio_channel_current->next; if(!radio_set_freq(stream,priv->radio_channel_current->freq)) return 0; mp_tmsg(MSGT_RADIO, MSGL_V, "[radio] Selected channel: %d - %s (freq: %.2f)\n", priv->radio_channel_current->index, priv->radio_channel_current->name, priv->radio_channel_current->freq); break; } } else mp_tmsg(MSGT_RADIO, MSGL_ERR, "[radio] Can not change channel: no channel list given.\n"); return 1; }
/***************************************************************** * \brief step channel up or down * \parameter direction RADIO_CHANNEL_LOWER - go to prev channel,RADIO_CHANNEL_HIGHER - to next * \return 1 if success,0 - otherwise * * if channel parameter is NULL function prints error message and does nothing, otherwise * changes channel to prev or next in list */ int radio_step_channel(struct stream_st *stream, int direction) { radio_priv_t* priv=(radio_priv_t*)stream->priv; if (priv->radio_channel_list) { switch (direction){ case RADIO_CHANNEL_HIGHER: if (priv->radio_channel_current->next) priv->radio_channel_current = priv->radio_channel_current->next; else priv->radio_channel_current = priv->radio_channel_list; if(!radio_set_freq(stream,priv->radio_channel_current->freq)) return 0; mp_msg(MSGT_RADIO, MSGL_V, MSGTR_RADIO_SelectedChannel, priv->radio_channel_current->index, priv->radio_channel_current->name, priv->radio_channel_current->freq); break; case RADIO_CHANNEL_LOWER: if (priv->radio_channel_current->prev) priv->radio_channel_current = priv->radio_channel_current->prev; else while (priv->radio_channel_current->next) priv->radio_channel_current = priv->radio_channel_current->next; if(!radio_set_freq(stream,priv->radio_channel_current->freq)) return 0; mp_msg(MSGT_RADIO, MSGL_V, MSGTR_RADIO_SelectedChannel, priv->radio_channel_current->index, priv->radio_channel_current->name, priv->radio_channel_current->freq); break; } }else mp_msg(MSGT_RADIO, MSGL_ERR, MSGTR_RADIO_ChangeChannelNoChannelList); return 1; }
/***************************************************************** * \brief tune current frequency by step_interval value * \parameter step_interval increment value * \return 1 if success,0 - otherwise * */ int radio_step_freq(struct stream *stream, float step_interval) { float frequency; radio_priv_t* priv=(radio_priv_t*)stream->priv; if (get_frequency(priv,&frequency)!=STREAM_OK) return 0; frequency+=step_interval; if (frequency>priv->rangehigh) frequency=priv->rangehigh; if (frequency<priv->rangelow) frequency=priv->rangelow; return radio_set_freq(stream,frequency); }
/***************************************************************** * \brief change channel to one with given index * \parameter channel string, containing channel number * \return 1 if success,0 - otherwise * * if channel parameter is NULL function prints error message and does nothing, otherwise * changes channel to given */ int radio_set_channel(struct stream *stream, char *channel) { radio_priv_t* priv=(radio_priv_t*)stream->priv; int i, channel_int; radio_channels_t* tmp; char* endptr; if (*channel=='\0') mp_tmsg(MSGT_RADIO,MSGL_ERR,"[radio] Wrong channel name: %s\n",channel); if (priv->radio_channel_list) { channel_int = strtol(channel,&endptr,10); tmp = priv->radio_channel_list; if (*endptr!='\0') { //channel is not a number, so it contains channel name for ( ; tmp; tmp=tmp->next) if (!strncmp(channel,tmp->name,sizeof(tmp->name)-1)) break; if (!tmp) { mp_tmsg(MSGT_RADIO,MSGL_ERR,"[radio] Wrong channel name: %s\n",channel); return 0; } } else { for (i = 1; i < channel_int; i++) if (tmp->next) tmp = tmp->next; else break; if (tmp->index!=channel_int) { mp_tmsg(MSGT_RADIO,MSGL_ERR,"[radio] Wrong channel number: %d\n",channel_int); return 0; } } priv->radio_channel_current=tmp; mp_tmsg(MSGT_RADIO, MSGL_V, "[radio] Selected channel: %d - %s (freq: %.2f)\n", priv->radio_channel_current->index, priv->radio_channel_current->name, priv->radio_channel_current->freq); if(!radio_set_freq(stream, priv->radio_channel_current->freq)) return 0; } else mp_tmsg(MSGT_RADIO, MSGL_ERR, "[radio] Can not change channel: no channel list given.\n"); return 1; }
/***************************************************************** * \brief change channel to one with given index * \parameter channel string, containing channel number * \return 1 if success,0 - otherwise * * if channel parameter is NULL function prints error message and does nothing, otherwise * changes channel to given */ int radio_set_channel(struct stream_st *stream, char *channel) { radio_priv_t* priv=(radio_priv_t*)stream->priv; int i, channel_int; radio_channels_t* tmp; char* endptr; if (*channel=='\0') mp_msg(MSGT_RADIO,MSGL_ERR,MSGTR_RADIO_WrongChannelName,channel); if (priv->radio_channel_list) { channel_int = strtol(channel,&endptr,10); tmp = priv->radio_channel_list; if (*endptr!='\0'){ //channel is not a number, so it contains channel name for ( ; tmp; tmp=tmp->next) if (!strncmp(channel,tmp->name,sizeof(tmp->name)-1)) break; if (!tmp){ mp_msg(MSGT_RADIO,MSGL_ERR,MSGTR_RADIO_WrongChannelName,channel); return 0; } }else{ for (i = 1; i < channel_int; i++) if (tmp->next) tmp = tmp->next; else break; if (tmp->index!=channel_int){ mp_msg(MSGT_RADIO,MSGL_ERR,MSGTR_RADIO_WrongChannelNumberInt,channel_int); return 0; } } priv->radio_channel_current=tmp; mp_msg(MSGT_RADIO, MSGL_V, MSGTR_RADIO_SelectedChannel, priv->radio_channel_current->index, priv->radio_channel_current->name, priv->radio_channel_current->freq); if(!radio_set_freq(stream, priv->radio_channel_current->freq)) return 0; } else mp_msg(MSGT_RADIO, MSGL_ERR, MSGTR_RADIO_ChangeChannelNoChannelList); return 1; }
int main(int argc, char **argv) { int optchar; int search = 0; char *drv = NULL; u_int16_t freq = DEF_FREQ; int volu = 0; u_int16_t action = NONE; u_int16_t lower = 0, higher = 0; u_int32_t cycle = 1; #ifndef NOMIXER int mixer = 0; char *master_volume = NULL; char *other_volume = NULL; #endif /* !NOMIXER */ if (gouser() < 0) return -1; pn = strrchr(argv[0], '/'); if (pn == NULL) pn = argv[0]; else pn++; radio_init(); /* * Call radio_drv_init() before usage(), * or default driver will be: NULL, 0x0 */ drv = getenv("FMTUNER"); if (drv == NULL || *drv == '\0') drv = DEF_DRV; if (radio_drv_init(drv) == ERADIO_INVL) invalid_driver_error(drv); if (argc < 2) usage(); /* Argh... options */ #ifndef NOMIXER while ((optchar = getopt(argc, argv, "c:Dd:f:h:il:mSsv:W:X:x:")) != -1) { #else while ((optchar = getopt(argc, argv, "c:Dd:f:h:il:mSsv:W:X:x:")) != -1) { #endif /* !NOMIXER */ switch (optchar) { case 'c': /* number of probes for each scanned frequency */ if ((cycle = strtol(optarg, (char **)NULL, 10)) == 0) cycle = 1; break; case 'D': action = DETE; break; case 'd': radio_drv_free(); if (radio_drv_init(optarg) == ERADIO_INVL) invalid_driver_error(optarg); break; case 'f': freq = 100.0 * strtod(optarg, (char **)NULL); if (freq == 0) freq = DEF_FREQ; action |= TUNE; break; case 'h': higher = atof(optarg) * 100; break; case 'i': action |= INFO; break; case 'l': lower = atof(optarg) * 100; break; case 'm': action |= MONO; break; case 'S': action = SCAN; break; case 's': action |= STAT; break; case 'v': volu = strtoul(optarg, (char **)NULL, 10); action |= VOLU; break; case 'W': action = SRCH; search = atof(optarg) * 100; break; #ifndef NOMIXER case 'X': /* set outputs.master */ master_volume = optarg; break; case 'x': other_volume = optarg; break; #endif /* !NOMIXER */ default: usage(); } } /* Minor actions have more priority */ if (action & MINOR) action &= MINOR; #if 0 /* Drop privs for drivers that don't need root */ if ((action & ~MINOR) != DETE) if (!radio_info_root()) setuid(getuid()); #endif /* Enabling communication with the radio port */ if (radio_info_root()) if (goroot() < 0) die(1); if (radio_get_port() < 0) die(1); /* Test for card presense */ if (radio_test_port() != 1) { fprintf(stderr, "%s: card not found: ", pn); radio_info_show(stderr, radio_info_name(), radio_info_port()); radio_free_port(); die(1); } if (radio_info_root()) if (gouser() < 0) die(1); /* * During time consuming actions fmio can get * some signal. Define action for such emergency. * Though it's more suitable to define these under SCAN or DETE, * it won't hurt if they'll be here. */ signal(SIGINT , die); #ifndef __DOS__ signal(SIGHUP , die); #endif signal(SIGTERM, die); switch (action & ~MINOR) { case NONE: #ifndef NOMIXER mixer = radio_mixer_init() < 0 ? 0 : 1; #endif /* !NOMIXER */ if (radio_info_root()) if (goroot() < 0) die(1); if (action & MONO) radio_set_mono(); switch (radio_info_policy()) { case 0: if (action & TUNE) radio_set_volume(action & VOLU ? volu : 1); break; case 1: if (action & TUNE) radio_set_volume(action & VOLU ? volu : radio_info_maxvol()); break; } if (action & TUNE) radio_set_freq(freq); if (action & VOLU) radio_set_volume(volu); if (action & STAT) { int st = radio_info_stereo(); int si = radio_info_signal(); if (st != ERADIO_INVL) printf("%s", st ? "stereo" : "mono"); if (st != ERADIO_INVL && si != ERADIO_INVL) printf(" : "); if (si != ERADIO_INVL) printf("%s", si ? "signal" : "noise"); if (st != ERADIO_INVL || si != ERADIO_INVL) printf("\n"); } if (action & INFO) { u_int16_t f = radio_info_freq(); int v = radio_info_volume(); printf("Driver: "); radio_info_show(stdout, radio_info_name(), radio_info_port()); if (f) printf("Frequency: %.2f MHz\n", (float) f / 100); if (v) printf("Volume: %u\n", v); v = radio_info_signal(); if (v != ERADIO_INVL) printf("Signal: %s\n", v ? "on" : "off"); v = radio_info_stereo(); if (v != ERADIO_INVL) printf("Stereo: %s\n", v ? "on" : "off"); } if (radio_info_root()) gouser(); #ifndef NOMIXER if (mixer) if (other_volume) radio_mixer_update_volume(other_volume); /* * Now outputs.master=0,0 * Update saved values */ if (mixer) { if (master_volume) radio_mixer_set_volume(master_volume); radio_mixer_cleanup(); } #endif /* !NOMIXER */ break; case DETE: if (goroot() < 0) die(1); radio_detect(); if (gouser() < 0) die(1); break; case SCAN: if (radio_info_root()) if (goroot() < 0) die(1); radio_scan(lower, higher, cycle); if (radio_info_root()) if (gouser() < 0) die(1); break; case SRCH: #ifndef NOMIXER mixer = radio_mixer_init() < 0 ? 0 : 1; #endif /* !NOMIXER */ if (radio_info_root()) if (goroot() < 0) die(1); if (search < 0) freq = radio_search(0, -1 * search); else freq = radio_search(1, search); if (radio_info_root()) if (gouser() < 0) die(1); if (freq) printf("%s: %.2f MHz\n", pn, (float)freq / 100); #ifndef NOMIXER if (mixer) radio_mixer_cleanup(); #endif /* !NOMIXER */ break; default: break; } if (radio_info_root()) if (goroot() < 0) die(1); radio_free_port(); if (radio_info_root()) gouser(); radio_drv_free(); radio_cleanup(); return 0; } /* * Dump the usage string to screen */ void usage(void) { const char usage_string[] = #ifdef NOMIXER "Usage: %s [-d driver] [-f frequency] [-i] [-m] [-s] [-v volume]\n" #else "Usage: %s [-d drv] [-f freq] [-i] [-m] [-s] [-v vol] [-X vol] [-x vol]\n" #endif /* NOMIXER */ "\t%s [-d driver] -S [-l begin] [-h end] [-c count]\n" "\t%s [-d driver] -W frequency\n" "\t%s -D - detect driver\n\n" "\t-f frequency in Mhz, -f 98.0 for example\n" "\t-i information\n" "\t-m mono\n" "\t-s stat\n" "\t-v volume, -v 0 set tuner off\n" "\t-S scan -l start frequency, -h end frequency\n" "\t-c number of probes for each scanned frequency\n" "\t-W search\n" ; printf("%s version %s\n", pn, VERSION); printf("Default driver: "); radio_info_show(stdout, radio_info_name(), radio_info_port()); printf(usage_string, pn, pn, pn, pn); die(0); } void die(int sig) { radio_drv_free(); radio_cleanup(); exit(sig); }