1c72fcc34Sopenharmony_ci/*
2c72fcc34Sopenharmony_ci * mainloop.c - main loop
3c72fcc34Sopenharmony_ci * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
4c72fcc34Sopenharmony_ci *
5c72fcc34Sopenharmony_ci * This program is free software: you can redistribute it and/or modify
6c72fcc34Sopenharmony_ci * it under the terms of the GNU General Public License as published by
7c72fcc34Sopenharmony_ci * the Free Software Foundation, either version 2 of the License, or
8c72fcc34Sopenharmony_ci * (at your option) any later version.
9c72fcc34Sopenharmony_ci *
10c72fcc34Sopenharmony_ci * This program is distributed in the hope that it will be useful,
11c72fcc34Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
12c72fcc34Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13c72fcc34Sopenharmony_ci * GNU General Public License for more details.
14c72fcc34Sopenharmony_ci *
15c72fcc34Sopenharmony_ci * You should have received a copy of the GNU General Public License
16c72fcc34Sopenharmony_ci * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17c72fcc34Sopenharmony_ci */
18c72fcc34Sopenharmony_ci
19c72fcc34Sopenharmony_ci#include "aconfig.h"
20c72fcc34Sopenharmony_ci#include <stdio.h>
21c72fcc34Sopenharmony_ci#include <stdlib.h>
22c72fcc34Sopenharmony_ci#include <errno.h>
23c72fcc34Sopenharmony_ci#include <poll.h>
24c72fcc34Sopenharmony_ci#include <panel.h>
25c72fcc34Sopenharmony_ci#include <alsa/asoundlib.h>
26c72fcc34Sopenharmony_ci#include "mem.h"
27c72fcc34Sopenharmony_ci#include "die.h"
28c72fcc34Sopenharmony_ci#include "colors.h"
29c72fcc34Sopenharmony_ci#include "widget.h"
30c72fcc34Sopenharmony_ci#include "mixer_widget.h"
31c72fcc34Sopenharmony_ci#include "mixer_display.h"
32c72fcc34Sopenharmony_ci#include "mixer_controls.h"
33c72fcc34Sopenharmony_ci#include "mainloop.h"
34c72fcc34Sopenharmony_ci
35c72fcc34Sopenharmony_cistatic WINDOW *curses_initialized;
36c72fcc34Sopenharmony_ci
37c72fcc34Sopenharmony_cistatic void black_hole_error_handler(const char *file ATTRIBUTE_UNUSED,
38c72fcc34Sopenharmony_ci				     int line ATTRIBUTE_UNUSED,
39c72fcc34Sopenharmony_ci				     const char *function ATTRIBUTE_UNUSED,
40c72fcc34Sopenharmony_ci				     int err ATTRIBUTE_UNUSED,
41c72fcc34Sopenharmony_ci				     const char *fmt ATTRIBUTE_UNUSED, ...)
42c72fcc34Sopenharmony_ci{
43c72fcc34Sopenharmony_ci}
44c72fcc34Sopenharmony_ci
45c72fcc34Sopenharmony_civoid initialize_curses(bool use_color, bool use_mouse)
46c72fcc34Sopenharmony_ci{
47c72fcc34Sopenharmony_ci	curses_initialized = initscr();
48c72fcc34Sopenharmony_ci	cbreak();
49c72fcc34Sopenharmony_ci	noecho();
50c72fcc34Sopenharmony_ci#ifdef HAVE_CURSES_ESCDELAY
51c72fcc34Sopenharmony_ci	set_escdelay(100);
52c72fcc34Sopenharmony_ci#endif
53c72fcc34Sopenharmony_ci	window_size_changed(); /* update screen_lines/cols */
54c72fcc34Sopenharmony_ci	init_colors(use_color);
55c72fcc34Sopenharmony_ci	if (use_mouse)
56c72fcc34Sopenharmony_ci		mousemask(ALL_MOUSE_EVENTS, NULL);
57c72fcc34Sopenharmony_ci
58c72fcc34Sopenharmony_ci	snd_lib_error_set_handler(black_hole_error_handler);
59c72fcc34Sopenharmony_ci}
60c72fcc34Sopenharmony_ci
61c72fcc34Sopenharmony_civoid app_shutdown(void)
62c72fcc34Sopenharmony_ci{
63c72fcc34Sopenharmony_ci	if (curses_initialized) {
64c72fcc34Sopenharmony_ci		clear();
65c72fcc34Sopenharmony_ci		refresh();
66c72fcc34Sopenharmony_ci		curs_set(1);
67c72fcc34Sopenharmony_ci		endwin();
68c72fcc34Sopenharmony_ci	}
69c72fcc34Sopenharmony_ci	mixer_shutdown();
70c72fcc34Sopenharmony_ci}
71c72fcc34Sopenharmony_ci
72c72fcc34Sopenharmony_civoid mainloop(void)
73c72fcc34Sopenharmony_ci{
74c72fcc34Sopenharmony_ci	struct pollfd *pollfds = NULL;
75c72fcc34Sopenharmony_ci	int nfds = 0, n;
76c72fcc34Sopenharmony_ci	const struct widget *active_widget;
77c72fcc34Sopenharmony_ci	unsigned short revents;
78c72fcc34Sopenharmony_ci	int key;
79c72fcc34Sopenharmony_ci	int err;
80c72fcc34Sopenharmony_ci
81c72fcc34Sopenharmony_ci	for (;;) {
82c72fcc34Sopenharmony_ci		update_panels();
83c72fcc34Sopenharmony_ci		doupdate();
84c72fcc34Sopenharmony_ci
85c72fcc34Sopenharmony_ci		active_widget = get_active_widget();
86c72fcc34Sopenharmony_ci		if (!active_widget)
87c72fcc34Sopenharmony_ci			break;
88c72fcc34Sopenharmony_ci
89c72fcc34Sopenharmony_ci		n = 1 + snd_mixer_poll_descriptors_count(mixer);
90c72fcc34Sopenharmony_ci		if (n != nfds) {
91c72fcc34Sopenharmony_ci			free(pollfds);
92c72fcc34Sopenharmony_ci			nfds = n;
93c72fcc34Sopenharmony_ci			pollfds = ccalloc(nfds, sizeof *pollfds);
94c72fcc34Sopenharmony_ci			pollfds[0].fd = fileno(stdin);
95c72fcc34Sopenharmony_ci			pollfds[0].events = POLLIN;
96c72fcc34Sopenharmony_ci		}
97c72fcc34Sopenharmony_ci		err = snd_mixer_poll_descriptors(mixer, &pollfds[1], nfds - 1);
98c72fcc34Sopenharmony_ci		if (err < 0)
99c72fcc34Sopenharmony_ci			fatal_alsa_error("cannot get poll descriptors", err);
100c72fcc34Sopenharmony_ci		n = poll(pollfds, nfds, -1);
101c72fcc34Sopenharmony_ci		if (n < 0) {
102c72fcc34Sopenharmony_ci			if (errno == EINTR) {
103c72fcc34Sopenharmony_ci				pollfds[0].revents = 0;
104c72fcc34Sopenharmony_ci				doupdate(); /* handle SIGWINCH */
105c72fcc34Sopenharmony_ci			} else {
106c72fcc34Sopenharmony_ci				fatal_error("poll error");
107c72fcc34Sopenharmony_ci			}
108c72fcc34Sopenharmony_ci		}
109c72fcc34Sopenharmony_ci		if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL))
110c72fcc34Sopenharmony_ci			break;
111c72fcc34Sopenharmony_ci		if (pollfds[0].revents & POLLIN)
112c72fcc34Sopenharmony_ci			--n;
113c72fcc34Sopenharmony_ci		if (n > 0) {
114c72fcc34Sopenharmony_ci			err = snd_mixer_poll_descriptors_revents(mixer, &pollfds[1], nfds - 1, &revents);
115c72fcc34Sopenharmony_ci			if (err < 0)
116c72fcc34Sopenharmony_ci				fatal_alsa_error("cannot get poll events", err);
117c72fcc34Sopenharmony_ci			if (revents & (POLLERR | POLLNVAL))
118c72fcc34Sopenharmony_ci				close_mixer_device();
119c72fcc34Sopenharmony_ci			else if (revents & POLLIN)
120c72fcc34Sopenharmony_ci				snd_mixer_handle_events(mixer);
121c72fcc34Sopenharmony_ci		}
122c72fcc34Sopenharmony_ci		key = wgetch(active_widget->window);
123c72fcc34Sopenharmony_ci		while (key != ERR) {
124c72fcc34Sopenharmony_ci#ifdef KEY_RESIZE
125c72fcc34Sopenharmony_ci			if (key == KEY_RESIZE)
126c72fcc34Sopenharmony_ci				window_size_changed();
127c72fcc34Sopenharmony_ci			else
128c72fcc34Sopenharmony_ci#endif
129c72fcc34Sopenharmony_ci				active_widget->handle_key(key);
130c72fcc34Sopenharmony_ci			active_widget = get_active_widget();
131c72fcc34Sopenharmony_ci			if (!active_widget)
132c72fcc34Sopenharmony_ci				break;
133c72fcc34Sopenharmony_ci			key = wgetch(active_widget->window);
134c72fcc34Sopenharmony_ci		}
135c72fcc34Sopenharmony_ci		if (!active_widget)
136c72fcc34Sopenharmony_ci			break;
137c72fcc34Sopenharmony_ci		if (controls_changed) {
138c72fcc34Sopenharmony_ci			controls_changed = FALSE;
139c72fcc34Sopenharmony_ci			create_controls();
140c72fcc34Sopenharmony_ci			control_values_changed = FALSE;
141c72fcc34Sopenharmony_ci			display_controls();
142c72fcc34Sopenharmony_ci		} else if (control_values_changed) {
143c72fcc34Sopenharmony_ci			control_values_changed = FALSE;
144c72fcc34Sopenharmony_ci			display_controls();
145c72fcc34Sopenharmony_ci		}
146c72fcc34Sopenharmony_ci	}
147c72fcc34Sopenharmony_ci	free(pollfds);
148c72fcc34Sopenharmony_ci}
149