pulseaudio 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.6
1
+ 0.0.7
@@ -1,118 +1,304 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <interface>
3
3
  <!-- interface-requires gtk+ 3.0 -->
4
- <object class="GtkListStore" id="liststore1"/>
4
+ <object class="GtkAdjustment" id="adjustmentSinkVolume">
5
+ <property name="upper">100</property>
6
+ <property name="step_increment">1</property>
7
+ <property name="page_increment">10</property>
8
+ </object>
9
+ <object class="GtkAdjustment" id="adjustmentSourceVolume">
10
+ <property name="upper">100</property>
11
+ <property name="step_increment">1</property>
12
+ <property name="page_increment">10</property>
13
+ </object>
5
14
  <object class="GtkWindow" id="window">
6
15
  <property name="can_focus">False</property>
7
16
  <property name="title" translatable="yes">Choose active sink</property>
8
17
  <property name="window_position">center</property>
9
18
  <property name="default_width">440</property>
10
19
  <property name="default_height">400</property>
20
+ <signal name="window-state-event" handler="on_window_window_state_event" swapped="no"/>
11
21
  <signal name="delete-event" handler="on_window_delete_event" swapped="no"/>
12
22
  <child>
13
- <object class="GtkVPaned" id="vpaned1">
23
+ <object class="GtkNotebook" id="notebook1">
14
24
  <property name="visible">True</property>
15
25
  <property name="can_focus">True</property>
16
- <property name="position">200</property>
17
- <property name="position_set">True</property>
18
26
  <child>
19
- <object class="GtkFrame" id="frame1">
27
+ <object class="GtkVBox" id="vbox1">
20
28
  <property name="visible">True</property>
21
29
  <property name="can_focus">False</property>
22
- <property name="label_xalign">0</property>
23
- <property name="shadow_type">none</property>
30
+ <property name="spacing">4</property>
24
31
  <child>
25
- <object class="GtkAlignment" id="alignment1">
32
+ <object class="GtkFrame" id="frame1">
26
33
  <property name="visible">True</property>
27
34
  <property name="can_focus">False</property>
28
- <property name="left_padding">12</property>
35
+ <property name="label_xalign">0</property>
36
+ <property name="shadow_type">none</property>
29
37
  <child>
30
- <object class="GtkViewport" id="viewport1">
38
+ <object class="GtkAlignment" id="alignment1">
31
39
  <property name="visible">True</property>
32
40
  <property name="can_focus">False</property>
41
+ <property name="left_padding">12</property>
33
42
  <child>
34
- <object class="GtkScrolledWindow" id="scrolledwindow2">
43
+ <object class="GtkTable" id="table1">
35
44
  <property name="visible">True</property>
36
- <property name="can_focus">True</property>
37
- <property name="shadow_type">in</property>
45
+ <property name="can_focus">False</property>
46
+ <property name="n_rows">2</property>
47
+ <property name="n_columns">2</property>
38
48
  <child>
39
- <object class="GtkTreeView" id="tvSinks">
49
+ <object class="GtkHScale" id="hscaleSinkVolume">
40
50
  <property name="visible">True</property>
41
51
  <property name="can_focus">True</property>
42
- <signal name="cursor-changed" handler="on_tvSinks_cursor_changed" swapped="no"/>
43
- <child internal-child="selection">
44
- <object class="GtkTreeSelection" id="treeview-selection1"/>
45
- </child>
52
+ <property name="adjustment">adjustmentSinkVolume</property>
53
+ <property name="round_digits">1</property>
54
+ <property name="draw_value">False</property>
55
+ <signal name="change-value" handler="on_hscaleSinkVolume_change_value" after="yes" swapped="no"/>
46
56
  </object>
