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