/*****************************************************************
 * \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;
}
Beispiel #6
0
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);
}