57
+ <packing>
58
+ <property name="right_attach">2</property>
59
+ <property name="y_options">GTK_FILL</property>
60
+ </packing>
61
+ </child>
62
+ <child>
63
+ <object class="GtkCheckButton" id="cbSinkMute">
64
+ <property name="label" translatable="yes">Mute</property>
65
+ <property name="use_action_appearance">False</property>
66
+ <property name="visible">True</property>
67
+ <property name="can_focus">True</property>
68
+ <property name="receives_default">False</property>
69
+ <property name="use_action_appearance">False</property>
70
+ <property name="xalign">0</property>
71
+ <property name="draw_indicator">True</property>
72
+ <signal name="toggled" handler="on_cbSinkMute_toggled" after="yes" swapped="no"/>
73
+ </object>
74
+ <packing>
75
+ <property name="right_attach">2</property>
76
+ <property name="top_attach">1</property>
77
+ <property name="bottom_attach">2</property>
78
+ <property name="y_options">GTK_FILL</property>
79
+ </packing>
47
80
  </child>
48
81
  </object>
49
82
  </child>
50
83
  </object>
51
84
  </child>
85
+ <child type="label">
86
+ <object class="GtkLabel" id="label4">
87
+ <property name="visible">True</property>
88
+ <property name="can_focus">False</property>
89
+ <property name="label" translatable="yes">&lt;b&gt;Volume&lt;/b&gt;</property>
90
+ <property name="use_markup">True</property>
91
+ </object>
92
+ </child>
52
93
  </object>
94
+ <packing>
95
+ <property name="expand">False</property>
96
+ <property name="fill">True</property>
97
+ <property name="position">0</property>
98
+ </packing>
53
99
  </child>
54
- <child type="label">
55
- <object class="GtkLabel" id="label1">
100
+ <child>
101
+ <object class="GtkFrame" id="frameChooseDefaultSink">
56
102
  <property name="visible">True</property>
57
103
  <property name="can_focus">False</property>
58
- <property name="label" translatable="yes">&lt;b&gt;Choose active sink&lt;/b&gt;</property>
59
- <property name="use_markup">True</property>
104
+ <property name="label_xalign">0</property>
105
+ <property name="shadow_type">none</property>
106
+ <child>
107
+ <object class="GtkAlignment" id="alignmentChooseDefaultSink">
108
+ <property name="visible">True</property>
109
+ <property name="can_focus">False</property>
110
+ <property name="left_padding">12</property>
111
+ <child>
112
+ <object class="GtkViewport" id="viewport1">
113
+ <property name="visible">True</property>
114
+ <property name="can_focus">False</property>
115
+ <child>
116
+ <object class="GtkScrolledWindow" id="scrolledwindow2">
117
+ <property name="visible">True</property>
118
+ <property name="can_focus">True</property>
119
+ <property name="shadow_type">in</property>
120
+ <child>
121
+ <object class="GtkTreeView" id="tvSinks">
122
+ <property name="visible">True</property>
123
+ <property name="can_focus">True</property>
124
+ <signal name="cursor-changed" handler="on_tvSinks_cursor_changed" swapped="no"/>
125
+ <child internal-child="selection">
126
+ <object class="GtkTreeSelection" id="treeview-selection1"/>
127
+ </child>
128
+ </object>
129
+ </child>
130
+ </object>
131
+ </child>
132
+ </object>
133
+ </child>
134
+ </object>
135
+ </child>
136
+ <child type="label">
137
+ <object class="GtkLabel" id="labelChooseDefaultSink">
138
+ <property name="visible">True</property>
139
+ <property name="can_focus">False</property>
140
+ <property name="label" translatable="yes">&lt;b&gt;Choose default sink&lt;/b&gt;</property>
141
+ <property name="use_markup">True</property>
142
+ </object>
143
+ </child>
60
144
  </object>
145
+ <packing>
146
+ <property name="expand">True</property>
147
+ <property name="fill">True</property>
148
+ <property name="position">1</property>
149
+ </packing>
61
150
  </child>
62
151
  </object>
152
+ </child>
153
+ <child type="tab">
154
+ <object class="GtkLabel" id="label1">
155
+ <property name="visible">True</property>
156
+ <property name="can_focus">False</property>
157
+ <property name="label" translatable="yes">Sinks</property>
158
+ </object>
63
159
  <packing>
