Exemplo n.º 1
0
static int load_rules(struct userdata *u) {
    FILE *f;
    int n = 0;
    int ret = -1;
    char buf_name[256], buf_volume[256], buf_sink[256], buf_source[256];
    char *ln = buf_name;

    f = u->table_file ?
        fopen(u->table_file, "r") :
        pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "r");

    if (!f) {
        if (errno == ENOENT) {
            pa_log_info("starting with empty ruleset.");
            ret = 0;
        } else
            pa_log("failed to open file '%s': %s", u->table_file, pa_cstrerror(errno));

        goto finish;
    }

    pa_lock_fd(fileno(f), 1);

    while (!feof(f)) {
        struct rule *rule;
        pa_cvolume v;
        pa_bool_t v_is_set;

        if (!fgets(ln, sizeof(buf_name), f))
            break;

        n++;

        pa_strip_nl(ln);

        if (ln[0] == '#')
            continue;

        if (ln == buf_name) {
            ln = buf_volume;
            continue;
        }

        if (ln == buf_volume) {
            ln = buf_sink;
            continue;
        }

        if (ln == buf_sink) {
            ln = buf_source;
            continue;
        }

        pa_assert(ln == buf_source);

        if (buf_volume[0]) {
            if (!parse_volume(buf_volume, &v)) {
                pa_log("parse failure in %s:%u, stopping parsing", u->table_file, n);
                goto finish;
            }

            v_is_set = TRUE;
        } else
            v_is_set = FALSE;

        ln = buf_name;

        if (pa_hashmap_get(u->hashmap, buf_name)) {
            pa_log("double entry in %s:%u, ignoring", u->table_file, n);
            continue;
        }

        rule = pa_xnew(struct rule, 1);
        rule->name = pa_xstrdup(buf_name);
        if ((rule->volume_is_set = v_is_set))
            rule->volume = v;
        rule->sink = buf_sink[0] ? pa_xstrdup(buf_sink) : NULL;
        rule->source = buf_source[0] ? pa_xstrdup(buf_source) : NULL;

        pa_hashmap_put(u->hashmap, rule->name, rule);
    }

    if (ln != buf_name) {
        pa_log("invalid number of lines in %s.", u->table_file);
        goto finish;
    }

    ret = 0;

