1 /*
2 *
3 * Conky, a system monitor, based on torsmo
4 *
5 * Any original torsmo code is licensed under the BSD license
6 *
7 * All code written since the fork of torsmo is licensed under the GPL
8 *
9 * Please see COPYING for details
10 *
11 * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
12 * Copyright (c) 2005-2021 Brenden Matthews, Philip Kovacs, et. al.
13 * (see AUTHORS)
14 * All rights reserved.
15 *
16 * This program is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 *
28 */
29
30 #include <ctype.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <sys/ioctl.h>
34 #include "conky.h"
35 #include "logging.h"
36 #include "specials.h"
37 #include "text_object.h"
38
39 #ifdef HAVE_LINUX_SOUNDCARD_H
40 #include <linux/soundcard.h>
41 #else
42 #ifdef __OpenBSD__
43 #include <soundcard.h>
44 #else
45 #include <sys/soundcard.h>
46 #endif /* __OpenBSD__ */
47 #endif /* HAVE_LINUX_SOUNDCARD_H */
48
49 #if defined(__sun)
50 #include <stropts.h>
51 #include <unistd.h>
52 #endif
53
54 #define MIXER_DEV "/dev/mixer"
55
56 static int mixer_fd;
57 static const char *devs[] = SOUND_DEVICE_NAMES;
58
mixer_init(const char * name)59 int mixer_init(const char *name) {
60 unsigned int i;
61
62 if (name == 0 || name[0] == '\0') { name = "vol"; }
63
64 /* open mixer */
65 if (mixer_fd <= 0) {
66 mixer_fd = open(MIXER_DEV, O_RDONLY);
67 if (mixer_fd == -1) {
68 NORM_ERR("can't open %s: %s", MIXER_DEV, strerror(errno));
69 return -1;
70 }
71 }
72
73 for (i = 0; i < sizeof(devs) / sizeof(const char *); i++) {
74 if (strcasecmp(devs[i], name) == 0) { return i; }
75 }
76
77 return -1;
78 }
79
mixer_get(int i)80 static int mixer_get(int i) {
81 static char rep = 0;
82 int val = -1;
83
84 if (ioctl(mixer_fd, MIXER_READ(i), &val) == -1) {
85 if (!rep) { NORM_ERR("mixer ioctl: %s", strerror(errno)); }
86 rep = 1;
87 return 0;
88 }
89 rep = 0;
90
91 return val;
92 }
93
mixer_get_avg(int i)94 static int mixer_get_avg(int i) {
95 int v = mixer_get(i);
96
97 return ((v >> 8) + (v & 0xFF)) / 2;
98 }
99
mixer_get_left(int i)100 static int mixer_get_left(int i) { return mixer_get(i) >> 8; }
101
mixer_get_right(int i)102 static int mixer_get_right(int i) { return mixer_get(i) & 0xFF; }
mixer_is_mute(int i)103 int mixer_is_mute(int i) { return !mixer_get(i); }
104
105 #define mixer_to_255(i, x) x
106
parse_mixer_arg(struct text_object * obj,const char * arg)107 void parse_mixer_arg(struct text_object *obj, const char *arg) {
108 obj->data.l = mixer_init(arg);
109 }
110
mixer_percentage(struct text_object * obj)111 uint8_t mixer_percentage(struct text_object *obj) {
112 return mixer_get_avg(obj->data.l);
113 }
114
mixerl_percentage(struct text_object * obj)115 uint8_t mixerl_percentage(struct text_object *obj) {
116 return mixer_get_left(obj->data.l);
117 }
118
mixerr_percentage(struct text_object * obj)119 uint8_t mixerr_percentage(struct text_object *obj) {
120 return mixer_get_right(obj->data.l);
121 }
122
check_mixer_muted(struct text_object * obj)123 int check_mixer_muted(struct text_object *obj) {
124 if (!mixer_is_mute(obj->data.l)) return 0;
125 return 1;
126 }
127
scan_mixer_bar(struct text_object * obj,const char * arg)128 void scan_mixer_bar(struct text_object *obj, const char *arg) {
129 char buf1[64];
130 int n;
131
132 if (arg && sscanf(arg, "%63s %n", buf1, &n) >= 1) {
133 obj->data.i = mixer_init(buf1);
134 scan_bar(obj, arg + n, 100);
135 } else {
136 obj->data.i = mixer_init(nullptr);
137 scan_bar(obj, arg, 100);
138 }
139 }
140
mixer_barval(struct text_object * obj)141 double mixer_barval(struct text_object *obj) {
142 return mixer_to_255(obj->data.i, mixer_get_avg(obj->data.i));
143 }
144
mixerl_barval(struct text_object * obj)145 double mixerl_barval(struct text_object *obj) {
146 return mixer_to_255(obj->data.i, mixer_get_left(obj->data.i));
147 }
148
mixerr_barval(struct text_object * obj)149 double mixerr_barval(struct text_object *obj) {
150 return mixer_to_255(obj->data.i, mixer_get_right(obj->data.i));
151 }
152