alsactl 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -1
- data/Rakefile +6 -0
- data/changes/0.1.1-critical.md +20 -0
- data/ext/alsacore/alsacore.c +372 -0
- data/ext/alsacore/extconf.rb +2 -2
- data/lib/alsactl/mixers.rb +1 -1
- data/lib/alsactl/version.rb +1 -1
- metadata +6 -3
- data/lib/alsacore/alsacore.so +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 482516915f981f7caead792ba342ce6c3cb641b581f30fcc1abb1aa4a738b345
|
4
|
+
data.tar.gz: d9901d56b145b182f74856571508c3a9c0c56373914ccd37e894f9ad5a3f63cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebd6800c0e93d7bed7d50f6bf57735ac13929409a5e624e3001c99c3acaaa481c6604d1468a4603f8990691c27159ff2a1974707e313d6cde6993de97b4df423
|
7
|
+
data.tar.gz: 34070edd4b4bc9c6596cbb6eeaf269b7e5fc7a011f41f3d3bd987644fb5098f826d6920b4f6aee942a59f945ef63a46bc899295d206ffaf82bae5bcc093d2dc1
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
### CHANGELOG -- (Ruby AlsaCtl) ###
|
2
2
|
1) 0.1.0, unreleased: 2021-May-04 -- Changed the API to use Ruby as the complex implementation interface, because faster to get it done, less code, and way simpler than doing all the higher-order calculations (as well as string and symbol comparisons) in the C wrapper. [t. Edelweiss]
|
3
3
|
1) 0.1.0, unreleased: 2021-May-04 -- In so doing above, turned entire C wrapper into an abstract class and module, so it can only be implemented by inheritance. Added such an implementation class, ``Mixers::DefMixer``. [t. Edelweiss]
|
4
|
-
1) 0.1.0, immediate pre-release: 2021-May-09 -- Realized that this gem was named too generic and changed the name to AlsaCtl, as there is a reasonable chance I might need to also handle PulseAudio or other APIs, at some point. Please also note the difference in the GitHub repo URL.
|
4
|
+
1) 0.1.0, immediate pre-release: 2021-May-09 -- Realized that this gem was named too generic and changed the name to AlsaCtl, as there is a reasonable chance I might need to also handle PulseAudio or other APIs, at some point. Please also note the difference in the GitHub repo URL.
|
5
|
+
1) 0.1.1, [CRITICAL PATCH] immediate pre-release: 2021-Jul-19 -- **CRITICAL PATCH (but does not change interface) -- please read** ``changes/0.1.1-critical.md`` **for information.** [t. Edelweiss]
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# SUMMARY #
|
2
|
+
|
3
|
+
**Date**
|
4
|
+
2021-Jul-19
|
5
|
+
|
6
|
+
**Version**
|
7
|
+
0.1.1
|
8
|
+
|
9
|
+
**Severity**
|
10
|
+
[CRITICAL UPDATE]
|
11
|
+
|
12
|
+
**Description**
|
13
|
+
No one appears to have noticed, perhaps due to the still highly-prevalent Ruby 2.7 on many systems, but this gem did NOT compile on later versions (2.8 BETA or anything 3.0+). This was due to a poorly-configured extconf, Rakefile, and gemspec. I have only been doing Ruby-C extensions for a few months, on and off, so I was not aware that Rake does not get invoked on execution of ``gem install``.
|
14
|
+
|
15
|
+
As such, the extension object file was not being placed into the correct location, even after a successful compilation, so the wrapper kept attempting to link _ONLY_ to the 2.7 version of the ``.so``. The key takeaway from this and why it would _still install_ was that the shared object, the one generated by my own local dev machine and older dev environment, was actually being placed into the proper location as a static dep, whereas the local, native, newly-compiled extension library was staying in an unlinked location (still under ``/ext/alsacore/``).
|
16
|
+
|
17
|
+
Thanks to a suggestion by @sampersand, on reviewing the ``openssl`` gem, I found out the correct way to link it was to leave the compiled object inside said directory, and to ``require 'alsacore.so'``, instead of using ``require_relative`` and the local path.
|
18
|
+
|
19
|
+
**Final Notes**
|
20
|
+
Please make sure to update this gem, if you have it installed, as the next Ruby version you upgrade to will NOT allow this to work, otherwise.
|
@@ -0,0 +1,372 @@
|
|
1
|
+
/* IN-PROCESS FILE - 2021-May-09 */
|
2
|
+
// Include Ruby
|
3
|
+
#include <ruby.h>
|
4
|
+
|
5
|
+
// Include other libraries
|
6
|
+
#include <stdio.h>
|
7
|
+
#include <math.h>
|
8
|
+
|
9
|
+
// ALSA includes
|
10
|
+
#include <alsa/asoundlib.h>
|
11
|
+
#include <alsa/version.h>
|
12
|
+
|
13
|
+
// Expansion to create a mixer pointer and then get the
|
14
|
+
// data from it
|
15
|
+
#define MIXLOADER base_mixer_obj* mixer; TypedData_Get_Struct(self, base_mixer_obj, &base_mixer_type, mixer);
|
16
|
+
|
17
|
+
// Don't try to handle anything on NULL mixer
|
18
|
+
#define CHK_MIX if (mixer->handle == NULL || \
|
19
|
+
mixer->element == NULL) { return Qnil; }
|
20
|
+
|
21
|
+
// Shorthand to allocate the channel arrays
|
22
|
+
#define MAX_CHANNELS (SND_MIXER_SCHN_LAST + 1)
|
23
|
+
|
24
|
+
// Shorthand early return on error
|
25
|
+
#define CRIT_CHECK if (err != 0) { return INT2NUM(err); }
|
26
|
+
|
27
|
+
/*
|
28
|
+
* Document-module: AlsaCore
|
29
|
+
*
|
30
|
+
* This module provides the concrete methods from which
|
31
|
+
* to extend custom mixers for volume control.
|
32
|
+
*
|
33
|
+
* A simple example of a default/Master mixer object is
|
34
|
+
* available and usable as +AlsaCtl::DefMixer+.
|
35
|
+
*
|
36
|
+
* = Example
|
37
|
+
*
|
38
|
+
* require 'AlsaCore'
|
39
|
+
*
|
40
|
+
* class MyMixer < AlsaCore::BaseMixer
|
41
|
+
*/
|
42
|
+
|
43
|
+
// Basic type initiators used in this file
|
44
|
+
VALUE AlsaCore = Qnil;
|
45
|
+
VALUE BaseMixer = Qnil;
|
46
|
+
// End type initiators
|
47
|
+
|
48
|
+
/*
|
49
|
+
* Document-class: AlsaCore::BaseMixer
|
50
|
+
*
|
51
|
+
* The BaseMixer class provides purely protected methods
|
52
|
+
* that can be used from an inheriting class. +AlsaCtl::DefMixer+
|
53
|
+
* inherits this class and provides a simple interface without
|
54
|
+
* complex mixer management operations.
|
55
|
+
*
|
56
|
+
* BaseMixer provides methods for
|
57
|
+
* 1. Resource management
|
58
|
+
* 2. Connection
|
59
|
+
* 3. Disconnection
|
60
|
+
* 4. Setting ALL the volumes of a mixer
|
61
|
+
* 5. Per-channel volume setting of the mixer
|
62
|
+
* 6. Per-channel retrieval of mixer volume information
|
63
|
+
* 7. Enumeration of channels within the mixer
|
64
|
+
* 8. Key error handling for common operations
|
65
|
+
*
|
66
|
+
* The API can be found on https://www.alsa-project.org/alsa-doc/alsa-lib/
|
67
|
+
*
|
68
|
+
*---
|
69
|
+
* Document-method: pro_initialize
|
70
|
+
*
|
71
|
+
* (base_mixer_m_initialize)
|
72
|
+
*
|
73
|
+
* Protected method initializes the BaseMixer class.
|
74
|
+
*
|
75
|
+
* Instantiates the wrapped struct. Does not take any
|
76
|
+
* arguments.
|
77
|
+
*
|
78
|
+
* self.new -> BaseMixer
|
79
|
+
* self.initialize -> BaseMixer
|
80
|
+
*
|
81
|
+
*---
|
82
|
+
* Document-method: pro_connect
|
83
|
+
*
|
84
|
+
* (method_base_mixer_connect)
|
85
|
+
*
|
86
|
+
* Connects to a requested ALSA mixer.
|
87
|
+
*
|
88
|
+
* Takes 2 strings, a card name and element name (identifier).
|
89
|
+
* +DefMixer+ automatically passes the values "default" and "Master"
|
90
|
+
* to generate the default mixer element for the system.
|
91
|
+
*
|
92
|
+
* self.connect(char*, char*) -> BaseMixer | error
|
93
|
+
*
|
94
|
+
* pro_connect("default", "Master") -> new BaseMixer
|
95
|
+
*
|
96
|
+
*---
|
97
|
+
* Document-method: pro_close
|
98
|
+
*
|
99
|
+
* (method_base_mixer_disconnect)
|
100
|
+
*
|
101
|
+
* Disconnects the mixer and sets its struct member pointers
|
102
|
+
* to NULL.
|
103
|
+
*
|
104
|
+
* Takes no arguments.
|
105
|
+
*
|
106
|
+
* Returns true, if no error.
|
107
|
+
*
|
108
|
+
*---
|
109
|
+
* Document-method: pro_enum
|
110
|
+
*
|
111
|
+
* (method_base_mixer_enum_channels)
|
112
|
+
*
|
113
|
+
* Returns a hash of valid channels for the mixer, on success.
|
114
|
+
* On failure, returns +nil+.
|
115
|
+
*
|
116
|
+
* Takes no arguments.
|
117
|
+
*
|
118
|
+
*---
|
119
|
+
* Document-method: pro_cvolume_get
|
120
|
+
*
|
121
|
+
* (method_base_mixer_cvolume_get)
|
122
|
+
* Gets the volume settings for a selected channel on the mixer.
|
123
|
+
*
|
124
|
+
* Returns a hash with the volume, on success.
|
125
|
+
*
|
126
|
+
* On failure, returns either:
|
127
|
+
* +nil+, if the mixer is disconnected
|
128
|
+
* +false+, if the mixer doesn't have this channel
|
129
|
+
*
|
130
|
+
* Takes 1 argument, the channel number to check.
|
131
|
+
*
|
132
|
+
* pro_cvolume_get(1) -> {:name, :max, :min, :volume, :percent}
|
133
|
+
*
|
134
|
+
*---
|
135
|
+
* Document-method: pro_cvolume_set
|
136
|
+
*
|
137
|
+
* (method_base_mixer_cvolume_set)
|
138
|
+
*
|
139
|
+
* Sets the volume for a specific channel.
|
140
|
+
*
|
141
|
+
* Takes 2 arguments, the channel number (+int+) and the volume to use (+long+).
|
142
|
+
* When inheriting this class, you need to convert the values correctly,
|
143
|
+
* as 1 will not be 1%, but more like 0.1%, if your mixer uses 2^16 or something.
|
144
|
+
*
|
145
|
+
* Returns the output of method_base_mixer_cvolume_get for the same channel,
|
146
|
+
* on success.
|
147
|
+
*
|
148
|
+
* Returns +nil+, on failure.
|
149
|
+
*
|
150
|
+
* pro_cvolume_set(1, 32768) -> Sets channel 1 to 32768 (usually 50%)
|
151
|
+
*
|
152
|
+
*---
|
153
|
+
* Document-method: pro_volume_set
|
154
|
+
*
|
155
|
+
* (method_base_mixer_volume_set_all)
|
156
|
+
*
|
157
|
+
* Sets the volumes for the entire mixer, all channels. This method
|
158
|
+
* uses a separate call from ALSA, +snd_mixer_selem_set_playback_volume_all+,
|
159
|
+
* which does not require any channels.
|
160
|
+
*
|
161
|
+
* Takes 1 argument, the volume (+long+).
|
162
|
+
*
|
163
|
+
* pro_volume_set(32768) -> Sets all channels to 32768 (probably 50%)
|
164
|
+
*/
|
165
|
+
|
166
|
+
// ---------------------------
|
167
|
+
// MIXER STRUCT BELOW
|
168
|
+
// ---------------------------
|
169
|
+
|
170
|
+
// Define the base mixer struct
|
171
|
+
typedef struct {
|
172
|
+
snd_mixer_t* handle; // Mixer handle
|
173
|
+
snd_mixer_elem_t* element; // Mixer element
|
174
|
+
} base_mixer_obj; // End Mixer struct def
|
175
|
+
|
176
|
+
// ---------------------------
|
177
|
+
// MIXER METHODS BELOW
|
178
|
+
// ---------------------------
|
179
|
+
|
180
|
+
// Free method for base mixer
|
181
|
+
void base_mixer_free(void* data) {
|
182
|
+
free(data);
|
183
|
+
} // End mixer free
|
184
|
+
|
185
|
+
// Size of mixer
|
186
|
+
size_t base_mixer_size(const void* data) {
|
187
|
+
return sizeof(data);
|
188
|
+
} // End size of mixer
|
189
|
+
|
190
|
+
// Define the Ruby struct type to encapsulate the
|
191
|
+
// master sound mixer
|
192
|
+
static const rb_data_type_t base_mixer_type = {
|
193
|
+
.wrap_struct_name = "base_mixer_obj",
|
194
|
+
.function = {
|
195
|
+
.dmark = NULL,
|
196
|
+
.dfree = base_mixer_free,
|
197
|
+
.dsize = base_mixer_size,
|
198
|
+
},
|
199
|
+
.data = NULL,
|
200
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
201
|
+
}; // End base mixer type definition
|
202
|
+
|
203
|
+
// Define allocation of mixer handle object
|
204
|
+
VALUE base_mixer_alloc(VALUE self) {
|
205
|
+
// Allocate the size for a mixer handle and its opened element
|
206
|
+
base_mixer_obj* mixer = malloc(sizeof(base_mixer_obj));
|
207
|
+
return TypedData_Wrap_Struct(self, &base_mixer_type, mixer); // Wrap it up!
|
208
|
+
} // End mixer handle allocation
|
209
|
+
|
210
|
+
// Initialize / constructor
|
211
|
+
VALUE base_mixer_m_initialize(VALUE self) {
|
212
|
+
// The below are set on connect() and voided on disconnect()
|
213
|
+
snd_mixer_t *handle = NULL; // NULL handle
|
214
|
+
snd_mixer_elem_t* elem = NULL; // NULL element
|
215
|
+
|
216
|
+
// Create a Base Mixer struct pointer to access
|
217
|
+
// from the class
|
218
|
+
base_mixer_obj mm = {
|
219
|
+
.handle = handle,
|
220
|
+
.element = elem,
|
221
|
+
};
|
222
|
+
|
223
|
+
MIXLOADER; // Shorthand load the mixer
|
224
|
+
*mixer = mm; // Bind the struct to the class object's pointer
|
225
|
+
return self;
|
226
|
+
} // End mix handle initializer
|
227
|
+
|
228
|
+
// Connect with the ALSA server
|
229
|
+
VALUE method_base_mixer_connect(VALUE self, VALUE card_name, VALUE elem_name) {
|
230
|
+
int err = 0; // Placeholder for errors
|
231
|
+
snd_mixer_selem_id_t *sid; // Create mixer element ID
|
232
|
+
|
233
|
+
// Default mixer will be default/Master
|
234
|
+
const char *card = StringValueCStr(card_name); // ex: "default"
|
235
|
+
const char *selem_name = StringValueCStr(elem_name); // ex: "Master"
|
236
|
+
|
237
|
+
MIXLOADER; // Shorthand load the mixer
|
238
|
+
// If the mixer is already connected, raise an error
|
239
|
+
if (mixer->handle != NULL || mixer->element != NULL) {
|
240
|
+
rb_raise(rb_eRuntimeError,
|
241
|
+
"\n::ERROR: Already connected to mixer! Disconnect first!::\n");
|
242
|
+
return Qnil;
|
243
|
+
}
|
244
|
+
|
245
|
+
// The below will use CRIT_CHECK, as these errors are
|
246
|
+
// non-recoverable, and continuation in other methods
|
247
|
+
// will result in seg faults.
|
248
|
+
//
|
249
|
+
// Open and load a mixer object
|
250
|
+
err = snd_mixer_open(&mixer->handle, 0);
|
251
|
+
CRIT_CHECK;
|
252
|
+
err = snd_mixer_attach(mixer->handle, card);
|
253
|
+
CRIT_CHECK;
|
254
|
+
err = snd_mixer_selem_register(mixer->handle, NULL, NULL);
|
255
|
+
CRIT_CHECK;
|
256
|
+
err = snd_mixer_load(mixer->handle);
|
257
|
+
CRIT_CHECK;
|
258
|
+
|
259
|
+
// Attach a mixer element to the handle
|
260
|
+
snd_mixer_selem_id_alloca(&sid);
|
261
|
+
snd_mixer_selem_id_set_index(sid, 0);
|
262
|
+
snd_mixer_selem_id_set_name(sid, selem_name);
|
263
|
+
|
264
|
+
// Instantiate the mixer element attached to the handle
|
265
|
+
mixer->element = snd_mixer_find_selem(mixer->handle, sid);
|
266
|
+
|
267
|
+
// Checker for valid channels moved to Ruby side
|
268
|
+
return self;
|
269
|
+
} // End connect method
|
270
|
+
|
271
|
+
// Disconnect from the ALSA server
|
272
|
+
VALUE method_base_mixer_disconnect(VALUE self) {
|
273
|
+
MIXLOADER; // Shorthand load the mixer
|
274
|
+
if (mixer->handle != NULL) {
|
275
|
+
int err = snd_mixer_close(mixer->handle); // Close the mixer
|
276
|
+
CRIT_CHECK;
|
277
|
+
mixer->element = NULL;
|
278
|
+
mixer->handle = NULL;
|
279
|
+
} // If it's already NULL, there is nothing to close,
|
280
|
+
// So returning TRUE is still saying the mixer is disconnected
|
281
|
+
return Qtrue;
|
282
|
+
} // End disconnect method
|
283
|
+
|
284
|
+
// Enumerate the channels
|
285
|
+
VALUE method_base_mixer_enum_channels(VALUE self) {
|
286
|
+
MIXLOADER; // Shorthand load the mixer
|
287
|
+
CHK_MIX; // Check if mixer is null or not, before attempting operations
|
288
|
+
VALUE channels = rb_hash_new(); // Hash of channels
|
289
|
+
for (int i = 0; i < (MAX_CHANNELS); i++) {
|
290
|
+
// Check if the channel exists; if so, give it a true key.
|
291
|
+
// Ignore any channels not present -- a bad index returns NIL, anyway
|
292
|
+
if (snd_mixer_selem_has_playback_channel(mixer->element, i)) {
|
293
|
+
rb_hash_aset(channels, INT2NUM(i), Qtrue);
|
294
|
+
}
|
295
|
+
}
|
296
|
+
return channels;
|
297
|
+
} // End channel enumerator
|
298
|
+
|
299
|
+
// Get the volume for a single channel
|
300
|
+
VALUE method_base_mixer_cvolume_get(VALUE self, VALUE cid) {
|
301
|
+
long min, max, current; // Volume values
|
302
|
+
MIXLOADER; // Shorthand load the mixer
|
303
|
+
CHK_MIX; // Check if mixer is null or not, before attempting operations
|
304
|
+
snd_mixer_handle_events(mixer->handle); // Refresh events on handle
|
305
|
+
snd_mixer_selem_get_playback_volume_range(mixer->element, &min, &max); // Get volume range
|
306
|
+
|
307
|
+
// Get the volume for the channel, but only if cid (channel id) is valid
|
308
|
+
if (RB_TYPE_P(cid, T_FIXNUM)){
|
309
|
+
int cid_fix = NUM2INT(cid);
|
310
|
+
if (snd_mixer_selem_has_playback_channel(mixer->element, cid_fix)) {
|
311
|
+
snd_mixer_selem_get_playback_volume(mixer->element, cid_fix, ¤t);
|
312
|
+
VALUE channel = rb_hash_new(); // Channel has volume and percent
|
313
|
+
// Name of channel, if available
|
314
|
+
rb_hash_aset(channel, rb_id2sym(rb_intern("name")),
|
315
|
+
rb_str_new2(snd_mixer_selem_channel_name(cid_fix)));
|
316
|
+
// Minimum and maximum values
|
317
|
+
rb_hash_aset(channel, rb_id2sym(rb_intern("max")), LONG2NUM(max));
|
318
|
+
rb_hash_aset(channel, rb_id2sym(rb_intern("min")), LONG2NUM(min));
|
319
|
+
// Current channel volume
|
320
|
+
rb_hash_aset(channel, rb_id2sym(rb_intern("volume")), LONG2NUM(current));
|
321
|
+
// Get the percentage of the total (round to 0 decimals,
|
322
|
+
// for reasons logical to audio use)
|
323
|
+
int perc = (int) round(( ((double) current / (double) max) ) * 100);
|
324
|
+
rb_hash_aset(channel, rb_id2sym(rb_intern("percent")), INT2NUM(perc));
|
325
|
+
return channel;
|
326
|
+
} else { return Qfalse; } // False if channel doesn't exist
|
327
|
+
} else { return Qnil; } // Nil if channel id is not a number
|
328
|
+
} // End getter for single-channel volume
|
329
|
+
|
330
|
+
// Set volume on a single channel
|
331
|
+
VALUE method_base_mixer_cvolume_set(VALUE self, VALUE channel, VALUE volume) {
|
332
|
+
MIXLOADER; // Shorthand load the mixer
|
333
|
+
CHK_MIX; // Check if mixer is null or not, before attempting operations
|
334
|
+
int ch = NUM2INT(channel); // Cast the channel to an INT
|
335
|
+
// Set the volume for one channel
|
336
|
+
snd_mixer_selem_set_playback_volume(mixer->element, ch, NUM2LONG(volume));
|
337
|
+
return method_base_mixer_cvolume_get(self, channel);
|
338
|
+
} // End set channel volume to specified
|
339
|
+
|
340
|
+
// Set ALL the channels' volumes on the mixer
|
341
|
+
VALUE method_base_mixer_volume_set_all(VALUE self, VALUE volume) {
|
342
|
+
MIXLOADER; // Shorthand load the mixer
|
343
|
+
CHK_MIX; // Check if mixer is null or not, before attempting operations
|
344
|
+
// Set the volume for all channels
|
345
|
+
int err = snd_mixer_selem_set_playback_volume_all(mixer->element, NUM2LONG(volume));
|
346
|
+
return (err ? Qfalse : Qtrue);
|
347
|
+
} // End set volume to specified
|
348
|
+
|
349
|
+
// Initialize the AlsaCore module
|
350
|
+
void Init_alsacore() {
|
351
|
+
AlsaCore = rb_define_module("AlsaCore"); // Module
|
352
|
+
|
353
|
+
// Mixer class
|
354
|
+
BaseMixer = rb_define_class_under(AlsaCore, "BaseMixer", rb_cData);
|
355
|
+
rb_define_alloc_func(BaseMixer, base_mixer_alloc);
|
356
|
+
rb_define_protected_method(BaseMixer, "pro_initialize", base_mixer_m_initialize, 0);
|
357
|
+
|
358
|
+
// Connection methods
|
359
|
+
rb_define_protected_method(BaseMixer, "pro_connect", method_base_mixer_connect, 2);
|
360
|
+
rb_define_protected_method(BaseMixer, "pro_disconnect", method_base_mixer_disconnect, 0);
|
361
|
+
rb_define_protected_method(BaseMixer, "pro_close", method_base_mixer_disconnect, 0);
|
362
|
+
|
363
|
+
// Enumerate the channels
|
364
|
+
rb_define_protected_method(BaseMixer, "pro_enum", method_base_mixer_enum_channels, 0);
|
365
|
+
|
366
|
+
// Get a channel's volume
|
367
|
+
rb_define_protected_method(BaseMixer, "pro_cvolume_get", method_base_mixer_cvolume_get, 1);
|
368
|
+
|
369
|
+
// Setters
|
370
|
+
rb_define_protected_method(BaseMixer, "pro_volume_set", method_base_mixer_volume_set_all, 1);
|
371
|
+
rb_define_protected_method(BaseMixer, "pro_cvolume_set", method_base_mixer_cvolume_set, 2);
|
372
|
+
} // End init
|
data/ext/alsacore/extconf.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# ext/alsacore/extconf.rb
|
2
2
|
require 'mkmf'
|
3
3
|
|
4
|
-
# Build
|
4
|
+
# Build AlsaCore
|
5
5
|
$LFLAGS = '-lasound'
|
6
6
|
have_library("asound")
|
7
7
|
have_header("alsa/asoundlib.h")
|
8
8
|
have_func("snd_mixer_open")
|
9
9
|
have_func("snd_mixer_close")
|
10
|
-
create_makefile("alsacore
|
10
|
+
create_makefile("alsacore")
|
data/lib/alsactl/mixers.rb
CHANGED
data/lib/alsactl/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alsactl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Edelweiss
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
ALSA wrapper in Ruby, utilizing a purely-abstract C-Ruby API backend
|
@@ -21,12 +21,15 @@ extra_rdoc_files:
|
|
21
21
|
- README.md
|
22
22
|
- CHANGELOG.md
|
23
23
|
- LICENSE.txt
|
24
|
+
- changes/0.1.1-critical.md
|
24
25
|
files:
|
25
26
|
- CHANGELOG.md
|
26
27
|
- LICENSE.txt
|
27
28
|
- README.md
|
29
|
+
- Rakefile
|
30
|
+
- changes/0.1.1-critical.md
|
31
|
+
- ext/alsacore/alsacore.c
|
28
32
|
- ext/alsacore/extconf.rb
|
29
|
-
- lib/alsacore/alsacore.so
|
30
33
|
- lib/alsactl.rb
|
31
34
|
- lib/alsactl/mixers.rb
|
32
35
|
- lib/alsactl/version.rb
|
data/lib/alsacore/alsacore.so
DELETED
Binary file
|