64
- <property name="resize">False</property>
65
- <property name="shrink">True</property>
160
+ <property name="tab_fill">False</property>
66
161
  </packing>
67
162
  </child>
68
163
  <child>
69
- <object class="GtkFrame" id="frame2">
164
+ <object class="GtkVBox" id="vbox2">
70
165
  <property name="visible">True</property>
71
166
  <property name="can_focus">False</property>
72
- <property name="label_xalign">0</property>
73
- <property name="shadow_type">none</property>
167
+ <property name="spacing">4</property>
74
168
  <child>
75
- <object class="GtkAlignment" id="alignment2">
169
+ <object class="GtkFrame" id="frameSourceVolume">
76
170
  <property name="visible">True</property>
77
171
  <property name="can_focus">False</property>
78
- <property name="left_padding">12</property>
172
+ <property name="label_xalign">0</property>
173
+ <property name="shadow_type">none</property>
79
174
  <child>
80
- <object class="GtkViewport" id="viewport2">
175
+ <object class="GtkAlignment" id="alignmentSourceVolume">
81
176
  <property name="visible">True</property>
82
177
  <property name="can_focus">False</property>
178
+ <property name="left_padding">12</property>
83
179
  <child>
84
- <object class="GtkScrolledWindow" id="scrolledwindow1">
180
+ <object class="GtkTable" id="tableSourceVolume">
85
181
  <property name="visible">True</property>
86
- <property name="can_focus">True</property>
87
- <property name="shadow_type">in</property>
182
+ <property name="can_focus">False</property>
183
+ <property name="n_rows">2</property>
184
+ <property name="n_columns">2</property>
88
185
  <child>
89
- <object class="GtkTreeView" id="tvSources">
186
+ <object class="GtkHScale" id="hscaleSourceVolume">
90
187
  <property name="visible">True</property>
91
188
  <property name="can_focus">True</property>
92
- <signal name="cursor-changed" handler="on_tvSources_cursor_changed" swapped="no"/>
93
- <child internal-child="selection">
94
- <object class="GtkTreeSelection" id="treeview-selection"/>
95
- </child>
189
+ <property name="adjustment">adjustmentSourceVolume</property>
190
+ <property name="round_digits">1</property>
191
+ <property name="draw_value">False</property>
192
+ <signal name="change-value" handler="on_hscaleSourceVolume_change_value" after="yes" swapped="no"/>
96
193
  </object>
194
+ <packing>
195
+ <property name="right_attach">2</property>
196
+ <property name="y_options">GTK_FILL</property>
197
+ </packing>
198
+ </child>
199
+ <child>
200
+ <object class="GtkCheckButton" id="cbSourceMute">
201
+ <property name="label" translatable="yes">Mute</property>
202
+ <property name="use_action_appearance">False</property>
203
+ <property name="visible">True</property>
204
+ <property name="can_focus">True</property>
205
+ <property name="receives_default">False</property>
206
+ <property name="use_action_appearance">False</property>
207
+ <property name="xalign">0</property>
208
+ <property name="draw_indicator">True</property>
209
+ <signal name="toggled" handler="on_cbSourceMute_toggled" after="yes" swapped="no"/>
210
+ </object>
211
+ <packing>
212
+ <property name="right_attach">2</property>
213
+ <property name="top_attach">1</property>
214
+ <property name="bottom_attach">2</property>
215
+ <property name="y_options">GTK_FILL</property>
216
+ </packing>
97
217
  </child>
98
218
  </object>
99
219
  </child>
100
220
  </object>
101
221
  </child>
222
+ <child type="label">
223
+ <object class="GtkLabel" id="label5">
224
+ <property name="visible">True</property>
225
+ <property name="can_focus">False</property>
226
+ <property name="label" translatable="yes">&lt;b&gt;Volume&lt;/b&gt;</property>
227
+ <property name="use_markup">True</property>
228
+ </object>
229
+ </child>
102
230
  </object>
231
+ <packing>
232
+ <property name="expand">False</property>
233
+ <property name="fill">True</property>
234
+ <property name="position">0</property>
235
+ </packing>
103
236
  </child>
