Beispiel #1
0
static void render()
{
    if (about_is_show)
    {
        return;
    }
	else if (visualization_isopen)
	{
		show_visualization(0, 0);
        show_processbar<79>(24, 0);
		return;
	}    
	show_list();
	show_processbar<80>(20, 0);
	show_help(21, 0);
    show_volume(21, 40);
}
int main(int argc, char *const *argv) {
    static const char *context_name = "i3blocks-pulse-volume";
    static const char *usage_str = "Usage: %s [-h] [-d] [-s INDEX] [-m FUNC]\n"
            "Options:\n"
            "  -s INDEX: pulseaudio sink index on which to wait for "
            "changes (default: 0)\n"
            "  -m FUNC : function used to compute the displayed volume value\n"
            "            in there are multiple channels (eg. left/right):\n"
            "             * avg: use average volume of all channels (default)\n"
            "             * min: use minimum volume of all channels\n"
            "             * max: use maximum volume of all channels\n"
            "  -d      : use decibel notation instead of 0-100 percentage; "
            "the sink may\n"
            "            not support this feature\n";

    options_t options;
    options.calculator = pa_cvolume_avg;
    options.use_decibel = 0;
    options.observed_index = 0;

    sink_info_data_t sink_info_data;
    sink_info_data.sink_ready = 0;
    sink_info_data.sink_changed = 0;

    pa_mainloop *pa_ml = NULL;
    pa_mainloop_api *pa_ml_api = NULL;
    pa_operation *pa_op = NULL;
    pa_context *pa_ctx = NULL;

    enum state_t state = FIRST_SINK_INFO;
    int pa_ready = CONN_WAIT;

    int opt;
    while ((opt = getopt(argc, argv, "m:s:dh")) != -1) {
        if (opt == 'm') {
            if (strcmp(optarg, "min") == 0) {
                options.calculator = pa_cvolume_min;
            } else if (strcmp(optarg, "max") == 0) {
                options.calculator = pa_cvolume_max;
            } else if (strcmp(optarg, "avg") == 0) {
                options.calculator = pa_cvolume_avg;
            } else {
                fprintf(stderr, usage_str, argv[0]);
                return 1;
            }
        } else if (opt == 's') {
            // Parse observed sink index
            errno = 0;
            char *endptr;
            uint32_t *oind = &options.observed_index;
            *oind = strtoul(optarg, &endptr, 10);
            if ((errno == ERANGE) || (errno != 0 && *oind == 0) ||
                endptr == optarg) {
                fprintf(stderr, "%s: invalid sink index: %s\n", argv[0],
                        optarg);
                fprintf(stderr, usage_str, argv[0]);
                return 1;
            }
        } else if (opt == 'd') {
            options.use_decibel = 1;
        } else if (opt == 'h') {
            fprintf(stderr, usage_str, argv[0]);
            return 0;
        } else {
            fprintf(stderr, usage_str, argv[0]);
            return 1;
        }
    }

    // Needed to filter out sink in callbacks
    sink_info_data.observed_index = options.observed_index;

    if ((pa_ml = pa_mainloop_new()) == NULL) {
        fprintf(stderr, "error: failed to allocate pulseaudio mainloop.\n");
        return 2;
    }
    if ((pa_ml_api = pa_mainloop_get_api(pa_ml)) == NULL) {
        fprintf(stderr, "error: failed to allocate pulseaudio mainloop API.\n");
        return 3;
    }
    if ((pa_ctx = pa_context_new(pa_ml_api, context_name)) == NULL) {
        fprintf(stderr, "error: failed to allocate pulseaudio context.\n");
        return 4;
    }

    if (pa_context_connect(pa_ctx, NULL, PA_CONTEXT_NOFAIL, NULL) < 0) {
        fprintf(stderr, "error: failed to connect to pulseaudio context: %s\n",
                pa_strerror(pa_context_errno(pa_ctx)));
        return 5;
    }

    pa_context_set_state_callback(pa_ctx, state_cb, &pa_ready);
    pa_context_set_subscribe_callback(pa_ctx, subscribe_cb, &sink_info_data);

    while (1) {
        if (pa_ready == CONN_WAIT) {
            pa_mainloop_iterate(pa_ml, 1, NULL);
            continue;
        }

        if (pa_ready == CONN_FAILED) {
            pa_context_disconnect(pa_ctx);
            pa_context_unref(pa_ctx);
            pa_mainloop_free(pa_ml);
            fprintf(stderr,
                    "error: failed to connect to pulseaudio context.\n");
            return 6;
        }

        // Main loop automaton
        switch (state) {
            case FIRST_SINK_INFO:
                // First run
                pa_op = pa_context_get_sink_info_by_index(pa_ctx,
                            options.observed_index,
                            sink_info_cb, &sink_info_data);
                state = SUBSCRIBE;
                break;
            case SUBSCRIBE:
                if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
                    pa_operation_unref(pa_op);
                    if (!sink_info_data.sink_ready) {
                        fprintf(stderr, "error: sink %u does not exist.\n",
                                options.observed_index);
                        pa_context_disconnect(pa_ctx);
                        pa_context_unref(pa_ctx);
                        pa_mainloop_free(pa_ml);
                        return 7;
                    }
                    if (options.use_decibel &&
                        !sink_info_data.sink.can_decibel) {
                        fprintf(stderr,
                                "error: sink %u does not support decibel; "
                                "try without `-d`.\n",
                                options.observed_index);
                        pa_context_disconnect(pa_ctx);
                        pa_context_unref(pa_ctx);
                        pa_mainloop_free(pa_ml);
                        return 8;
                    }
                    // Show volume once at start
                    show_volume(&sink_info_data.sink, &options);
                    // Subsequent runs: wait for changes
                    pa_op = pa_context_subscribe(pa_ctx,
                                                 PA_SUBSCRIPTION_MASK_SINK,
                                                 NULL, &sink_info_data);
                    state = SUBSCRIBED;
                }
                break;
            case SUBSCRIBED:
                if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
                    pa_operation_unref(pa_op);
                    state = WAIT_FOR_CHANGE;
                }
                break;
            case WAIT_FOR_CHANGE:
                if (sink_info_data.sink_changed) {
                    sink_info_data.sink_changed = 0;
                    pa_op = pa_context_get_sink_info_by_index(pa_ctx,
                                options.observed_index, sink_info_cb,
                                &sink_info_data);
                    state = SHOW_CHANGE;
                }
                break;
            case SHOW_CHANGE:
                if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
                    pa_operation_unref(pa_op);
                    show_volume(&sink_info_data.sink, &options);
                    state = WAIT_FOR_CHANGE;
                }
                break;
            default:
                return 7;
        }
        pa_mainloop_iterate(pa_ml, 1, NULL);
    }
}
Beispiel #3
0
static error_t parse_opt (int key, char *arg, struct argp_state *state)
{
	int s,d;
	struct arguments *arguments = state->input;

	switch (key)
	{
		case 's':
			show_type();
			show_zcd();
			show_fnc();
			show_ycm();
			show_fblk();
			show_volume();
			show_mute();
			break;

		case 'm':
	        	mute();
			break;

		case 'u':
	        	unmute();
			break;

		case 'l':
			set_volume(atoi(arg));
			break;

		case 'z':
			set_zcd(atoi(arg));
			break;

		case 'f':
			set_fnc(atoi(arg));
			break;

		case 'y':
			set_ycm(atoi(arg));
			break;

		case 'v':
			if ( parse_route_arg(arg,&s,&d) < 0 )
			{
				return ARGP_ERR_UNKNOWN;
			}

			set_video(s,d);

			break;

		case 'a':
			if ( parse_route_arg(arg,&s,&d) < 0 )
			{
				return ARGP_ERR_UNKNOWN;
			}

			set_audio(s,d);

			break;

		default:
			return ARGP_ERR_UNKNOWN;
	}

	return 0;
}