├── .gitignore ├── Makefile ├── README.md ├── demo.png ├── libpulse.deps ├── libpulse.vapi ├── meson.build ├── src ├── App.vala ├── Nodes.vala └── Pulse.vala └── subprojects ├── .gitignore └── libgtkflow.wrap /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .gdb_history 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | run: build 2 | G_DEBUG=fatal-criticals gdb -ex run --args build/pulse-flow 3 | 4 | build: configure 5 | ninja -C build 6 | 7 | configure: 8 | [ -f build/build.ninja ] || meson ./build 9 | 10 | clean: 11 | ninja -C build clean 12 | 13 | .PHONY: run build configure clean 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pulse-flow 2 | 3 | A pulseaudio configuration tool 4 | 5 | ![](demo.png) 6 | 7 | ### Dependencies 8 | - [meson (build)](http://mesonbuild.com) 9 | 10 | ### Run 11 | ``` 12 | $ git clone https://github.com/benwaffle/pulse-flow.git 13 | $ cd pulse-flow 14 | $ meson build 15 | $ ninja -C build 16 | $ build/pulse-flow 17 | ``` 18 | -------------------------------------------------------------------------------- /demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwaffle/pulse-flow/3588c5859de016ae776a3beb8d0eda9492aea432/demo.png -------------------------------------------------------------------------------- /libpulse.deps: -------------------------------------------------------------------------------- 1 | posix 2 | -------------------------------------------------------------------------------- /libpulse.vapi: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of PulseAudio. 3 | 4 | Copyright 2009 Lennart Poettering 5 | 6 | PulseAudio is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation; either version 2.1 of the License, 9 | or (at your option) any later version. 10 | 11 | PulseAudio is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with PulseAudio; if not, see . 18 | ***/ 19 | 20 | using GLib; 21 | using Posix; 22 | 23 | [CCode (cheader_filename="pulse/pulseaudio.h")] 24 | namespace PulseAudio { 25 | 26 | [CCode (cname="pa_get_library_version")] 27 | public unowned string get_library_version(); 28 | 29 | [CCode (cname="PA_API_VERSION")] 30 | public const int API_VERSION; 31 | 32 | [CCode (cname="PA_PROTOCOL_VERSION")] 33 | public const int PROTOCOL_VERSION; 34 | 35 | [CCode (cname="PA_MAJOR")] 36 | public const int MAJOR; 37 | 38 | [CCode (cname="PA_MINOR")] 39 | public const int MINOR; 40 | 41 | [CCode (cname="PA_MICRO")] 42 | public const int MICRO; 43 | 44 | [CCode (cname="PA_CHECK_VERSION")] 45 | public bool CHECK_VERSION(int major, int minor, int micro); 46 | 47 | [CCode (cname="PA_INVALID_INDEX")] 48 | public const uint32 INVALID_INDEX; 49 | 50 | [CCode (cname="pa_free_cb_t", has_target=false)] 51 | public delegate void FreeCb(void *p); 52 | 53 | [CCode (cname="pa_sample_format_t", cprefix="PA_SAMPLE_", has_type_id=false)] 54 | public enum SampleFormat { 55 | U8, 56 | ALAW, 57 | ULAW, 58 | S16LE, 59 | S16BE, 60 | FLOAT32LE, 61 | FLOAT32BE, 62 | S32LE, 63 | S32BE, 64 | S24LE, 65 | S24BE, 66 | S24_32LE, 67 | S24_32BE, 68 | MAX, 69 | S16NE, 70 | S16RE, 71 | FLOAT32NE, 72 | FLOAT32RE, 73 | S32NE, 74 | S32RE, 75 | S24NE, 76 | S24RE, 77 | S24_32NE, 78 | S24_32RE; 79 | 80 | [CCode (cname="pa_sample_size_of_format")] 81 | public size_t size(); 82 | 83 | [CCode (cname="pa_sample_format_to_string")] 84 | public unowned string? to_string(); 85 | 86 | [CCode (cname="pa_sample_format_is_le")] 87 | public int is_le(); 88 | 89 | [CCode (cname="pa_sample_format_is_be")] 90 | public int is_be(); 91 | 92 | [CCode (cname="pa_sample_format_is_ne")] 93 | public int is_ne(); 94 | 95 | [CCode (cname="pa_sample_format_is_re")] 96 | public int is_re(); 97 | 98 | [CCode (cname="pa_parse_sample_format")] 99 | public static SampleFormat parse(string b); 100 | } 101 | 102 | [CCode (cname="pa_usec_t")] 103 | public struct usec : uint64 { 104 | } 105 | 106 | [CCode (cname="pa_sample_spec", has_type_id=false)] 107 | public struct SampleSpec { 108 | public SampleFormat format; 109 | public uint32 rate; 110 | public uint8 channels; 111 | 112 | [CCode (cname="PA_SAMPLE_SPEC_SNPRINT_MAX")] 113 | public const size_t SNPRINT_MAX; 114 | 115 | [CCode (cname="pa_bytes_per_second")] 116 | public size_t bytes_per_second(); 117 | 118 | [CCode (cname="pa_frame_size")] 119 | public size_t frame_size(); 120 | 121 | [CCode (cname="pa_sample_size")] 122 | public size_t sample_size(); 123 | 124 | [CCode (cname="pa_bytes_to_usec", instance_pos=1.1)] 125 | public usec bytes_to_usec(size_t size); 126 | 127 | [CCode (cname="pa_usec_to_bytes", instance_pos=1.1)] 128 | public size_t usec_to_bytes(usec u); 129 | 130 | [CCode (cname="pa_sample_spec_init")] 131 | public unowned SampleSpec? init(); 132 | 133 | [CCode (cname="pa_sample_spec_valid")] 134 | public bool valid(); 135 | 136 | [CCode (cname="pa_sample_spec_equal")] 137 | public bool equal(SampleSpec other); 138 | 139 | [CCode (cname="pa_sample_spec_snprint", instance_pos=3.1)] 140 | public unowned string snprint(char[] buf); 141 | 142 | public string sprint() { 143 | var buffer = new char[SNPRINT_MAX]; 144 | this.snprint(buffer); 145 | return (string) buffer; 146 | } 147 | 148 | public string to_string() { 149 | return sprint(); 150 | } 151 | 152 | [CCode (cname="pa_sample_spec_init")] 153 | public SampleSpec(); 154 | } 155 | 156 | // [CCode (cname="PA_BYTES_SNPRINT_MAX")] 157 | [CCode (cname="PA_SAMPLE_SPEC_SNPRINT_MAX")] 158 | public const size_t BYTES_SNPRINT_MAX; 159 | 160 | [CCode (cname="pa_bytes_snprint")] 161 | public unowned string bytes_snprint(char[] buf, uint bytes); 162 | 163 | public string bytes_sprint(uint bytes) { 164 | var buffer = new char[BYTES_SNPRINT_MAX]; 165 | bytes_snprint(buffer, bytes); 166 | return (string) buffer; 167 | } 168 | 169 | [CCode (cname="pa_volume_t", has_type_id=false)] 170 | [SimpleType] 171 | public struct Volume : uint32 { 172 | 173 | [CCode (cname="PA_SW_VOLUME_SNPRINT_DB_MAX")] 174 | public const size_t SW_SNPRINT_DB_MAX; 175 | 176 | [CCode (cname="PA_VOLUME_SNPRINT_MAX")] 177 | public const size_t SNPRINT_MAX; 178 | 179 | [CCode (cname="PA_VOLUME_NORM")] 180 | public const Volume NORM; 181 | 182 | [CCode (cname="PA_VOLUME_MUTED")] 183 | public const Volume MUTED; 184 | 185 | [CCode (cname="PA_VOLUME_MAX")] 186 | public const Volume MAX; 187 | 188 | [CCode (cname="PA_VOLUME_UI_MAX")] 189 | public const Volume UI_MAX; 190 | 191 | [CCode (cname="PA_VOLUME_INVALID")] 192 | public const Volume INVALID; 193 | 194 | [CCode (cname="pa_volume_snprint", instance_pos = 3.1)] 195 | public unowned string snprint(char[] s); 196 | 197 | public string sprint() { 198 | var buffer = new char[SNPRINT_MAX]; 199 | this.snprint(buffer); 200 | return (string) buffer; 201 | } 202 | 203 | public string to_string() { 204 | return sprint(); 205 | } 206 | 207 | [CCode (cname="pa_sw_volume_snprint_dB", instance_pos = 3.1)] 208 | public unowned string sw_snprint_dB(char[] s); 209 | 210 | public string sw_sprint_dB() { 211 | var buffer = new char[SW_SNPRINT_DB_MAX]; 212 | this.sw_snprint_dB(buffer); 213 | return (string) buffer; 214 | } 215 | 216 | [CCode (cname="pa_sw_volume_multiply")] 217 | public Volume sw_multiply(Volume other); 218 | 219 | [CCode (cname="pa_sw_volume_divide")] 220 | public Volume sw_divide(Volume other); 221 | 222 | [CCode (cname="pa_sw_volume_from_dB")] 223 | public static Volume sw_from_dB(double f); 224 | 225 | [CCode (cname="pa_sw_volume_to_dB")] 226 | public double sw_to_dB(); 227 | 228 | [CCode (cname="pa_sw_volume_from_linear")] 229 | public static Volume sw_from_linear(double f); 230 | 231 | [CCode (cname="pa_sw_volume_to_linear")] 232 | public double sw_to_linear(); 233 | } 234 | 235 | [CCode (cname="PA_DECIBEL_MININFTY")] 236 | public const double DECIBEL_MININFTY; 237 | 238 | [CCode (cname="PA_CHANNELS_MAX")] 239 | public const int CHANNELS_MAX; 240 | 241 | [CCode (cname="PA_RATE_MAX")] 242 | public const int RATE_MAX; 243 | 244 | [CCode (cname="pa_cvolume", has_copy_function=false, has_destroy_function=false, has_type_id=false)] 245 | public struct CVolume { 246 | public uint8 channels; 247 | 248 | public Volume values[CHANNELS_MAX]; 249 | 250 | [CCode (cname="PA_SW_CVOLUME_SNPRINT_DB_MAX")] 251 | public const size_t SW_SNPRINT_DB_MAX; 252 | 253 | [CCode (cname="PA_CVOLUME_SNPRINT_MAX")] 254 | public const size_t SNPRINT_MAX; 255 | 256 | [CCode (cname="pa_cvolume_equal")] 257 | public bool equal(CVolume other); 258 | 259 | [CCode (cname="pa_cvolume_init")] 260 | public unowned CVolume? init(); 261 | 262 | [CCode (cname="pa_cvolume_reset")] 263 | public unowned CVolume? reset(uint8 channels); 264 | 265 | [CCode (cname="pa_cvolume_mute")] 266 | public unowned CVolume? mute(uint8 channels); 267 | 268 | [CCode (cname="pa_cvolume_snprint", instance_pos = 3.1)] 269 | public unowned string snprint(char[] s); 270 | 271 | public string sprint() { 272 | var buffer = new char[SNPRINT_MAX]; 273 | this.snprint(buffer); 274 | return (string) buffer; 275 | } 276 | 277 | public string to_string() { 278 | return sprint(); 279 | } 280 | 281 | [CCode (cname="pa_sw_cvolume_snprint_dB", instance_pos = 3.1)] 282 | public unowned string sw_snprint_dB(char [] s); 283 | 284 | public string sw_sprint_dB() { 285 | var buffer = new char[SW_SNPRINT_DB_MAX]; 286 | this.sw_snprint_dB(buffer); 287 | return (string) buffer; 288 | } 289 | 290 | [CCode (cname="pa_cvolume_init")] 291 | public CVolume(); 292 | 293 | [CCode (cname="pa_cvolume_avg")] 294 | public Volume avg(); 295 | 296 | [CCode (cname="pa_cvolume_max")] 297 | public Volume max(); 298 | 299 | [CCode (cname="pa_cvolume_min")] 300 | public Volume min(); 301 | 302 | [CCode (cname="pa_cvolume_avg_mask")] 303 | public Volume avg_mask(ChannelMap map, ChannelPositionMask mask); 304 | 305 | [CCode (cname="pa_cvolume_max_mask")] 306 | public Volume max_mask(ChannelMap map, ChannelPositionMask mask); 307 | 308 | [CCode (cname="pa_cvolume_min_mask")] 309 | public Volume min_mask(ChannelMap map, ChannelPositionMask mask); 310 | 311 | [CCode (cname="pa_cvolume_valid")] 312 | public bool valid(); 313 | 314 | [CCode (cname="pa_cvolume_channels_equal_to")] 315 | public bool channels_equal_to(Volume other); 316 | 317 | [CCode (cname="pa_cvolume_is_muted")] 318 | public bool is_muted(); 319 | 320 | [CCode (cname="pa_cvolume_is_norm")] 321 | public bool is_norm(); 322 | 323 | [CCode (cname="pa_sw_cvolume_multiply")] 324 | public unowned CVolume? multiply(CVolume other); 325 | 326 | [CCode (cname="pa_sw_cvolume_divide")] 327 | public unowned CVolume? divide(CVolume other); 328 | 329 | [CCode (cname="pa_sw_cvolume_multiply_scalar")] 330 | public unowned CVolume? multiply_scalar(Volume other); 331 | 332 | [CCode (cname="pa_sw_cvolume_divide_scalar")] 333 | public unowned CVolume? divide_scalar(Volume other); 334 | 335 | [CCode (cname="pa_cvolume_remap")] 336 | public unowned CVolume? remap(ChannelMap from, ChannelMap to); 337 | 338 | [CCode (cname="pa_cvolume_compatible")] 339 | public bool compatible(SampleSpec ss); 340 | 341 | [CCode (cname="pa_cvolume_compatible_with_channel_map")] 342 | public bool compatible_with_channel_map(ChannelMap cm); 343 | 344 | [CCode (cname="pa_cvolume_set")] 345 | public unowned CVolume? set(uint8 channels, Volume v); 346 | 347 | [CCode (cname="pa_cvolume_get_balance")] 348 | public float get_balance(ChannelMap map); 349 | 350 | [CCode (cname="pa_cvolume_set_balance")] 351 | public unowned CVolume? set_balance(ChannelMap map, float b); 352 | 353 | [CCode (cname="pa_cvolume_get_fade")] 354 | public float get_fade(ChannelMap map); 355 | 356 | [CCode (cname="pa_cvolume_set_fade")] 357 | public unowned CVolume? set_fade(ChannelMap map, float f); 358 | 359 | [CCode (cname="pa_cvolume_scale")] 360 | public unowned CVolume? scale(Volume max); 361 | 362 | [CCode (cname="pa_cvolume_scale_mask")] 363 | public unowned CVolume? scale_mask(Volume max, ChannelMap map, ChannelPositionMask mask); 364 | 365 | [CCode (cname="pa_cvolume_set_position")] 366 | public unowned CVolume? set_position(ChannelMap map, ChannelPosition p, Volume v); 367 | 368 | [CCode (cname="pa_cvolume_get_position")] 369 | public Volume get_position(ChannelMap map, ChannelPosition p); 370 | 371 | [CCode (cname="pa_cvolume_merge")] 372 | public unowned CVolume? merge(CVolume other); 373 | 374 | [CCode (cname="pa_cvolume_inc")] 375 | public unowned CVolume? inc(Volume plus = 1); 376 | 377 | [CCode (cname="pa_cvolume_dec")] 378 | public unowned CVolume? dec(Volume minus = 1); 379 | } 380 | 381 | [CCode (cname="pa_channel_map", has_type_id=false)] 382 | public struct ChannelMap { 383 | public uint8 channels; 384 | // TODO: Replace array length with CHANNELS_MAX once vala's bug #647788 is fixed 385 | public ChannelPosition map[32]; 386 | 387 | [CCode (cname="PA_CHANNEL_MAP_SNPRINT_MAX")] 388 | public const size_t SNPRINT_MAX; 389 | 390 | [CCode (cname="pa_channel_map_init")] 391 | public ChannelMap(); 392 | 393 | [CCode (cname="pa_channel_map_init")] 394 | public unowned ChannelMap? init(); 395 | 396 | [CCode (cname="pa_channel_map_init_mono")] 397 | public unowned ChannelMap? init_mono(); 398 | 399 | [CCode (cname="pa_channel_map_init_stereo")] 400 | public unowned ChannelMap? init_stereo(); 401 | 402 | [CCode (cname="pa_channel_map_init_auto")] 403 | public unowned ChannelMap? init_auto(uint8 channels, ChannelMapDef def = ChannelMapDef.DEFAULT); 404 | 405 | [CCode (cname="pa_channel_map_init_extend")] 406 | public unowned ChannelMap? init_extend(uint8 channels, ChannelMapDef def = ChannelMapDef.DEFAULT); 407 | 408 | [CCode (cname="pa_channel_map_snprint", instance_pos = 3.1)] 409 | public unowned string snprint(char[] s); 410 | 411 | public string sprint() { 412 | var buffer = new char[SNPRINT_MAX]; 413 | this.snprint(buffer); 414 | return (string) buffer; 415 | } 416 | 417 | public string to_string() { 418 | return sprint(); 419 | } 420 | 421 | [CCode (cname="pa_channel_map_parse")] 422 | public unowned ChannelMap? parse(string s); 423 | 424 | [CCode (cname="pa_channel_map_equal")] 425 | public bool equal(ChannelMap other); 426 | 427 | [CCode (cname="pa_channel_map_superset")] 428 | public bool superset(ChannelMap other); 429 | 430 | [CCode (cname="pa_channel_map_valid")] 431 | public bool valid(); 432 | 433 | [CCode (cname="pa_channel_map_compatible")] 434 | public bool compatible(SampleSpec ss); 435 | 436 | [CCode (cname="pa_channel_map_can_balance")] 437 | public bool can_balance(); 438 | 439 | [CCode (cname="pa_channel_map_can_fade")] 440 | public bool can_fade(); 441 | 442 | [CCode (cname="pa_channel_map_to_name")] 443 | public unowned string? to_name(); 444 | 445 | [CCode (cname="pa_channel_map_to_pretty_name")] 446 | public unowned string? to_pretty_name(); 447 | 448 | [CCode (cname="pa_channel_map_has_position")] 449 | public bool has_position(ChannelPosition p); 450 | 451 | [CCode (cname="pa_channel_map_mask")] 452 | public ChannelPositionMask mask(); 453 | } 454 | 455 | [CCode (cname="pa_channel_position_mask_t", has_type_id=false)] 456 | public struct ChannelPositionMask : uint64 { 457 | } 458 | 459 | [CCode (cname="pa_channel_position_t", cprefix="PA_CHANNEL_POSITION_", has_type_id=false)] 460 | public enum ChannelPosition { 461 | INVALID, 462 | MONO, 463 | FRONT_LEFT, 464 | FRONT_RIGHT, 465 | FRONT_CENTER, 466 | REAR_CENTER, 467 | REAR_LEFT, 468 | REAR_RIGHT, 469 | LFE, 470 | FRONT_LEFT_OF_CENTER, 471 | FRONT_RIGHT_OF_CENTER, 472 | SIDE_LEFT, 473 | SIDE_RIGHT, 474 | TOP_CENTER, 475 | AUX0, 476 | AUX1, 477 | AUX2, 478 | AUX3, 479 | AUX4, 480 | AUX5, 481 | AUX6, 482 | AUX7, 483 | AUX8, 484 | AUX9, 485 | AUX10, 486 | AUX11, 487 | AUX12, 488 | AUX13, 489 | AUX14, 490 | AUX15, 491 | AUX16, 492 | AUX17, 493 | AUX18, 494 | AUX19, 495 | AUX20, 496 | AUX21, 497 | AUX22, 498 | AUX23, 499 | AUX24, 500 | AUX25, 501 | AUX26, 502 | AUX27, 503 | AUX28, 504 | AUX29, 505 | AUX30, 506 | AUX31, 507 | MAX; 508 | 509 | [CCode (cname="PA_CHANNEL_POSITION_MASK")] 510 | public ChannelPositionMask mask(); 511 | 512 | [CCode (cname="pa_channel_position_to_string")] 513 | public unowned string? to_string(); 514 | 515 | [CCode (cname="pa_channel_position_to_pretty_string")] 516 | public unowned string? to_pretty_string(); 517 | 518 | [CCode (cname="pa_channel_position_from_string")] 519 | public static ChannelPosition from_string(string s); 520 | } 521 | 522 | [CCode (cname="pa_channel_map_def_t", cprefix="PA_CHANNEL_MAP_", has_type_id=false)] 523 | public enum ChannelMapDef { 524 | AIFF, 525 | WAVEEX, 526 | AUX, 527 | DEFAULT, 528 | 529 | [CCode (cname="PA_CHANNEL_MAP_DEF_MAX")] 530 | MAX 531 | } 532 | 533 | [Compact] 534 | [CCode (cname="pa_proplist", cprefix="pa_proplist_", free_function="pa_proplist_free", has_type_id=false)] 535 | public class Proplist { 536 | 537 | [CCode (cname="PA_PROP_MEDIA_NAME")] 538 | public const string PROP_MEDIA_NAME; 539 | [CCode (cname="PA_PROP_MEDIA_TITLE")] 540 | public const string PROP_MEDIA_TITLE; 541 | [CCode (cname="PA_PROP_MEDIA_ARTIST")] 542 | public const string PROP_MEDIA_ARTIST; 543 | [CCode (cname="PA_PROP_MEDIA_COPYRIGHT")] 544 | public const string PROP_MEDIA_COPYRIGHT; 545 | [CCode (cname="PA_PROP_MEDIA_SOFTWARE")] 546 | public const string PROP_MEDIA_SOFTWARE; 547 | [CCode (cname="PA_PROP_MEDIA_LANGUAGE")] 548 | public const string PROP_MEDIA_LANGUAGE; 549 | [CCode (cname="PA_PROP_MEDIA_FILENAME")] 550 | public const string PROP_MEDIA_FILENAME; 551 | [CCode (cname="PA_PROP_MEDIA_ICON_NAME")] 552 | public const string PROP_MEDIA_ICON_NAME; 553 | [CCode (cname="PA_PROP_MEDIA_ROLE")] 554 | public const string PROP_MEDIA_ROLE; 555 | [CCode (cname="PA_PROP_EVENT_ID")] 556 | public const string PROP_EVENT_ID; 557 | [CCode (cname="PA_PROP_EVENT_DESCRIPTION")] 558 | public const string PROP_EVENT_DESCRIPTION; 559 | [CCode (cname="PA_PROP_EVENT_MOUSE_X")] 560 | public const string PROP_EVENT_MOUSE_X; 561 | [CCode (cname="PA_PROP_EVENT_MOUSE_Y")] 562 | public const string PROP_EVENT_MOUSE_Y; 563 | [CCode (cname="PA_PROP_EVENT_MOUSE_HPOS")] 564 | public const string PROP_EVENT_MOUSE_HPOS; 565 | [CCode (cname="PA_PROP_EVENT_MOUSE_VPOS")] 566 | public const string PROP_EVENT_MOUSE_VPOS; 567 | [CCode (cname="PA_PROP_EVENT_MOUSE_BUTTON")] 568 | public const string PROP_EVENT_MOUSE_BUTTON; 569 | [CCode (cname="PA_PROP_WINDOW_NAME")] 570 | public const string PROP_WINDOW_NAME; 571 | [CCode (cname="PA_PROP_WINDOW_ID")] 572 | public const string PROP_WINDOW_ID; 573 | [CCode (cname="PA_PROP_WINDOW_ICON_NAME")] 574 | public const string PROP_WINDOW_ICON_NAME; 575 | [CCode (cname="PA_PROP_WINDOW_X11_DISPLAY")] 576 | public const string PROP_WINDOW_X11_DISPLAY; 577 | [CCode (cname="PA_PROP_WINDOW_X11_SCREEN")] 578 | public const string PROP_WINDOW_X11_SCREEN; 579 | [CCode (cname="PA_PROP_WINDOW_X11_MONITOR")] 580 | public const string PROP_WINDOW_X11_MONITOR; 581 | [CCode (cname="PA_PROP_WINDOW_X11_XID")] 582 | public const string PROP_WINDOW_X11_XID; 583 | [CCode (cname="PA_PROP_APPLICATION_NAME")] 584 | public const string PROP_APPLICATION_NAME; 585 | [CCode (cname="PA_PROP_APPLICATION_ID")] 586 | public const string PROP_APPLICATION_ID; 587 | [CCode (cname="PA_PROP_APPLICATION_VERSION")] 588 | public const string PROP_APPLICATION_VERSION; 589 | [CCode (cname="PA_PROP_APPLICATION_ICON_NAME")] 590 | public const string PROP_APPLICATION_ICON_NAME; 591 | [CCode (cname="PA_PROP_APPLICATION_LANGUAGE")] 592 | public const string PROP_APPLICATION_LANGUAGE; 593 | [CCode (cname="PA_PROP_APPLICATION_PROCESS_ID")] 594 | public const string PROP_APPLICATION_PROCESS_ID; 595 | [CCode (cname="PA_PROP_APPLICATION_PROCESS_BINARY")] 596 | public const string PROP_APPLICATION_PROCESS_BINARY; 597 | [CCode (cname="PA_PROP_APPLICATION_PROCESS_USER")] 598 | public const string PROP_APPLICATION_PROCESS_USER; 599 | [CCode (cname="PA_PROP_APPLICATION_PROCESS_HOST")] 600 | public const string PROP_APPLICATION_PROCESS_HOST; 601 | [CCode (cname="PA_PROP_APPLICATION_PROCESS_MACHINE_ID")] 602 | public const string PROP_APPLICATION_PROCESS_MACHINE_ID; 603 | [CCode (cname="PA_PROP_APPLICATION_PROCESS_SESSION_ID")] 604 | public const string PROP_APPLICATION_PROCESS_SESSION_ID; 605 | [CCode (cname="PA_PROP_DEVICE_STRING")] 606 | public const string PROP_DEVICE_STRING; 607 | [CCode (cname="PA_PROP_DEVICE_API")] 608 | public const string PROP_DEVICE_API; 609 | [CCode (cname="PA_PROP_DEVICE_DESCRIPTION")] 610 | public const string PROP_DEVICE_DESCRIPTION; 611 | [CCode (cname="PA_PROP_DEVICE_BUS_PATH")] 612 | public const string PROP_DEVICE_BUS_PATH; 613 | [CCode (cname="PA_PROP_DEVICE_SERIAL")] 614 | public const string PROP_DEVICE_SERIAL; 615 | [CCode (cname="PA_PROP_DEVICE_VENDOR_ID")] 616 | public const string PROP_DEVICE_VENDOR_ID; 617 | [CCode (cname="PA_PROP_DEVICE_VENDOR_NAME")] 618 | public const string PROP_DEVICE_VENDOR_NAME; 619 | [CCode (cname="PA_PROP_DEVICE_PRODUCT_ID")] 620 | public const string PROP_DEVICE_PRODUCT_ID; 621 | [CCode (cname="PA_PROP_DEVICE_PRODUCT_NAME")] 622 | public const string PROP_DEVICE_PRODUCT_NAME; 623 | [CCode (cname="PA_PROP_DEVICE_CLASS")] 624 | public const string PROP_DEVICE_CLASS; 625 | [CCode (cname="PA_PROP_DEVICE_FORM_FACTOR")] 626 | public const string PROP_DEVICE_FORM_FACTOR; 627 | [CCode (cname="PA_PROP_DEVICE_BUS")] 628 | public const string PROP_DEVICE_BUS; 629 | [CCode (cname="PA_PROP_DEVICE_ICON_NAME")] 630 | public const string PROP_DEVICE_ICON_NAME; 631 | [CCode (cname="PA_PROP_DEVICE_ACCESS_MODE")] 632 | public const string PROP_DEVICE_ACCESS_MODE; 633 | [CCode (cname="PA_PROP_DEVICE_MASTER_DEVICE")] 634 | public const string PROP_DEVICE_MASTER_DEVICE; 635 | [CCode (cname="PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE")] 636 | public const string PROP_DEVICE_BUFFERING_BUFFER_SIZE; 637 | [CCode (cname="PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE")] 638 | public const string PROP_DEVICE_BUFFERING_FRAGMENT_SIZE; 639 | [CCode (cname="PA_PROP_DEVICE_PROFILE_NAME")] 640 | public const string PROP_DEVICE_PROFILE_NAME; 641 | [CCode (cname="PA_PROP_DEVICE_INTENDED_ROLES")] 642 | public const string PROP_DEVICE_INTENDED_ROLES; 643 | [CCode (cname="PA_PROP_DEVICE_PROFILE_DESCRIPTION")] 644 | public const string PROP_DEVICE_PROFILE_DESCRIPTION; 645 | [CCode (cname="PA_PROP_MODULE_AUTHOR")] 646 | public const string PROP_MODULE_AUTHOR; 647 | [CCode (cname="PA_PROP_MODULE_DESCRIPTION")] 648 | public const string PROP_MODULE_DESCRIPTION; 649 | [CCode (cname="PA_PROP_MODULE_USAGE")] 650 | public const string PROP_MODULE_USAGE; 651 | [CCode (cname="PA_PROP_MODULE_VERSION")] 652 | public const string PROP_MODULE_VERSION; 653 | 654 | [CCode (cname="pa_proplist_new")] 655 | public Proplist(); 656 | 657 | public int sets(string key, string value); 658 | public int setp(string pair); 659 | 660 | [PrintfFormat] 661 | public int setf(string key, string format, ...); 662 | 663 | public int set(string key, void* data, size_t size); 664 | 665 | public unowned string? gets(string key); 666 | 667 | public int get(string key, out void* data, out size_t size); 668 | 669 | public void update(UpdateMode mode, Proplist other); 670 | 671 | public void unset(string key); 672 | 673 | [CCode (array_length = false)] 674 | public void unset_many(string[] key); 675 | 676 | public unowned string? iterate(ref void* state); 677 | 678 | public string to_string(); 679 | 680 | public string to_string_sep(string sep); 681 | 682 | public static Proplist? from_string(string s); 683 | 684 | public bool contains(string key); 685 | 686 | public void clear(); 687 | 688 | public Proplist copy(); 689 | 690 | public uint size(); 691 | 692 | public bool is_empty(); 693 | } 694 | 695 | [CCode (cname="pa_update_mode_t", cprefix="PA_UPDATE_", has_type_id=false)] 696 | public enum UpdateMode { 697 | SET, 698 | MERGE, 699 | REPLACE 700 | } 701 | 702 | [CCode (cname="PA_OK")] 703 | public const int OK; 704 | 705 | [CCode (cname="int", cprefix="PA_ERR_", has_type_id=false)] 706 | public enum Error { 707 | ACCESS, 708 | COMMAND, 709 | INVALID, 710 | EXIST, 711 | NOENTITY, 712 | CONNECTIONREFUSED, 713 | PROTOCOL, 714 | TIMEOUT, 715 | AUTHKEY, 716 | INTERNAL, 717 | CONNECTIONTERMINATED, 718 | KILLED, 719 | INVALIDSERVER, 720 | MODINITFAILED, 721 | BADSTATE, 722 | NODATA, 723 | VERSION, 724 | TOOLARGE, 725 | NOTSUPPORTED, 726 | UNKNOWN, 727 | NOEXTENSION, 728 | OBSOLETE, 729 | NOTIMPLEMENTED, 730 | FORKED, 731 | IO, 732 | MAX 733 | } 734 | 735 | [CCode (cname="pa_strerror")] 736 | public unowned string? strerror(Error e); 737 | 738 | public delegate void VoidFunc(); 739 | 740 | [CCode (cname="pa_spawn_api", has_type_id=false)] 741 | public struct SpawnApi { 742 | VoidFunc? prefork; 743 | VoidFunc? postfork; 744 | VoidFunc? atfork; 745 | } 746 | 747 | [CCode (cname="pa_io_event_flags_t", cprefix="PA_IO_EVENT_", has_type_id=false)] 748 | public enum IoEventFlags { 749 | NULL, 750 | INPUT, 751 | OUTPUT, 752 | HANGUP, 753 | ERROR 754 | } 755 | 756 | [Compact] 757 | [CCode (cname="pa_io_event", unref_function="", ref_function="", has_type_id=false)] 758 | public struct IoEvent { 759 | } 760 | 761 | [Compact] 762 | [CCode (cname="pa_time_event", unref_function="", ref_function="", has_type_id=false)] 763 | public struct TimeEvent { 764 | } 765 | 766 | [Compact] 767 | [CCode (cname="pa_defer_event", unref_function="", ref_function="", has_type_id=false)] 768 | public struct DeferEvent { 769 | } 770 | 771 | [Compact] 772 | [CCode (cname="pa_signal_event", cprefix="pa_signal_", free_function="pa_signal_free", has_type_id=false)] 773 | public struct SignalEvent { 774 | 775 | [CCode (cname="pa_signal_new")] 776 | public SignalEvent(int sig, MainLoopApi.SignalEventCb cb); 777 | 778 | public void set_destroy(MainLoopApi.SignalEventDestroyCb cb); 779 | } 780 | 781 | [Compact] 782 | [CCode (cname="pa_mainloop_api", unref_function="", ref_function="", has_type_id=false)] 783 | public class MainLoopApi { 784 | public void* userdata; 785 | 786 | /* Callbacks for the consumer to implement*/ 787 | public delegate void IoEventCb(MainLoopApi a, IoEvent e, int fd, IoEventFlags flags); 788 | public delegate void IoEventDestroyCb(MainLoopApi a, IoEvent e); 789 | 790 | public delegate void TimeEventCb(MainLoopApi a, TimeEvent e, ref timeval t); 791 | public delegate void TimeEventDestroyCb(MainLoopApi a, TimeEvent e); 792 | 793 | public delegate void DeferEventCb(MainLoopApi a, DeferEvent e); 794 | public delegate void DeferEventDestroyCb(MainLoopApi a, DeferEvent e); 795 | 796 | public delegate void SignalEventCb(MainLoopApi a, SignalEvent e); 797 | public delegate void SignalEventDestroyCb(MainLoopApi a, SignalEvent e); 798 | 799 | /* Callbacks for the provider to implement */ 800 | public delegate IoEvent IoNewCb(MainLoopApi a, int fd, IoEventFlags flags, IoEventCb cb); 801 | public delegate void IoEnableCb(MainLoopApi a, IoEvent e, IoEventFlags flags); 802 | public delegate void IoFreeCb(MainLoopApi a, IoEvent e); 803 | public delegate void IoSetDestroyCb(MainLoopApi a, IoEvent e, IoEventDestroyCb? cb); 804 | 805 | public delegate TimeEvent TimeNewCb(MainLoopApi a, timeval? t, TimeEventCb cb); 806 | public delegate void TimeRestartCb(MainLoopApi a, TimeEvent e, timeval? t); 807 | public delegate void TimeFreeCb(MainLoopApi a, TimeEvent e); 808 | public delegate void TimeSetDestroyCb(MainLoopApi a, TimeEvent e, TimeEventDestroyCb? cb); 809 | 810 | public delegate DeferEvent DeferNewCb(MainLoopApi a, DeferEventCb cb); 811 | public delegate void DeferEnableCb(MainLoopApi a, DeferEvent e, bool b); 812 | public delegate void DeferFreeCb(MainLoopApi a, DeferEvent e); 813 | public delegate void DeferSetDestroyCb(MainLoopApi a, DeferEvent e, DeferEventDestroyCb? cb); 814 | 815 | public delegate void QuitCb(MainLoopApi a, int retval); 816 | 817 | public delegate void OnceCb(MainLoopApi a); 818 | 819 | public IoNewCb io_new; 820 | public IoEnableCb io_enable; 821 | public IoFreeCb io_free; 822 | public IoSetDestroyCb io_set_destroy; 823 | 824 | public TimeNewCb time_new; 825 | public TimeRestartCb time_restart; 826 | public TimeFreeCb time_free; 827 | public TimeSetDestroyCb time_set_destroy; 828 | 829 | public DeferNewCb defer_new; 830 | public DeferEnableCb defer_enable; 831 | public DeferFreeCb defer_free; 832 | public DeferSetDestroyCb defer_set_destroy; 833 | 834 | public QuitCb quit; 835 | 836 | [CCode (cname="pa_mainloop_api_once")] 837 | public void once(OnceCb cb); 838 | } 839 | 840 | [CCode (cname="pa_signal_init")] 841 | public void signal_init(MainLoopApi api); 842 | 843 | [CCode (cname="pa_signal_done")] 844 | public void signal_done(); 845 | 846 | [CCode (cname="pa_poll_func")] 847 | public delegate int PollFunc(pollfd[] ufds, int timeout); 848 | 849 | [Compact] 850 | [CCode (cname="pa_mainloop", cprefix="pa_mainloop_", free_function="pa_mainloop_free", has_type_id=false)] 851 | public class MainLoop { 852 | 853 | [CCode (cname="pa_mainloop_new")] 854 | public MainLoop(); 855 | 856 | public int prepare(int timeout = -1); 857 | public int poll(); 858 | public int dispatch(); 859 | public int get_retval(); 860 | public int iterate(bool block = true, out int retval = null); 861 | public int run(out int retval = null); 862 | public unowned MainLoopApi get_api(); 863 | public void quit(int retval); 864 | public void wakeup(); 865 | public void set_poll_func(PollFunc poll_func); 866 | } 867 | 868 | [Compact] 869 | [CCode (cname="pa_threaded_mainloop", cprefix="pa_threaded_mainloop_", free_function="pa_threaded_mainloop_free")] 870 | public class ThreadedMainLoop { 871 | 872 | [CCode (cname="pa_threaded_mainloop_new")] 873 | public ThreadedMainLoop(); 874 | 875 | public int start(); 876 | public void stop(); 877 | public void lock(); 878 | public void unlock(); 879 | public void wait(); 880 | public void signal(bool WaitForAccept = false); 881 | public void accept(); 882 | public int get_retval(); 883 | public unowned MainLoopApi get_api(); 884 | public bool in_thread(); 885 | } 886 | 887 | [Compact] 888 | [CCode (cname="pa_operation", cprefix="pa_operation_", unref_function="pa_operation_unref", ref_function="pa_operation_ref", has_type_id=false)] 889 | public class Operation { 890 | 891 | [CCode (cname="pa_operation_state_t", cprefix="PA_OPERATION_", has_type_id=false)] 892 | public enum State { 893 | RUNNING, 894 | DONE, 895 | CANCELED 896 | } 897 | 898 | public void cancel(); 899 | public State get_state(); 900 | } 901 | 902 | [Compact] 903 | [CCode (cname="pa_context", cprefix="pa_context_", unref_function="pa_context_unref", ref_function="pa_context_ref", has_type_id=false)] 904 | public class Context { 905 | 906 | [CCode (cname="pa_context_flags_t", cprefix="PA_CONTEXT_", has_type_id=false)] 907 | public enum Flags { 908 | NOAUTOSPAWN, 909 | NOFAIL 910 | } 911 | 912 | [CCode (cname="pa_context_state_t", cprefix="PA_CONTEXT_", has_type_id=false)] 913 | public enum State { 914 | UNCONNECTED, 915 | CONNECTING, 916 | AUTHORIZING, 917 | SETTING_NAME, 918 | READY, 919 | FAILED, 920 | TERMINATED; 921 | 922 | [CCode (cname="PA_CONTEXT_IS_GOOD", has_type_id=false)] 923 | public bool IS_GOOD(); 924 | } 925 | 926 | [CCode (cname="pa_subscription_mask_t", cprefix="PA_SUBSCRIPTION_MASK_", has_type_id=false)] 927 | public enum SubscriptionMask { 928 | NULL, 929 | SINK, 930 | SOURCE, 931 | SINK_INPUT, 932 | SOURCE_OUTPUT, 933 | MODULE, 934 | CLIENT, 935 | SAMPLE_CACHE, 936 | SERVER, 937 | CARD, 938 | ALL; 939 | 940 | [CCode (cname="pa_subscription_match_flags")] 941 | public bool match_flags(SubscriptionEventType t); 942 | } 943 | 944 | [CCode (cname="pa_subscription_event_type_t", cprefix="PA_SUBSCRIPTION_EVENT_", has_type_id=false)] 945 | public enum SubscriptionEventType { 946 | SINK, 947 | SOURCE, 948 | SINK_INPUT, 949 | SOURCE_OUTPUT, 950 | MODULE, 951 | CLIENT, 952 | SAMPLE_CACHE, 953 | SERVER, 954 | [Version (deprecated=true)] 955 | AUTOLOAD, 956 | CARD, 957 | FACILITY_MASK, 958 | NEW, 959 | CHANGE, 960 | REMOVE, 961 | TYPE_MASK; 962 | 963 | public string to_string() { 964 | string type = "unknown"; 965 | if ((this & TYPE_MASK) == NEW) type = "new"; 966 | if ((this & TYPE_MASK) == CHANGE) type = "change"; 967 | if ((this & TYPE_MASK) == REMOVE) type = "remove"; 968 | 969 | string facility = "unknown"; 970 | if ((this & FACILITY_MASK) == SINK) facility = "sink"; 971 | if ((this & FACILITY_MASK) == SOURCE) facility = "source"; 972 | if ((this & FACILITY_MASK) == SINK_INPUT) facility = "sink-input"; 973 | if ((this & FACILITY_MASK) == SOURCE_OUTPUT) facility = "source-output"; 974 | if ((this & FACILITY_MASK) == MODULE) facility = "module"; 975 | if ((this & FACILITY_MASK) == CLIENT) facility = "client"; 976 | if ((this & FACILITY_MASK) == SAMPLE_CACHE) facility = "sample-cache"; 977 | if ((this & FACILITY_MASK) == SERVER) facility = "server"; 978 | if ((this & FACILITY_MASK) == AUTOLOAD) facility = "autoload"; 979 | if ((this & FACILITY_MASK) == CARD) facility = "card"; 980 | 981 | return "Event '%s' on %s".printf (type, facility); 982 | } 983 | } 984 | 985 | [CCode (cname = "pa_context_notify_cb_t")] 986 | public delegate void NotifyCb(Context c); 987 | [CCode (cname = "pa_context_success_cb_t")] 988 | public delegate void SuccessCb(Context c, int success); 989 | [CCode (cname = "pa_context_event_cb_t")] 990 | public delegate void EventCb(Context c, string name, Proplist? proplist); 991 | [CCode (cname = "pa_context_subscribe_cb_t")] 992 | public delegate void SubscribeCb(Context c, SubscriptionEventType t, uint32 idx); 993 | [CCode (cname = "pa_sink_info_cb_t")] 994 | public delegate void SinkInfoCb(Context c, SinkInfo? i, int eol); 995 | [CCode (cname = "pa_source_info_cb_t")] 996 | public delegate void SourceInfoCb(Context c, SourceInfo? i, int eol); 997 | [CCode (cname = "pa_card_info_cb_t")] 998 | public delegate void CardInfoCb(Context c, CardInfo? i, int eol); 999 | [CCode (cname = "pa_sink_input_info_cb_t")] 1000 | public delegate void SinkInputInfoCb(Context c, SinkInputInfo? i, int eol); 1001 | [CCode (cname = "pa_source_output_info_cb_t")] 1002 | public delegate void SourceOutputInfoCb(Context c, SourceOutputInfo? i, int eol); 1003 | [CCode (cname = "pa_server_info_cb_t")] 1004 | public delegate void ServerInfoCb(Context c, ServerInfo? i); 1005 | [CCode (cname = "pa_stat_info_cb_t")] 1006 | public delegate void StatInfoCb(Context c, ServerInfo? i); 1007 | [CCode (cname = "pa_module_info_cb_t")] 1008 | public delegate void ModuleInfoCb(Context c, ModuleInfo? i, int eol); 1009 | [CCode (cname = "pa_client_info_cb_t")] 1010 | public delegate void ClientInfoCb(Context c, ClientInfo? i, int eol); 1011 | [CCode (cname = "pa_sample_info_cb_t")] 1012 | public delegate void SampleInfoCb(Context c, SampleInfo? i, int eol); 1013 | [CCode (cname = "pa_context_index_cb_t")] 1014 | public delegate void IndexCb(Context c, uint32 idx); 1015 | 1016 | [CCode (cname="pa_context_new_with_proplist")] 1017 | public Context(MainLoopApi api, string? name, Proplist? proplist = null); 1018 | 1019 | public void set_state_callback(NotifyCb? cb = null); 1020 | public void set_event_callback(EventCb? cb = null); 1021 | public void set_subscribe_callback(SubscribeCb? cb = null); 1022 | 1023 | public Error errno(); 1024 | 1025 | public int is_pending(); 1026 | public State get_state(); 1027 | public int is_local(); 1028 | public unowned string? get_server(); 1029 | public uint32 get_protocol_version(); 1030 | public uint32 get_server_protocol_version(); 1031 | public uint32 get_index(); 1032 | 1033 | public int connect(string? server = null, Flags flags = 0, SpawnApi? api = null); 1034 | public void disconnect(); 1035 | 1036 | public Operation? drain(NotifyCb? cb = null); 1037 | public Operation? exit_daemon(SuccessCb? cb = null); 1038 | public Operation? set_default_sink(string name, SuccessCb? cb = null); 1039 | public Operation? set_default_source(string name, SuccessCb? cb = null); 1040 | public Operation? set_name(string name, SuccessCb? cb = null); 1041 | 1042 | [CCode (array_length = false)] 1043 | public Operation? proplist_remove(string[] keys, SuccessCb? cb = null); 1044 | public Operation? proplist_update(UpdateMode mode, Proplist pl, SuccessCb? cb = null); 1045 | 1046 | public Operation? subscribe(SubscriptionMask mask, SuccessCb? cb = null); 1047 | 1048 | public Operation? get_sink_info_by_name(string name, SinkInfoCb cb); 1049 | public Operation? get_sink_info_by_index(uint32 idx, SinkInfoCb cb); 1050 | public Operation? get_sink_info_list(SinkInfoCb cb); 1051 | 1052 | public Operation? set_sink_volume_by_name(string name, CVolume volume, SuccessCb? cb = null); 1053 | public Operation? set_sink_volume_by_index(uint32 idx, CVolume volume, SuccessCb? cb = null); 1054 | public Operation? set_sink_mute_by_name(string name, bool mute, SuccessCb? cb = null); 1055 | public Operation? set_sink_mute_by_index(uint32 idx, bool mute, SuccessCb? cb = null); 1056 | 1057 | public Operation? suspend_sink_by_name(string name, bool suspend, SuccessCb? cb = null); 1058 | public Operation? suspend_sink_by_index(uint32 idx, bool suspend, SuccessCb? cb = null); 1059 | 1060 | public Operation? set_sink_port_by_name(string name, string port, SuccessCb? cb = null); 1061 | public Operation? set_sink_port_by_index(uint32 idx, string port, SuccessCb? cb = null); 1062 | 1063 | public Operation? get_source_info_by_name(string name, SourceInfoCb cb); 1064 | public Operation? get_source_info_by_index(uint32 idx, SourceInfoCb cb); 1065 | public Operation? get_source_info_list(SourceInfoCb cb); 1066 | 1067 | public Operation? set_source_volume_by_name(string name, CVolume volume, SuccessCb? cb = null); 1068 | public Operation? set_source_volume_by_index(uint32 idx, CVolume volume, SuccessCb? cb = null); 1069 | public Operation? set_source_mute_by_name(string name, bool mute, SuccessCb? cb = null); 1070 | public Operation? set_source_mute_by_index(uint32 idx, bool mute, SuccessCb? cb = null); 1071 | 1072 | public Operation? suspend_source_by_name(string name, bool suspend, SuccessCb? cb = null); 1073 | public Operation? suspend_source_by_index(uint32 idx, bool suspend, SuccessCb? cb = null); 1074 | 1075 | public Operation? set_source_port_by_name(string name, string port, SuccessCb? cb = null); 1076 | public Operation? set_source_port_by_index(uint32 idx, string port, SuccessCb? cb = null); 1077 | 1078 | public Operation? get_server_info(ServerInfoCb cb); 1079 | 1080 | public Operation? get_module_info(uint32 idx, ModuleInfoCb cb); 1081 | public Operation? get_module_info_list(ModuleInfoCb cb); 1082 | 1083 | public Operation? load_module(string name, string? argument, IndexCb? cb = null); 1084 | public Operation? unload_module(uint32 idx, SuccessCb? cb = null); 1085 | 1086 | public Operation? get_client_info(uint32 idx, ClientInfoCb cb); 1087 | public Operation? get_client_info_list(ClientInfoCb cb); 1088 | 1089 | public Operation? kill_client(uint32 idx, SuccessCb? cb = null); 1090 | 1091 | public Operation? get_card_info_by_name(string name, CardInfoCb cb); 1092 | public Operation? get_card_info_by_index(uint32 idx, CardInfoCb cb); 1093 | public Operation? get_card_info_list(CardInfoCb cb); 1094 | 1095 | public Operation? set_card_profile_by_index(uint32 idx, string profile, SuccessCb? cb = null); 1096 | public Operation? set_card_profile_by_name(string name, string profile, SuccessCb? cb = null); 1097 | 1098 | public Operation? get_sink_input_info(uint32 idx, SinkInputInfoCb cb); 1099 | public Operation? get_sink_input_info_list(SinkInputInfoCb cb); 1100 | 1101 | public Operation? move_sink_input_by_index(uint32 idx, uint32 sink_idx, SuccessCb? cb = null); 1102 | public Operation? move_sink_input_by_name(uint32 idx, string sink_name, SuccessCb? cb = null); 1103 | 1104 | public Operation? set_sink_input_volume(uint32 idx, CVolume volume, SuccessCb? cb = null); 1105 | public Operation? set_sink_input_mute(uint32 idx, bool mute, SuccessCb? cb = null); 1106 | 1107 | public Operation? kill_sink_input(uint32 idx, SuccessCb? cb = null); 1108 | 1109 | public Operation? get_source_output_info(uint32 idx, SourceOutputInfoCb cb); 1110 | public Operation? get_source_output_info_list(SourceOutputInfoCb cb); 1111 | 1112 | public Operation? move_source_output_by_index(uint32 idx, uint32 source_idx, SuccessCb? cb = null); 1113 | public Operation? move_source_output_by_name(uint32 idx, string source_name, SuccessCb? cb = null); 1114 | 1115 | public Operation? kill_source_output(uint32 idx, SuccessCb? cb = null); 1116 | 1117 | public Operation? stat(StatInfoCb cb); 1118 | 1119 | public Operation? get_sample_info_by_name(string name, SampleInfoCb cb); 1120 | public Operation? get_sample_info_by_index(uint32 idx, SampleInfoCb cb); 1121 | public Operation? get_sample_info_list(SampleInfoCb cb); 1122 | 1123 | public Operation? remove_sample(string name, SuccessCb? cb = null); 1124 | 1125 | public Operation? play_sample(string name, string? device = null, Volume volume = Volume.INVALID, SuccessCb? cb = null); 1126 | public Operation? play_sample_with_proplist(string name, string? device = null, Volume volume = Volume.INVALID, Proplist? p = null, IndexCb? cb = null); 1127 | } 1128 | 1129 | [Compact] 1130 | [CCode (cname="pa_stream", cprefix="pa_stream_", unref_function="pa_stream_unref", ref_function="pa_stream_ref", has_type_id=false)] 1131 | public class Stream { 1132 | 1133 | [CCode (cname="pa_stream_flags_t", cprefix="PA_STREAM_", has_type_id=false)] 1134 | public enum Flags { 1135 | START_CORKED, 1136 | INTERPOLATE_TIMING, 1137 | NOT_MONOTONIC, 1138 | AUTO_TIMING_UPDATE, 1139 | NO_REMAP_CHANNELS, 1140 | NO_REMIX_CHANNELS, 1141 | FIX_FORMAT, 1142 | FIX_RATE, 1143 | FIX_CHANNELS, 1144 | DONT_MOVE, 1145 | VARIABLE_RATE, 1146 | PEAK_DETECT, 1147 | START_MUTED, 1148 | ADJUST_LATENCY, 1149 | EARLY_REQUESTS, 1150 | DONT_INHIBIT_AUTO_SUSPEND, 1151 | START_UNMUTED, 1152 | FAIL_ON_SUSPEND 1153 | } 1154 | 1155 | [CCode (cname="pa_stream_state_t", cprefix="PA_STREAM_", has_type_id=false)] 1156 | public enum State { 1157 | UNCONNECTED, 1158 | CREATING, 1159 | READY, 1160 | FAILED, 1161 | TERMINATED; 1162 | 1163 | [CCode (cname="PA_STREAM_IS_GOOD")] 1164 | public bool IS_GOOD(); 1165 | } 1166 | 1167 | [CCode (cname="pa_stream_direction_t", cprefix="PA_STREAM_", has_type_id=false)] 1168 | public enum Direction { 1169 | NODIRECTION, 1170 | PLAYBACK, 1171 | RECORD, 1172 | UPLOAD 1173 | } 1174 | 1175 | [CCode (cname="pa_seek_mode_t", cprefix="PA_SEEK_", has_type_id=false)] 1176 | public enum SeekMode { 1177 | RELATIVE, 1178 | ABSOLUTE, 1179 | RELATIVE_ON_READ, 1180 | RELATIVE_END 1181 | } 1182 | 1183 | [CCode (cname="pa_buffer_attr", has_type_id=false)] 1184 | public struct BufferAttr { 1185 | uint32 maxlength; 1186 | uint32 tlength; 1187 | uint32 prebuf; 1188 | uint32 minreq; 1189 | uint32 fragsize; 1190 | } 1191 | 1192 | [CCode (cname="pa_timing_info", has_type_id=false)] 1193 | public struct TimingInfo { 1194 | timeval timestamp; 1195 | int synchronized_clocks; 1196 | usec sink_usec; 1197 | usec source_usec; 1198 | usec transport_usec; 1199 | int playing; 1200 | int write_index_corrupt; 1201 | int64 write_index; 1202 | int read_index_corrupt; 1203 | int64 read_index; 1204 | usec configured_sink_usec; 1205 | usec configured_source_usec; 1206 | int64 since_underrun; 1207 | } 1208 | 1209 | [CCode (cname="PA_STREAM_EVENT_REQUEST_CORK")] 1210 | public const string EVENT_REQUEST_CORK; 1211 | 1212 | [CCode (cname="PA_STREAM_EVENT_REQUEST_UNCORK")] 1213 | public const string EVENT_REQUEST_UNCORK; 1214 | 1215 | public delegate void SuccessCb(Stream s, int success); 1216 | public delegate void RequestCb(Stream s, size_t nbytes); 1217 | public delegate void NotifyCb(Stream s); 1218 | public delegate void EventCb(Stream s, string name, Proplist proplist); 1219 | 1220 | [CCode (cname="pa_stream_new_with_proplist")] 1221 | public Stream(Context c, string name, SampleSpec ss, ChannelMap? map = null, Proplist? proplist = null); 1222 | 1223 | public State get_state(); 1224 | public Context get_context(); 1225 | public uint32 get_index(); 1226 | public uint32 get_device_index(); 1227 | public unowned string? get_device_name(); 1228 | public int is_suspended(); 1229 | public int is_corked(); 1230 | 1231 | public int connect_playback(string? dev = null, BufferAttr? a = null, Flags flags = 0, CVolume? volume = null, Stream? sync_stream = null); 1232 | public int connect_record(string? dev = null, BufferAttr? a = null, Flags flags = 0); 1233 | public int connect_upload(size_t length); 1234 | public int disconnect(); 1235 | public int finish_upload(); 1236 | 1237 | public int begin_write(out void* data, out size_t nbytes); 1238 | public int cancel_write(); 1239 | public int write(void *data, size_t bytes, FreeCb? free_cb = null, int64 offset = 0, SeekMode mode = SeekMode.RELATIVE); 1240 | public int peek(out void *data, out size_t nbytes); 1241 | public int drop(); 1242 | public size_t writable_size(); 1243 | public size_t readable_size(); 1244 | 1245 | public void set_state_callback(NotifyCb? cb = null); 1246 | public void set_write_callback(RequestCb? cb = null); 1247 | public void set_read_callback(RequestCb? cb = null); 1248 | public void set_overflow_callback(NotifyCb? cb = null); 1249 | public void set_underflow_callback(NotifyCb? cb = null); 1250 | public void set_started_callback(NotifyCb? cb = null); 1251 | public void set_latency_update_callback(NotifyCb? cb = null); 1252 | public void set_moved_callback(NotifyCb? cb = null); 1253 | public void set_suspended_callback(NotifyCb? cb = null); 1254 | public void set_event_callback(EventCb? cb = null); 1255 | public void set_buffer_attr_callback(NotifyCb? cb = null); 1256 | 1257 | public Operation? drain(SuccessCb? cb = null); 1258 | public Operation? update_timing_info(SuccessCb? cb = null); 1259 | 1260 | public Operation? cork(bool b, SuccessCb? cb = null); 1261 | public Operation? flush(SuccessCb? cb = null); 1262 | public Operation? prebuf(SuccessCb? cb = null); 1263 | public Operation? trigger(SuccessCb? cb = null); 1264 | 1265 | public Operation? set_name(string name, SuccessCb? cb = null); 1266 | public Operation? set_buffer_attr(BufferAttr attr, SuccessCb? cb = null); 1267 | public Operation? update_sample_rate(uint32 rate, SuccessCb? cb = null); 1268 | 1269 | [CCode (array_length = false)] 1270 | public Operation? proplist_remove(string[] keys, SuccessCb? cb = null); 1271 | public Operation? proplist_update(UpdateMode mode, Proplist pl, SuccessCb? cb = null); 1272 | 1273 | public unowned TimingInfo? get_timing_info(); 1274 | public int get_time(out usec u); 1275 | public int get_latency(out usec u, out bool negative = null); 1276 | 1277 | public unowned SampleSpec? get_sample_spec(); 1278 | public unowned ChannelMap? get_channel_map(); 1279 | public unowned BufferAttr? get_buffer_attr(); 1280 | 1281 | public int set_monitor_stream(uint32 sink_input); 1282 | public uint32 get_monitor_stream(); 1283 | } 1284 | 1285 | [CCode (cname="pa_sink_port_info", has_type_id=false)] 1286 | public struct SinkPortInfo { 1287 | public string name; 1288 | public string description; 1289 | public uint32 priority; 1290 | } 1291 | 1292 | [CCode (cname="pa_sink_info", has_type_id=false)] 1293 | public struct SinkInfo { 1294 | public string name; 1295 | public uint32 index; 1296 | public string description; 1297 | public SampleSpec sample_spec; 1298 | public ChannelMap channel_map; 1299 | public uint32 owner_module; 1300 | public CVolume volume; 1301 | public int mute; 1302 | public uint32 monitor_source; 1303 | public string monitor_source_name; 1304 | public usec latency; 1305 | public string driver; 1306 | public SinkFlags flags; 1307 | public Proplist proplist; 1308 | public usec configured_latency; 1309 | public Volume base_volume; 1310 | public SinkState state; 1311 | public uint32 n_volume_steps; 1312 | public uint32 card; 1313 | public uint32 n_ports; 1314 | [CCode (array_length_cname = "n_ports", array_length_type = "uint32")] 1315 | public SinkPortInfo*[] ports; 1316 | public SinkPortInfo* active_port; 1317 | } 1318 | 1319 | [CCode (cname="pa_source_port_info", has_type_id=false)] 1320 | public struct SourcePortInfo { 1321 | public string name; 1322 | public string description; 1323 | public uint32 priority; 1324 | } 1325 | 1326 | [CCode (cname="pa_source_info", has_type_id=false)] 1327 | public struct SourceInfo { 1328 | public string name; 1329 | public uint32 index; 1330 | public string description; 1331 | public SampleSpec sample_spec; 1332 | public ChannelMap channel_map; 1333 | public uint32 owner_module; 1334 | public CVolume volume; 1335 | public int mute; 1336 | public uint32 monitor_of_sink; 1337 | public string monitor_of_sink_name; 1338 | public usec latency; 1339 | public string driver; 1340 | public SourceFlags flags; 1341 | public Proplist proplist; 1342 | public usec configured_latency; 1343 | public Volume base_volume; 1344 | public SourceState state; 1345 | public uint32 n_volume_steps; 1346 | public uint32 card; 1347 | public uint32 n_ports; 1348 | [CCode (array_length_cname = "n_ports", array_length_type = "uint32")] 1349 | public SourcePortInfo*[] ports; 1350 | public SourcePortInfo* active_port; 1351 | } 1352 | 1353 | [CCode (cname="pa_server_info", has_type_id=false)] 1354 | public struct ServerInfo { 1355 | public string user_name; 1356 | public string host_name; 1357 | public string server_version; 1358 | public string server_name; 1359 | public SampleSpec sample_spec; 1360 | public string default_sink_name; 1361 | public string default_source_name; 1362 | public ChannelMap channel_map; 1363 | } 1364 | 1365 | [CCode (cname="pa_module_info", has_type_id=false)] 1366 | public struct ModuleInfo { 1367 | public uint32 index; 1368 | public string name; 1369 | public string argument; 1370 | public uint32 n_used; 1371 | public Proplist proplist; 1372 | } 1373 | 1374 | [CCode (cname="pa_client_info", has_type_id=false)] 1375 | public struct ClientInfo { 1376 | public uint32 index; 1377 | public string name; 1378 | public uint32 owner_module; 1379 | public string driver; 1380 | public Proplist proplist; 1381 | } 1382 | 1383 | [CCode (cname="pa_card_profile_info", has_type_id=false)] 1384 | public struct CardProfileInfo { 1385 | public string name; 1386 | public string description; 1387 | public uint32 n_sinks; 1388 | public uint32 n_sources; 1389 | public uint32 priority; 1390 | } 1391 | 1392 | [CCode (cname="pa_card_info", has_type_id=false)] 1393 | public struct CardInfo { 1394 | public uint32 index; 1395 | public string name; 1396 | public uint32 owner_module; 1397 | public string driver; 1398 | public uint32 n_profiles; 1399 | public CardProfileInfo[] profiles; 1400 | public CardProfileInfo *active_profile; 1401 | public Proplist proplist; 1402 | } 1403 | 1404 | [CCode (cname="pa_sink_input_info", has_type_id=false)] 1405 | public struct SinkInputInfo { 1406 | public uint32 index; 1407 | public string name; 1408 | public uint32 owner_module; 1409 | public uint32 client; 1410 | public uint32 sink; 1411 | public SampleSpec sample_spec; 1412 | public ChannelMap channel_map; 1413 | public CVolume volume; 1414 | public uint32 buffer_usec; 1415 | public uint32 sink_usec; 1416 | public string resample_method; 1417 | public string driver; 1418 | public int mute; 1419 | public Proplist proplist; 1420 | public int corked; 1421 | public int has_volume; 1422 | public int volume_writable; 1423 | } 1424 | 1425 | [CCode (cname="pa_source_output_info", has_type_id=false)] 1426 | public struct SourceOutputInfo { 1427 | public uint32 index; 1428 | public string name; 1429 | public uint32 owner_module; 1430 | public uint32 client; 1431 | public uint32 source; 1432 | public SampleSpec sample_spec; 1433 | public ChannelMap channel_map; 1434 | public uint32 buffer_usec; 1435 | public uint32 sink_usec; 1436 | public string resample_method; 1437 | public string driver; 1438 | public Proplist proplist; 1439 | public int corked; 1440 | public CVolume volume; 1441 | public int mute; 1442 | public int has_volume; 1443 | public int volume_writable; 1444 | } 1445 | 1446 | [CCode (cname="pa_stat_info", has_type_id=false)] 1447 | public struct StatInfo { 1448 | public uint32 memblock_total; 1449 | public uint32 memblock_total_size; 1450 | public uint32 memblock_allocated; 1451 | public uint32 memblock_allocated_size; 1452 | public uint32 scache_size; 1453 | } 1454 | 1455 | [CCode (cname="pa_sample_info", has_type_id=false)] 1456 | public struct SampleInfo { 1457 | public uint32 index; 1458 | public string name; 1459 | public CVolume volume; 1460 | public SampleSpec sample_spec; 1461 | public ChannelMap channel_map; 1462 | public usec duration; 1463 | public uint32 bytes; 1464 | public bool lazy; 1465 | public string filename; 1466 | public Proplist proplist; 1467 | } 1468 | 1469 | [CCode (cname="pa_sink_flags_t", cprefix="PA_SINK_", has_type_id=false)] 1470 | public enum SinkFlags { 1471 | HW_VOLUME_CTRL, 1472 | LATENCY, 1473 | HARDWARE, 1474 | NETWORK, 1475 | HW_MUTE_CTRL, 1476 | DECIBEL_VOLUME, 1477 | FLAT_VOLUME, 1478 | DYNAMIC_LATENCY 1479 | } 1480 | 1481 | [CCode (cname="pa_source_flags_t", cprefix="PA_SOURCE_", has_type_id=false)] 1482 | public enum SourceFlags { 1483 | HW_VOLUME_CTRL, 1484 | LATENCY, 1485 | HARDWARE, 1486 | NETWORK, 1487 | HW_MUTE_CTRL, 1488 | DECIBEL_VOLUME, 1489 | DYNAMIC_LATENCY 1490 | } 1491 | 1492 | [CCode (cname="pa_sink_state_t", cprefix="PA_SINK_", has_type_id=false)] 1493 | public enum SinkState { 1494 | INVALID_STATE, 1495 | RUNNING, 1496 | IDLE, 1497 | SUSPENDED; 1498 | 1499 | [CCode (cname="PA_SINK_IS_OPENED")] 1500 | public bool IS_OPENED(); 1501 | } 1502 | 1503 | [CCode (cname="pa_source_state_t", cprefix="PA_SOURCE_", has_type_id=false)] 1504 | public enum SourceState { 1505 | INVALID_STATE, 1506 | RUNNING, 1507 | IDLE, 1508 | SUSPENDED; 1509 | 1510 | [CCode (cname="PA_SOURCE_IS_OPENED")] 1511 | public bool IS_OPENED(); 1512 | } 1513 | 1514 | [CCode (cname="pa_gettimeofday")] 1515 | public unowned timeval gettimeofday(out timeval tv); 1516 | 1517 | [CCode (cname="pa_timeval_diff")] 1518 | public usec timeval_diff(ref timeval a, ref timeval b); 1519 | 1520 | [CCode (cname="pa_timeval_cmp")] 1521 | public int timeval_cmp(ref timeval a, ref timeval b); 1522 | 1523 | [CCode (cname="pa_timeval_age")] 1524 | public usec timeval_age(ref timeval a); 1525 | 1526 | [CCode (cname="pa_timeval_add")] 1527 | public unowned timeval timeval_add(ref timeval tv, usec x); 1528 | 1529 | [CCode (cname="pa_timeval_sub")] 1530 | public unowned timeval timeval_sub(ref timeval tv, usec x); 1531 | 1532 | [CCode (cname="pa_timeval_store")] 1533 | public unowned timeval timeval_store(out timeval tv, usec c); 1534 | 1535 | [CCode (cname="pa_timeval_load")] 1536 | public usec timeval_load(timeval tv); 1537 | 1538 | [CCode (cname="PA_USEC_MAX")] 1539 | public const usec USEC_MAX; 1540 | 1541 | [CCode (cname="PA_USEC_INVALID")] 1542 | public const usec USEC_INVALID; 1543 | 1544 | [CCode (cname="PA_MSEC_PER_SEC")] 1545 | public const usec MSEC_PER_SEC; 1546 | 1547 | [CCode (cname="PA_USEC_PER_SEC")] 1548 | public const usec USEC_PER_SEC; 1549 | 1550 | [CCode (cname="PA_NSEC_PER_SEC")] 1551 | public const uint64 NSEC_PER_SEC; 1552 | 1553 | 1554 | [CCode (cname="PA_USEC_PER_MSEC")] 1555 | public const usec USEC_PER_MSEC; 1556 | 1557 | [CCode (cname="PA_NSEC_PER_MSEC")] 1558 | public const uint64 NSEC_PER_MSEC; 1559 | 1560 | 1561 | [CCode (cname="PA_NSEC_PER_USEC")] 1562 | public const uint64 NSEC_PER_USEC; 1563 | } 1564 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('pulse-flow', 'vala', 'c', 2 | default_options: ['default_library=static']) # link to gtkflow statically 3 | 4 | flow = subproject('libgtkflow', default_options: ['enable_valadoc=false']) 5 | 6 | deps = [ 7 | dependency('glib-2.0'), 8 | dependency('gobject-2.0'), 9 | dependency('gtk+-3.0'), 10 | 11 | dependency('libpulse'), 12 | dependency('libpulse-mainloop-glib'), 13 | ] 14 | 15 | src = files([ 16 | 'src/Pulse.vala', 17 | 'src/Nodes.vala', 18 | 'src/App.vala' 19 | ]) 20 | 21 | executable('pulse-flow', 22 | src, 23 | dependencies: deps, 24 | include_directories: [ 25 | flow.get_variable('gflow_inc'), 26 | flow.get_variable('gtkflow_inc') 27 | ], 28 | link_with: [ 29 | flow.get_variable('gflow'), 30 | flow.get_variable('gtkflow') 31 | ], 32 | vala_args: ['--vapidir=' + meson.current_source_dir()], 33 | install: true) 34 | -------------------------------------------------------------------------------- /src/App.vala: -------------------------------------------------------------------------------- 1 | class App : Gtk.Application { 2 | Pulse pa; 3 | GtkFlow.NodeView nodeview; 4 | 5 | public App () { 6 | Object (application_id: "me.iofel.pulse-flow", 7 | flags: ApplicationFlags.FLAGS_NONE); 8 | } 9 | 10 | public override void activate () { 11 | var win = new Gtk.ApplicationWindow (this); 12 | var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 6); 13 | var sw = new Gtk.ScrolledWindow (null, null); 14 | nodeview = new GtkFlow.NodeView (); 15 | sw.add (nodeview); 16 | box.pack_end (sw, true, true); 17 | win.add (box); 18 | 19 | win.set_default_size (1000, 600); 20 | win.show_all (); 21 | 22 | pa = new Pulse (); 23 | pa.new_node.connect (this.add); 24 | pa.delete_node.connect (this.delete); 25 | } 26 | 27 | // positioning 28 | int srcx = 20; 29 | int sinkx = 500; 30 | int srcy = 20; 31 | int sinky = 20; 32 | 33 | private void add (PANode node) { 34 | nodeview.add_with_child (node, node.child); 35 | 36 | // position the nodes 37 | int x, y; 38 | if (node is PASource || node is PASinkInput) { 39 | x = srcx; 40 | y = srcy; 41 | srcy += 150; 42 | } else { 43 | x = sinkx; 44 | y = sinky; 45 | sinky += 150; 46 | } 47 | 48 | nodeview.set_node_position (node, x, y); 49 | } 50 | 51 | private void delete (PANode node) { 52 | if (node is PASource || node is PASinkInput) { 53 | srcy -= 150; 54 | } else { 55 | sinky -= 150; 56 | } 57 | nodeview.remove_node (node); 58 | } 59 | } 60 | 61 | int main (string[] args) { 62 | return new App ().run (args); 63 | } 64 | -------------------------------------------------------------------------------- /src/Nodes.vala: -------------------------------------------------------------------------------- 1 | using PulseAudio; 2 | 3 | /** 4 | * A class to represent a node in our app 5 | */ 6 | abstract class PANode : GFlow.SimpleNode { 7 | public Pulse pa; 8 | public Gtk.Box child = new Gtk.Box (Gtk.Orientation.VERTICAL, 6); 9 | public uint32 index = PulseAudio.INVALID_INDEX; 10 | 11 | construct { 12 | this.deletable = false; 13 | this.resizable = false; 14 | } 15 | } 16 | 17 | class PASource : PANode { 18 | public GFlow.Source src; 19 | 20 | public PASource (Pulse pa) { 21 | this.pa = pa; 22 | src = new GFlow.SimpleSource (0); 23 | src.name = "output"; 24 | add_source (src); 25 | } 26 | 27 | public void update (SourceInfo info) { 28 | index = info.index; 29 | name = "(Source #%u) %s".printf (index, info.description); 30 | } 31 | } 32 | 33 | class PASink : PANode { 34 | uint32 monitor = PulseAudio.INVALID_INDEX; 35 | public GFlow.Sink sink; 36 | Gtk.Scale volumescale; 37 | Gtk.Label volumelabel = new Gtk.Label ("100% (0.00dB)"); 38 | CVolume vols; 39 | 40 | public PASink (Pulse pa) { 41 | this.pa = pa; 42 | sink = new GFlow.SimpleSink (0); 43 | sink.name = "input"; 44 | (sink as GFlow.SimpleSink).max_sources = -1U; 45 | add_sink (sink); 46 | 47 | volumescale = new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL, 48 | PulseAudio.Volume.MUTED, PulseAudio.Volume.UI_MAX, PulseAudio.Volume.NORM/100.0); 49 | volumescale.set_value (PulseAudio.Volume.NORM); 50 | volumescale.draw_value = false; 51 | volumescale.add_mark (PulseAudio.Volume.NORM, Gtk.PositionType.BOTTOM, "100% (0dB)"); 52 | volumescale.value_changed.connect (() => { 53 | for (var i=0; i { 74 | if (i == null) 75 | return; 76 | var src = new GFlow.SimpleSource (0); 77 | src.name = "monitor"; 78 | add_source (src); 79 | }); 80 | } else { 81 | // delete monitor 82 | } 83 | } 84 | 85 | // TODO handle multiple channels 86 | var volume = info.volume.values[0]; 87 | volumelabel.label = "%s (%s)".printf (volume.sprint (), volume.sw_sprint_dB ()); 88 | volumescale.set_value (volume); 89 | } 90 | } 91 | 92 | class PASinkInput : PANode { 93 | GFlow.Source src; 94 | Gtk.Image img; 95 | 96 | public PASinkInput (Pulse pa) { 97 | this.pa = pa; 98 | img = new Gtk.Image.from_icon_name ("dialog-question", Gtk.IconSize.BUTTON); 99 | child.pack_start (img, false, false); 100 | src = new GFlow.SimpleSource (0); 101 | src.name = "output"; 102 | add_source (src); 103 | } 104 | 105 | public void update (SinkInputInfo info) { 106 | index = info.index; 107 | name = "(Sink Input #%u) %s".printf (index, info.name); 108 | 109 | if (Proplist.PROP_APPLICATION_ICON_NAME in info.proplist) { 110 | img.set_from_icon_name (info.proplist.gets (Proplist.PROP_APPLICATION_ICON_NAME), Gtk.IconSize.BUTTON); 111 | } 112 | 113 | var sink = pa.sinks[info.sink]; 114 | src.unlink_all (); 115 | src.link (sink.sink); 116 | } 117 | } 118 | 119 | class PASourceOutput : PANode { 120 | GFlow.Sink sink; 121 | 122 | public PASourceOutput (Pulse pa) { 123 | this.pa = pa; 124 | sink = new GFlow.SimpleSink (0); 125 | sink.name = "input"; 126 | (sink as GFlow.SimpleSink).max_sources = -1U; 127 | add_sink (sink); 128 | } 129 | 130 | public void update (SourceOutputInfo info) { 131 | index = info.index; 132 | name = "(Source Output #%u) %s".printf (index, info.name); 133 | 134 | var src = pa.sources[info.source]; 135 | src.unlink_all (); 136 | sink.link (src.src); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/Pulse.vala: -------------------------------------------------------------------------------- 1 | using PulseAudio; 2 | 3 | /** 4 | * A class to handle connections to pulseaudio and updates to info 5 | */ 6 | class Pulse : Object { 7 | public PulseAudio.Context ctx; 8 | private PulseAudio.GLibMainLoop loop; 9 | public HashTable sinks = new HashTable (direct_hash, direct_equal); 10 | public HashTable sources = new HashTable (direct_hash, direct_equal); 11 | public HashTable sinkinputs = new HashTable (direct_hash, direct_equal); 12 | public HashTable sourceoutputs = new HashTable (direct_hash, direct_equal); 13 | 14 | public signal void ready (Context ctx); 15 | public signal void new_node (PANode node); 16 | public signal void delete_node (PANode node); 17 | 18 | public Pulse () { 19 | loop = new PulseAudio.GLibMainLoop (); 20 | ctx = new PulseAudio.Context (loop.get_api (), "me.iofel.pulse-flow"); 21 | ctx.set_state_callback (this.state_cb); 22 | ctx.set_subscribe_callback (this.subscribe_cb); 23 | 24 | if (ctx.connect (null, PulseAudio.Context.Flags.NOFAIL) < 0) { 25 | print ("pa_context_connect() failed: %s\n", PulseAudio.strerror (ctx.errno ())); 26 | } 27 | } 28 | 29 | ~Pulse () { 30 | ctx.disconnect (); 31 | } 32 | 33 | /** 34 | * Handle pulseaudio state changes 35 | */ 36 | void state_cb (Context ctx) { 37 | Context.State state = ctx.get_state (); 38 | info (@"pa state = $state\n"); 39 | 40 | if (ctx.get_state () == Context.State.READY) { 41 | ready (ctx); 42 | ctx.subscribe (Context.SubscriptionMask.ALL, null); 43 | ctx.get_sink_info_list (this.sink_cb); 44 | ctx.get_source_info_list (this.source_cb); 45 | ctx.get_sink_input_info_list (this.sink_input_cb); 46 | ctx.get_source_output_info_list (this.source_output_cb); 47 | } 48 | } 49 | 50 | /** 51 | * Handle any changes from pulseaudio 52 | */ 53 | void subscribe_cb (Context ctx, Context.SubscriptionEventType ev, uint32 idx) { 54 | print (@"$ev $idx\n"); 55 | 56 | var type = ev & Context.SubscriptionEventType.TYPE_MASK; // type (new, change, remove) 57 | var facility = ev & Context.SubscriptionEventType.FACILITY_MASK; // facility (sink, source, ...) 58 | 59 | if (type == Context.SubscriptionEventType.NEW || type == Context.SubscriptionEventType.CHANGE) { 60 | if (facility == Context.SubscriptionEventType.SINK) 61 | ctx.get_sink_info_by_index (idx, this.sink_cb); 62 | if (facility == Context.SubscriptionEventType.SOURCE) 63 | ctx.get_source_info_by_index (idx, this.source_cb); 64 | if (facility == Context.SubscriptionEventType.SINK_INPUT) 65 | ctx.get_sink_input_info (idx, this.sink_input_cb); 66 | if (facility == Context.SubscriptionEventType.SOURCE_OUTPUT) 67 | ctx.get_source_output_info (idx, this.source_output_cb); 68 | } else if (type == Context.SubscriptionEventType.REMOVE) { 69 | PANode? node = null; 70 | if (facility == Context.SubscriptionEventType.SINK) { 71 | node = this.sinks[idx]; 72 | this.sinks.remove (idx); 73 | } 74 | if (facility == Context.SubscriptionEventType.SOURCE) { 75 | node = this.sources[idx]; 76 | this.sources.remove (idx); 77 | } 78 | if (facility == Context.SubscriptionEventType.SINK_INPUT) { 79 | node = this.sinkinputs[idx]; 80 | this.sinkinputs.remove (idx); 81 | } 82 | if (facility == Context.SubscriptionEventType.SOURCE_OUTPUT) { 83 | node = this.sourceoutputs[idx]; 84 | this.sourceoutputs.remove (idx); 85 | } 86 | 87 | if (node != null) { 88 | node.index = PulseAudio.INVALID_INDEX; 89 | node.unlink_all (); 90 | delete_node (node); 91 | } 92 | } 93 | } 94 | 95 | void sink_cb (Context ctx, SinkInfo? info, int eol) { 96 | if (eol < 0) error (PulseAudio.strerror (ctx.errno ())); 97 | if (eol > 0) return; 98 | 99 | var sink = sinks[info.index]; 100 | if (sink == null) { 101 | sink = new PASink (this); 102 | sinks[info.index] = sink; 103 | new_node (sink); 104 | } 105 | 106 | sink.update (info); 107 | } 108 | 109 | void source_cb (Context ctx, SourceInfo? info, int eol) { 110 | if (eol < 0) error (PulseAudio.strerror (ctx.errno ())); 111 | if (eol > 0) return; 112 | 113 | // monitors should not be their own nodes 114 | if (info.monitor_of_sink != PulseAudio.INVALID_INDEX) 115 | return; 116 | 117 | PASource source = sources[info.index]; 118 | if (source == null) { 119 | source = new PASource (this); 120 | sources[info.index] = source; 121 | new_node (source); 122 | } 123 | 124 | source.update (info); 125 | } 126 | 127 | void sink_input_cb (Context ctx, SinkInputInfo? info, int eol) { 128 | if (eol < 0) error (PulseAudio.strerror (ctx.errno ())); 129 | if (eol > 0) return; 130 | 131 | // don't show nodes that play the volume changed sound 132 | if (info.name == "audio-volume-change") 133 | return; 134 | 135 | PASinkInput sinkinput = sinkinputs[info.index]; 136 | if (sinkinput == null) { 137 | sinkinput = new PASinkInput (this); 138 | sinkinputs[info.index] = sinkinput; 139 | new_node (sinkinput); 140 | } 141 | 142 | sinkinput.update (info); 143 | } 144 | 145 | void source_output_cb (Context ctx, SourceOutputInfo? info, int eol) { 146 | if (eol < 0) error (PulseAudio.strerror (ctx.errno ())); 147 | if (eol > 0) return; 148 | 149 | // don't show pavucontrol's peak detect nodes 150 | if (Proplist.PROP_MEDIA_NAME in info.proplist && 151 | info.proplist.gets (Proplist.PROP_MEDIA_NAME) == "Peak detect") 152 | return; 153 | 154 | PASourceOutput sourceoutput = sourceoutputs[info.index]; 155 | if (sourceoutput == null) { 156 | sourceoutput = new PASourceOutput (this); 157 | sourceoutputs[info.index] = sourceoutput; 158 | new_node (sourceoutput); 159 | } 160 | 161 | sourceoutput.update (info); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /subprojects/.gitignore: -------------------------------------------------------------------------------- 1 | libgtkflow 2 | -------------------------------------------------------------------------------- /subprojects/libgtkflow.wrap: -------------------------------------------------------------------------------- 1 | [wrap-git] 2 | directory = libgtkflow 3 | url = https://notabug.org/grindhold/libgtkflow.git 4 | revision = 0.6.0 5 | --------------------------------------------------------------------------------