104
- <child type="label">
105
- <object class="GtkLabel" id="label2">
237
+ <child>
238
+ <object class="GtkFrame" id="frame2">
106
239
  <property name="visible">True</property>
107
240
  <property name="can_focus">False</property>
108
- <property name="label" translatable="yes">&lt;b&gt;Choose default source&lt;/b&gt;</property>
109
- <property name="use_markup">True</property>
241
+ <property name="label_xalign">0</property>
242
+ <property name="shadow_type">none</property>
243
+ <child>
244
+ <object class="GtkAlignment" id="alignment2">
245
+ <property name="visible">True</property>
246
+ <property name="can_focus">False</property>
247
+ <property name="left_padding">12</property>
248
+ <child>
249
+ <object class="GtkViewport" id="viewport2">
250
+ <property name="visible">True</property>
251
+ <property name="can_focus">False</property>
252
+ <child>
253
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
254
+ <property name="visible">True</property>
255
+ <property name="can_focus">True</property>
256
+ <property name="shadow_type">in</property>
257
+ <child>
258
+ <object class="GtkTreeView" id="tvSources">
259
+ <property name="visible">True</property>
260
+ <property name="can_focus">True</property>
261
+ <signal name="cursor-changed" handler="on_tvSources_cursor_changed" swapped="no"/>
262
+ <child internal-child="selection">
263
+ <object class="GtkTreeSelection" id="treeview-selection2"/>
264
+ </child>
265
+ </object>
266
+ </child>
267
+ </object>
268
+ </child>
269
+ </object>
270
+ </child>
271
+ </object>
272
+ </child>
273
+ <child type="label">
274
+ <object class="GtkLabel" id="labelChooseDefaultSource">
275
+ <property name="visible">True</property>
276
+ <property name="can_focus">False</property>
277
+ <property name="label" translatable="yes">&lt;b&gt;Choose default source&lt;/b&gt;</property>
278
+ <property name="use_markup">True</property>
279
+ </object>
280
+ </child>
110
281
  </object>
282
+ <packing>
283
+ <property name="expand">True</property>
284
+ <property name="fill">True</property>
285
+ <property name="position">1</property>
286
+ </packing>
111
287
  </child>
112
288
  </object>
113
289
  <packing>
114
- <property name="resize">True</property>
115
- <property name="shrink">True</property>
290
+ <property name="position">1</property>
291
+ </packing>
292
+ </child>
293
+ <child type="tab">
294
+ <object class="GtkLabel" id="label3">
295
+ <property name="visible">True</property>
296
+ <property name="can_focus">False</property>
297
+ <property name="label" translatable="yes">Sources</property>
298
+ </object>
299
+ <packing>
300
+ <property name="position">1</property>
301
+ <property name="tab_fill">False</property>
116
302
  </packing>
117
303
  </child>
118
304
  </object>
@@ -36,12 +36,23 @@ class PulseAudio::Gui::Choose_active_sink_gtk3
36
36
  events = PulseAudio::Events.instance
37
37
  events.connect(:event => :remove, &self.method(:on_remove))
38
38
  events.connect(:event => :new, &self.method(:on_new))
39
+ events.connect(:event => :change, &self.method(:on_change))
39
40
 
40
41
  @sicon = Gtk::StatusIcon.new
41
42
  @sicon.signal_connect("activate", &self.method(:on_sicon_activate))
42
43
  @sicon.signal_connect("popup-menu", &self.method(:on_sicon_popupmenu))
43
44
  @sicon.signal_connect("scroll-event", &self.method(:on_sicon_scroll))
44
45
  self.update_icon
46
+ self.update_sink_info
47
+ self.update_source_info
48
+ end
49
+
50
+ #Called when the window-state is changed to close window instead of minimize.
51
+ def on_window_window_state_event(win, win_state)
52
+ if win_state.new_window_state == 130
53
+ @ui["window"].hide
54
+ @ui["window"].deiconify
55
+ end
45
56
  end
46
57
 
47
58
  #Called when something is removed from PulseAudio. Removes items from the treeviews automatically.