finish:
    if (f) {
        pa_lock_fd(fileno(f), 0);
        fclose(f);
    }

    return ret;
}
Exemplo n.º 2
0
static void parse_options(int argc, char **argv, struct cmdopt *cmdopt)
{
    struct option options[] = {
        { "help"            , no_argument      , NULL, 'h' },
        { "daemon"          , no_argument      , NULL, 'd' },
        { "interactive"     , no_argument      , NULL, 'i' },
        { "8kHz"            , no_argument      , NULL, '8' },
        { "user"            , required_argument, NULL, 'u' },
        { "standard"        , required_argument, NULL, 's' },
        { "buflen"          , required_argument, NULL, 'b' },
        { "minreq"          , required_argument, NULL, 'r' },
        { "statistics"      , no_argument      , NULL, 'S' },
        { "tag-dtmf"        , required_argument, NULL, 'D' },
        { "tag-indicator"   , required_argument, NULL, 'I' },
        { "tag-notif"       , required_argument, NULL, 'N' },
        { "volume-dtmf"     , required_argument, NULL, '1' },
        { "volume-indicator", required_argument, NULL, '2' },
        { "volume-notif"    , required_argument, NULL, '3' },
        
#define OPTS "du:s:b:r:hi8SD:I:N:"
        { NULL           , 0                , NULL,  0  }
    };
    
    int option;
    struct passwd *pwd;
    long int t;
    char *e;

    while ((option = getopt_long(argc, argv, OPTS, options, NULL)) != -1) {
        switch (option) {

        case 'h':
            usage(argc, argv, 0);
            break;

        case 'd':
            cmdopt->daemon = 1;
            break;

        case 'i':
            cmdopt->interactive = 1;
            break;

        case '8':
            cmdopt->sample_rate = 8000;
            break;

        case 'u':
            if (!optarg && !*optarg)
                usage(argc, argv, EINVAL);

            cmdopt->uid = -1;

            while ((pwd = getpwent()) != NULL) {
                if (!strcmp(optarg, pwd->pw_name)) {
                    cmdopt->uid = pwd->pw_uid;
                    break;
                }
            }

            if (cmdopt->uid < 0) {
                printf("invalid username: %s\n", optarg);
                usage(argc, argv, EINVAL);
            }
            break;

        case 's':
            if (!strcmp(optarg, "cept"))
                cmdopt->standard = STD_CEPT;
            else if (!strcmp(optarg, "ansi"))
                cmdopt->standard = STD_ANSI;
            else if (!strcmp(optarg, "japan"))
                cmdopt->standard = STD_JAPAN;
            else if (!strcmp(optarg, "atnt"))
                cmdopt->standard = STD_ATNT;
            else {
                printf("invalid standard '%s'\n", optarg);
                usage(argc, argv, EINVAL);
            }
            break;

        case 'b':
            t = strtol(optarg, &e, 10);

            if (*e == '\0' && t > 0 && t <= 10000)
                cmdopt->buflen = t;
            else {
                printf("invalid buffer length '%s' msec\n", optarg);
                usage(argc, argv, EINVAL);
            }
            break;

        case 'r':
            t = strtol(optarg, &e, 10);

            if (*e == '\0' && t > 0 && t <= 1000)
                cmdopt->minreq = t;
            else {
                printf("invalid min.request length '%s' msec\n", optarg);
                usage(argc, argv, EINVAL);
            }
            break;

        case 'S':
            cmdopt->statistics = 1;
            break;

        case 'D':
            cmdopt->dtmf_tags = optarg;
            break;

        case 'I':
            cmdopt->ind_tags = optarg;
            break;

        case 'N':
            cmdopt->notif_tags = optarg;
            break;

        case '1':
            cmdopt->dtmf_volume = parse_volume(optarg);
            break;

        case '2':
            cmdopt->ind_volume = parse_volume(optarg);
            break;

        case '3':
            cmdopt->notif_volume = parse_volume(optarg);
            break;

        default:
            usage(argc, argv, EINVAL);
            break;
        }
    }

    if (!cmdopt->daemon && cmdopt->uid > 0) {
        printf("Warning: -d is not present; ignoring -u option\n");
    }
}
Exemplo n.º 3
0
int execcmd(const char * cmd, char * reply) {
	char arg[1024], * ptr;
	unsigned ncmd;
	const char * known [] = {
		"play",
		"love",
		"ban",
		"skip",
		"quit",
		"info",
		"pause",
		"discovery",
		"tag-artist",
		"tag-album",
		"tag-track",
		"artist-tags",
		"album-tags",
		"track-tags",
		"stop",
		"volume-up",
		"volume-down",
		"volume",
		"rtp",
		"status",
		"unlove",
		"detach"
	};

	memset(arg, 0, sizeof(arg));
	memset(reply, 0, BUFSIZE);

	for(ncmd = 0; ncmd < (sizeof(known) / sizeof(char *)); ++ncmd) {
		if(!strncmp(known[ncmd], cmd, strlen(known[ncmd])))
			break;
	}

	switch(ncmd) {
		case (sizeof(known) / sizeof(char *)):
			strncpy(reply, "ERROR", BUFSIZE);
			break;

		/* "play lastfm://station" */
		case 0:
			if(sscanf(cmd, "play %128[a-zA-Z0-9:/_ %,*.+-]", arg) == 1) {
				char * url;
				decode(arg, & url);
				station(url);
				free(url);
			}
			break;

		/* Love currently played track. */
		case 1:
			rate("L");
			break;

		/* Ban currently played track. */
		case 2:
			rate("B");
			break;

		/* Skip track. */
		case 3:
			rate("S");
			break;

		/* Kill Shell.FM. */
		case 4:
			quit();

		/* "info FORMAT" - returns the format string with the meta data filled in. */
		case 5:
			if(* (cmd + 5))
				strncpy(reply, meta(cmd + 5, 0, & track), BUFSIZE);
			else if(haskey(& rc, "np-file-format"))
				strncpy(
					reply,
					meta(value(& rc, "np-file-format"), 0, & track),
					BUFSIZE
				);

			break;

		/* Pause playback. */
		case 6:
			if(playfork) {
				if(pausetime) {
					kill(playfork, SIGCONT);
				}
				else {
					time(& pausetime);
					kill(playfork, SIGSTOP);
				}
			}
			break;

		/* Toggle discovery mode. Returns "DISCOVERY <ON|OFF>" */
		case 7:
			toggle(DISCOVERY);
			snprintf(
				reply,
				BUFSIZE,
				"DISCOVERY %s",
				enabled(DISCOVERY) ? "ON" : "OFF"
			);
			break;

		/* "tag-artist tag1,tag2,..." - tag the artist of the current track. */
		case 8:
			if(sscanf(cmd, "tag-artist %128s", arg) == 1)
				sendtag('a', arg, track);
			break;

		/* "tag-album tag1,tag2,..." - tag the album of the current track. */
		case 9:
			if(sscanf(cmd, "tag-album %128s", arg) == 1)
				sendtag('l', arg, track);
			break;

		/* "tag-track tag1,tag2,..." - tag the current track. */
		case 10:
			if(sscanf(cmd, "tag-track %128s", arg) == 1)
				sendtag('t', arg, track);
			break;

		/* Return comma-separated list of the current artists tags. */
		case 11:
			if((ptr = oldtags('a', track)) != NULL) {
				strncpy(reply, ptr, BUFSIZE);
				free(ptr);
				ptr = NULL;
			}
			break;

		/* Return comma-separated list of the current albums tags. */
		case 12:
			if((ptr = oldtags('l', track)) != NULL) {
				strncpy(reply, ptr, BUFSIZE);
				free(ptr);
				ptr = NULL;
			}
			break;

		/* Return comma-separated list of the current tracks tags. */
		case 13:
			if((ptr = oldtags('t', track)) != NULL) {
				strncpy(reply, ptr, BUFSIZE);
				free(ptr);
				ptr = NULL;
			}
			break;


		/* Stop playback. */
		case 14:
			if(playfork) {
				enable(STOPPED);
				kill(playfork, SIGUSR1);
			}
			break;

		/* Increase absolute volume (0-64) by 1. */
		case 15:
			volume_up();
			break;

		/* Decrease absolute volume (0-64) by 1. */
		case 16:
			volume_down();
			break;

		/*
			Set volume.
			"volume 32" - set absolute volume (0-64) to 32 (50%).
			"volume %50" - same, but using percentual volume.
			"volume +1" - same as "volume_up".
			"volume -1" - same as "volume_down".

			Returns absolute volume ("VOLUME 32").
		*/
		case 17:
			parse_volume(cmd);
			snprintf(reply, BUFSIZE, "VOLUME %d", volume);
			break;

		/* Toggle RTP (report to profile, "scrobbling"). Returns "RTP <ON|OFF>". */
		case 18:
			/* RTP on/off */
			toggle(RTP);
			snprintf(reply, BUFSIZE, "RTP %s", enabled(RTP) ? "ON" : "OFF");
			break;

		/* Get current status. Returns on of "PAUSE", "PLAYING" and "STOPPED". */
		case 19:
			strncpy(reply, PLAYBACK_STATUS, BUFSIZE);
			break;

		/* Unlove currently played track. */
		case 20:
			rate("U");
			break;
		
		/* Detach from network interface. */
		case 21:
			return 1;	
	}

	return 0;
}