@@ -80,15 +91,27 @@ class PulseAudio::Gui::Choose_active_sink_gtk3
80
91
  end
81
92
  end
82
93
 
94
+ #Called when something is changed. Updates mute-toggle-values, adjustment-values and more automatically.
95
+ def on_change(args)
96
+ event, ele, ele_id = args[:args][:event].to_sym, args[:args][:element].to_s, args[:args][:element_id].to_i
97
+
98
+ if ele == "sink"
99
+ self.update_sink_info
100
+ elsif ele == "source"
101
+ self.update_source_info
102
+ else
103
+ return nil
104
+ end
105
+ end
106
+
83
107
  #Updates the statusicons icon based on the current sinks volume.
84
108
  def update_icon
85
109
  #Get the current active sink which should be manipulated.
86
- sink_def = PulseAudio::Sink.by_default
87
- return nil if !sink_def
110
+ return nil if !@sink
88
111
 
89
112
 
90
113
  #Evaluate which icon is the closest to the current volume.
91
- vol_perc = sink_def.vol_perc
114
+ vol_perc = @sink.vol_perc
92
115
  levels = [0, 33, 66, 100]
93
116
 
94
117
  vol_closest = levels.first
@@ -107,6 +130,52 @@ class PulseAudio::Gui::Choose_active_sink_gtk3
107
130
  @sicon.set_from_file(icon_filepath)
108
131
  end
109
132
 
133
+ def update_sink_info
134
+ if @sink.muted?
135
+ @ui["cbSinkMute"].active = true
136
+ else
137
+ @ui["cbSinkMute"].active = false
138
+ end
139
+
140
+ @ui["adjustmentSinkVolume"].value = @sink.vol_perc.to_f
141
+ end
142
+
143
+ def update_source_info
144
+ if @source.muted?
145
+ @ui["cbSourceMute"].active = true
146
+ else
147
+ @ui["cbSourceMute"].active = false
148
+ end
149
+
150
+ @ui["adjustmentSourceVolume"].value = @source.vol_perc.to_f
151
+ end
152
+
153
+ def on_hscaleSinkVolume_change_value
154
+ GLib.source_remove(@timeout_sink_volume_change) if @timeout_sink_volume_change
155
+
156
+ @timeout_sink_volume_change = GLib.timeout_add(GLib::PRIORITY_DEFAULT_IDLE, 50, proc{
157
+ @timeout_sink_volume_change = nil
158
+ @sink.vol_perc = @ui["adjustmentSinkVolume"].value
159
+ }, nil, nil)
160
+ end
161
+
162
+ def on_hscaleSourceVolume_change_value
163
+ GLib.source_remove(@timeout_source_volume_change) if @timeout_source_volume_change
164
+
165
+ @timeout_source_volume_change = GLib.timeout_add(GLib::PRIORITY_DEFAULT_IDLE, 50, proc{
166
+ @timeout_source_volume_change = nil
167
+ @source.vol_perc = @ui["adjustmentSourceVolume"].value
168
+ }, nil, nil)
169
+ end
170
+
171
+ def on_cbSinkMute_toggled
172
+ @sink.mute = @ui["cbSinkMute"].active
173
+ end
174
+
175
+ def on_cbSourceMute_toggled
176
+ @source.mute = @ui["cbSourceMute"].active
177
+ end
178
+
110
179
  def on_sicon_activate(*args)
111
180
  if !@ui["window"].get_visible
112
181
  @ui["window"].show_all
@@ -118,12 +187,11 @@ class PulseAudio::Gui::Choose_active_sink_gtk3
118
187
  def on_sicon_scroll(sicon, scroll_e, temp)
119
188
  direction = scroll_e.direction.to_s
120
189
  return nil if direction == "smooth"
121
- sink_def = PulseAudio::Sink.by_default
122
190
 
123
191
  if direction == "up"
124
- sink_def.vol_incr
192
+ @sink.vol_incr
125
193
  elsif direction == "down"
126
- sink_def.vol_decr
194
+ @sink.vol_decr
127
195
  end
128
196
 
129
197
  self.update_icon
@@ -146,6 +214,7 @@ class PulseAudio::Gui::Choose_active_sink_gtk3
146
214
 
147
215
  if sink.default?
148
216
  @ui["tvSinks"].selection.select_iter(append_data[:iter])
217
+ @sink = sink
149
218
  end
150
219
  end
151
220
 
@@ -166,6 +235,7 @@ class PulseAudio::Gui::Choose_active_sink_gtk3
166
235
 
167
236
  if source.default?
168
237
  @ui["tvSources"].selection.select_iter(append_data[:iter])
238
+ @source = source
169
239
  end
170
240
  end
171
241
 
@@ -177,7 +247,6 @@ class PulseAudio::Gui::Choose_active_sink_gtk3
177
247
  return nil if @reloading or !@tv_sinks
178
248
  sel = @tv_sinks.sel
179
249
  return nil if !sel
180
- puts sel
181
250
 
182
251
  sink = nil
183
252
  PulseAudio::Sink.list do |sink_i|
@@ -188,8 +257,10 @@ class PulseAudio::Gui::Choose_active_sink_gtk3
188
257
  end
189
258
 
190
259
  raise "Could not find sink." if !sink
260
+ @sink = sink
191
261
  sink.default!
192
262
  self.update_icon
263
+ self.update_sink_info
193
264
  rescue => e
194
265
  Gtk3assist::Msgbox.error(e)
195
266
  end
@@ -210,8 +281,10 @@ class PulseAudio::Gui::Choose_active_sink_gtk3
210
281
  end
211
282
 
212
283
  raise "Could not find source." if !source
284
+ @source = source
213
285
  source.default!
214
286
  self.update_icon
287
+ self.update_source_info
215
288
  rescue => e
216
289
  Gtk3assist::Msgbox.error(e)
217
290
  end
@@ -70,6 +70,18 @@ class PulseAudio::Sink
70
70
  return PulseAudio::Sink.by_id(sink_id.to_i)
71
71
  end
72
72
 
73
+ #This automatically reloads a sink when a 'change'-event appears.
74
+ PulseAudio::Events.instance.connect(:event => :change, :element => "sink") do |args|
75
+ if @@sinks.key?(args[:args][:element_id]) and sink = @@sinks.get(args[:args][:element_id])
76
+ sink.reload
77
+ end
78
+ end
79
+
80
+ #Reloads the information on the sink.
81
+ def reload
82
+ PulseAudio::Sink.list #Reloads information on all sinks.
83
+ end
84
+
73
85
  #Returns a sink by its sink-ID.
74
86
  #===Examples
75
87
  # sink = PulseAudio::Sink.by_id(3)
@@ -134,7 +146,6 @@ class PulseAudio::Sink
134
146
  %x[pactl set-sink-mute #{self.sink_id} 0]
135
147
  end
136
148
 
137
- PulseAudio::Sink.list #reload info.
138
149
  return nil
139
150
  end
140
151
 
@@ -143,7 +154,6 @@ class PulseAudio::Sink
143
154
  # sink.vol_incr if sink.active? #=> nil
144
155
  def vol_incr
145
156
  %x[pactl set-sink-volume #{self.sink_id} -- +5%]
146
- PulseAudio::Sink.list #reload info.
147
157
  return nil
148
158
  end
149
159
 
@@ -152,7 +162,11 @@ class PulseAudio::Sink
152
162
  # sink.vol_decr if sink.active? #=> nil
153
163
  def vol_decr
154
164
  %x[pactl set-sink-volume #{self.sink_id} -- -5%]
155
- PulseAudio::Sink.list #reload info.
165
+ return nil
166
+ end
167
+
168
+ def vol_perc=(newval)
169
+ %x[pactl set-sink-volume #{self.sink_id} #{newval.to_i}%]
156
170
  return nil
157
171
  end
158
172
 
@@ -176,6 +190,7 @@ class PulseAudio::Sink
176
190
  #===Examples
177
191
  # sink.default!
178
192
  def default!
193
+ #Set all inputs to the this sink.
179
194
  PulseAudio::Sink::Input.list do |input|
180
195
  input.sink = self
181
196
  end
@@ -74,11 +74,82 @@ class PulseAudio::Source
74
74
  raise NameError, "No source by that ID: '#{id}' (#{id.class.name})."
75
75
  end
76
76
 
77
+ #This automatically reloads a source when a 'change'-event appears.
78
+ PulseAudio::Events.instance.connect(:event => :change, :element => "source") do |args|
79
+ if @@sources.key?(args[:args][:element_id]) and source = @@sources.get(args[:args][:element_id])
80
+ source.reload
81
+ end
82
+ end
83
+
84
+ #Reloads the information on the source.
85
+ def reload
86
+ PulseAudio::Source.list #Reloads info on all sources.
87
+ end
88
+
77
89
  #Updates the data on the object. This should not be called.
78
90
  def update(args)
79
91
  @args = args
80
92
  end
81
93
 
94
+ #Returns true if the source is muted. Otherwise false.
95
+ #===Examples
96
+ # source.muted? #=> false
97
+ def muted?
98
+ return true if @args[:props]["mute"] == "yes"
99
+ return false
100
+ end
101
+
102
+ #Toggles the mute-functionality of the source. If it is muted: unmutes. If it isnt muted: mutes.
103
+ #===Examples
104
+ # source.mute_toggle #=> nil
105
+ def mute_toggle
106
+ self.mute = !self.muted?
107
+ return nil
108
+ end
109
+
110
+ #Sets the mute to something specific.
111
+ #===Examples
112
+ # source.mute = true #=> nil
113
+ def mute=(val)
114
+ if val
115
+ %x[pactl set-source-mute #{self.source_id} 1]
116
+ else
117
+ %x[pactl set-source-mute #{self.source_id} 0]
118
+ end
119
+
120
+ return nil
121
+ end
122
+
123
+ #Increases the volume of the source by 5%.
124
+ #===Examples
125
+ # source.vol_incr if source.active? #=> nil
126
+ def vol_incr
127
+ %x[pactl set-source-volume #{self.source_id} -- +5%]
128
+ return nil
129
+ end
130
+
131
+ #Decreases the volume of the source by 5%.
132
+ #===Examples
133
+ # source.vol_decr if source.active? #=> nil
134
+ def vol_decr
135
+ %x[pactl set-source-volume #{self.source_id} -- -5%]
136
+ return nil
137
+ end
138
+
139
+ def vol_perc=(newval)
140
+ %x[pactl set-source-volume #{self.source_id} #{newval.to_i}%]
141
+ return nil
142
+ end
143
+
144
+ #Returns the current percent of the volume.
145
+ def vol_perc
146
+ if match = @args[:props]["volume"].to_s.match(/(\d+):\s*(\d+)%/)
147
+ return match[2].to_i
148
+ end
149
+
150
+ raise "Could not figure out the volume."
151
+ end
152
+
82
153
  #Returns the ID of the source.
83
154
  #===Examples
84
155
  # source.source_id #=> 2
data/pulseaudio.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "pulseaudio"
8
- s.version = "0.0.6"
8
+ s.version = "0.0.7"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kasper Johansen"]
12
- s.date = "2012-09-30"
12
+ s.date = "2012-10-03"
13
13
  s.description = "Ruby-library for controlling PulseAudio via 'pactl'."
14
14
  s.email = "k@spernj.org"
15
15
  s.executables = ["pulseaudio_volume.rb"]
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: pulseaudio
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.6
5
+ version: 0.0.7
6
6
  platform: ruby
7
7
  authors:
8
8
  - Kasper Johansen
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-09-30 00:00:00 Z
13
+ date: 2012-10-03 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: wref
@@ -164,7 +164,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
164
164
  requirements:
165
165
  - - ">="
166
166
  - !ruby/object:Gem::Version
167
- hash: -1301824168619278043
167
+ hash: 1285424623138543590
168
168
  segments:
169
169
  - 0
170
170
  version: "0"