├── .gitignore ├── 3rdparty └── pulseaudio-headers │ ├── GPL │ ├── LGPL │ └── pulse │ ├── cdecl.h │ ├── channelmap.h │ ├── context.h │ ├── def.h │ ├── error.h │ ├── ext-device-manager.h │ ├── ext-device-restore.h │ ├── ext-stream-restore.h │ ├── format.h │ ├── gccmacro.h │ ├── glib-mainloop.h │ ├── introspect.h │ ├── mainloop-api.h │ ├── mainloop-signal.h │ ├── mainloop.h │ ├── operation.h │ ├── proplist.h │ ├── pulseaudio.h │ ├── rtclock.h │ ├── sample.h │ ├── scache.h │ ├── simple.h │ ├── stream.h │ ├── subscribe.h │ ├── thread-mainloop.h │ ├── timeval.h │ ├── utf8.h │ ├── util.h │ ├── version.h │ ├── volume.h │ └── xmalloc.h ├── CMakeLists.txt ├── LICENSE.MIT ├── README.md ├── man └── apulse.1 ├── src ├── apulse-channel-map.c ├── apulse-common.c ├── apulse-context.c ├── apulse-ext.c ├── apulse-format-info.c ├── apulse-mainloop-glib.c ├── apulse-mainloop.c ├── apulse-misc.c ├── apulse-operation.c ├── apulse-proplist.c ├── apulse-signal.c ├── apulse-simple.c ├── apulse-stream.c ├── apulse-threaded-mainloop.c ├── apulse-volume.c ├── apulse.h ├── apulse.template ├── ringbuffer.c ├── ringbuffer.h ├── symbolmap ├── trace.c ├── trace.h ├── util.c └── util.h └── tests ├── CMakeLists.txt └── test_ringbuffer.c /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /debian 3 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/cdecl.h: -------------------------------------------------------------------------------- 1 | #ifndef foopulsecdeclhfoo 2 | #define foopulsecdeclhfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | 9 | PulseAudio is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published 11 | by the Free Software Foundation; either version 2.1 of the License, 12 | or (at your option) any later version. 13 | 14 | PulseAudio is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with PulseAudio; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 22 | USA. 23 | ***/ 24 | 25 | /** \file 26 | * C++ compatibility support */ 27 | 28 | #ifdef __cplusplus 29 | /** If using C++ this macro enables C mode, otherwise does nothing */ 30 | #define PA_C_DECL_BEGIN extern "C" { 31 | /** If using C++ this macros switches back to C++ mode, otherwise does nothing */ 32 | #define PA_C_DECL_END } 33 | 34 | #else 35 | /** If using C++ this macro enables C mode, otherwise does nothing */ 36 | #define PA_C_DECL_BEGIN 37 | /** If using C++ this macros switches back to C++ mode, otherwise does nothing */ 38 | #define PA_C_DECL_END 39 | 40 | #endif 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/error.h: -------------------------------------------------------------------------------- 1 | #ifndef fooerrorhfoo 2 | #define fooerrorhfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | Copyright 2006 Pierre Ossman for Cendio AB 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as published 12 | by the Free Software Foundation; either version 2.1 of the License, 13 | or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public License 21 | along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | #include 28 | 29 | /** \file 30 | * Error management */ 31 | 32 | PA_C_DECL_BEGIN 33 | 34 | /** Return a human readable error message for the specified numeric error code */ 35 | const char* pa_strerror(int error); 36 | 37 | PA_C_DECL_END 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/ext-device-manager.h: -------------------------------------------------------------------------------- 1 | #ifndef foopulseextdevicemanagerhfoo 2 | #define foopulseextdevicemanagerhfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2008 Lennart Poettering 8 | Copyright 2009 Colin Guthrie 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as published 12 | by the Free Software Foundation; either version 2.1 of the License, 13 | or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public License 21 | along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | /** \file 31 | * 32 | * Routines for controlling module-device-manager 33 | */ 34 | 35 | PA_C_DECL_BEGIN 36 | 37 | typedef struct pa_ext_device_manager_role_priority_info { 38 | const char *role; 39 | uint32_t priority; 40 | } pa_ext_device_manager_role_priority_info; 41 | 42 | /** Stores information about one device in the device database that is 43 | * maintained by module-device-manager. \since 0.9.21 */ 44 | typedef struct pa_ext_device_manager_info { 45 | const char *name; /**< Identifier string of the device. A string like "sink:" or similar followed by the name of the device. */ 46 | const char *description; /**< The description of the device when it was last seen, if applicable and saved */ 47 | const char *icon; /**< The icon given to the device */ 48 | uint32_t index; /**< The device index if it is currently available or PA_INVALID_INDEX */ 49 | uint32_t n_role_priorities; /**< How many role priorities do we have? */ 50 | pa_ext_device_manager_role_priority_info *role_priorities; /**< An array of role priority structures or NULL */ 51 | } pa_ext_device_manager_info; 52 | 53 | /** Callback prototype for pa_ext_device_manager_test(). \since 0.9.21 */ 54 | typedef void (*pa_ext_device_manager_test_cb_t)( 55 | pa_context *c, 56 | uint32_t version, 57 | void *userdata); 58 | 59 | /** Test if this extension module is available in the server. \since 0.9.21 */ 60 | pa_operation *pa_ext_device_manager_test( 61 | pa_context *c, 62 | pa_ext_device_manager_test_cb_t cb, 63 | void *userdata); 64 | 65 | /** Callback prototype for pa_ext_device_manager_read(). \since 0.9.21 */ 66 | typedef void (*pa_ext_device_manager_read_cb_t)( 67 | pa_context *c, 68 | const pa_ext_device_manager_info *info, 69 | int eol, 70 | void *userdata); 71 | 72 | /** Read all entries from the device database. \since 0.9.21 */ 73 | pa_operation *pa_ext_device_manager_read( 74 | pa_context *c, 75 | pa_ext_device_manager_read_cb_t cb, 76 | void *userdata); 77 | 78 | /** Sets the description for a device. \since 0.9.21 */ 79 | pa_operation *pa_ext_device_manager_set_device_description( 80 | pa_context *c, 81 | const char* device, 82 | const char* description, 83 | pa_context_success_cb_t cb, 84 | void *userdata); 85 | 86 | /** Delete entries from the device database. \since 0.9.21 */ 87 | pa_operation *pa_ext_device_manager_delete( 88 | pa_context *c, 89 | const char *const s[], 90 | pa_context_success_cb_t cb, 91 | void *userdata); 92 | 93 | /** Enable the role-based device-priority routing mode. \since 0.9.21 */ 94 | pa_operation *pa_ext_device_manager_enable_role_device_priority_routing( 95 | pa_context *c, 96 | int enable, 97 | pa_context_success_cb_t cb, 98 | void *userdata); 99 | 100 | /** Prefer a given device in the priority list. \since 0.9.21 */ 101 | pa_operation *pa_ext_device_manager_reorder_devices_for_role( 102 | pa_context *c, 103 | const char* role, 104 | const char** devices, 105 | pa_context_success_cb_t cb, 106 | void *userdata); 107 | 108 | /** Subscribe to changes in the device database. \since 0.9.21 */ 109 | pa_operation *pa_ext_device_manager_subscribe( 110 | pa_context *c, 111 | int enable, 112 | pa_context_success_cb_t cb, 113 | void *userdata); 114 | 115 | /** Callback prototype for pa_ext_device_manager_set_subscribe_cb(). \since 0.9.21 */ 116 | typedef void (*pa_ext_device_manager_subscribe_cb_t)( 117 | pa_context *c, 118 | void *userdata); 119 | 120 | /** Set the subscription callback that is called when 121 | * pa_ext_device_manager_subscribe() was called. \since 0.9.21 */ 122 | void pa_ext_device_manager_set_subscribe_cb( 123 | pa_context *c, 124 | pa_ext_device_manager_subscribe_cb_t cb, 125 | void *userdata); 126 | 127 | PA_C_DECL_END 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/ext-device-restore.h: -------------------------------------------------------------------------------- 1 | #ifndef foopulseextdevicerestorehfoo 2 | #define foopulseextdevicerestorehfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2008 Lennart Poettering 8 | Copyright 2011 Colin Guthrie 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as published 12 | by the Free Software Foundation; either version 2.1 of the License, 13 | or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public License 21 | along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | /** \file 31 | * 32 | * Routines for controlling module-device-restore 33 | */ 34 | 35 | PA_C_DECL_BEGIN 36 | 37 | /** Stores information about one device in the device database that is 38 | * maintained by module-device-manager. \since 1.0 */ 39 | typedef struct pa_ext_device_restore_info { 40 | pa_device_type_t type; /**< Device type sink or source? */ 41 | uint32_t index; /**< The device index */ 42 | uint8_t n_formats; /**< How many formats do we have? */ 43 | pa_format_info **formats; /**< An array of formats (may be NULL if n_formats == 0) */ 44 | } pa_ext_device_restore_info; 45 | 46 | /** Callback prototype for pa_ext_device_restore_test(). \since 1.0 */ 47 | typedef void (*pa_ext_device_restore_test_cb_t)( 48 | pa_context *c, 49 | uint32_t version, 50 | void *userdata); 51 | 52 | /** Test if this extension module is available in the server. \since 1.0 */ 53 | pa_operation *pa_ext_device_restore_test( 54 | pa_context *c, 55 | pa_ext_device_restore_test_cb_t cb, 56 | void *userdata); 57 | 58 | /** Subscribe to changes in the device database. \since 1.0 */ 59 | pa_operation *pa_ext_device_restore_subscribe( 60 | pa_context *c, 61 | int enable, 62 | pa_context_success_cb_t cb, 63 | void *userdata); 64 | 65 | /** Callback prototype for pa_ext_device_restore_set_subscribe_cb(). \since 1.0 */ 66 | typedef void (*pa_ext_device_restore_subscribe_cb_t)( 67 | pa_context *c, 68 | pa_device_type_t type, 69 | uint32_t idx, 70 | void *userdata); 71 | 72 | /** Set the subscription callback that is called when 73 | * pa_ext_device_restore_subscribe() was called. \since 1.0 */ 74 | void pa_ext_device_restore_set_subscribe_cb( 75 | pa_context *c, 76 | pa_ext_device_restore_subscribe_cb_t cb, 77 | void *userdata); 78 | 79 | /** Callback prototype for pa_ext_device_restore_read_formats(). \since 1.0 */ 80 | typedef void (*pa_ext_device_restore_read_device_formats_cb_t)( 81 | pa_context *c, 82 | const pa_ext_device_restore_info *info, 83 | int eol, 84 | void *userdata); 85 | 86 | /** Read the formats for all present devices from the device database. \since 1.0 */ 87 | pa_operation *pa_ext_device_restore_read_formats_all( 88 | pa_context *c, 89 | pa_ext_device_restore_read_device_formats_cb_t cb, 90 | void *userdata); 91 | 92 | /** Read an entry from the device database. \since 1.0 */ 93 | pa_operation *pa_ext_device_restore_read_formats( 94 | pa_context *c, 95 | pa_device_type_t type, 96 | uint32_t idx, 97 | pa_ext_device_restore_read_device_formats_cb_t cb, 98 | void *userdata); 99 | 100 | /** Read an entry from the device database. \since 1.0 */ 101 | pa_operation *pa_ext_device_restore_save_formats( 102 | pa_context *c, 103 | pa_device_type_t type, 104 | uint32_t idx, 105 | uint8_t n_formats, 106 | pa_format_info **formats, 107 | pa_context_success_cb_t cb, 108 | void *userdata); 109 | 110 | PA_C_DECL_END 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/ext-stream-restore.h: -------------------------------------------------------------------------------- 1 | #ifndef foopulseextstreamrestorehfoo 2 | #define foopulseextstreamrestorehfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2008 Lennart Poettering 8 | 9 | PulseAudio is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published 11 | by the Free Software Foundation; either version 2.1 of the License, 12 | or (at your option) any later version. 13 | 14 | PulseAudio is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with PulseAudio; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 22 | USA. 23 | ***/ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | /** \file 32 | * 33 | * Routines for controlling module-stream-restore 34 | */ 35 | 36 | PA_C_DECL_BEGIN 37 | 38 | /** Stores information about one entry in the stream database that is 39 | * maintained by module-stream-restore. \since 0.9.12 */ 40 | typedef struct pa_ext_stream_restore_info { 41 | const char *name; /**< Identifier string of the stream. A string like "sink-input-by-role:" or similar followed by some arbitrary property value. */ 42 | pa_channel_map channel_map; /**< The channel map for the volume field, if applicable */ 43 | pa_cvolume volume; /**< The volume of the stream when it was seen last, if applicable and saved */ 44 | const char *device; /**< The sink/source of the stream when it was last seen, if applicable and saved */ 45 | int mute; /**< The boolean mute state of the stream when it was last seen, if applicable and saved */ 46 | } pa_ext_stream_restore_info; 47 | 48 | /** Callback prototype for pa_ext_stream_restore_test(). \since 0.9.12 */ 49 | typedef void (*pa_ext_stream_restore_test_cb_t)( 50 | pa_context *c, 51 | uint32_t version, 52 | void *userdata); 53 | 54 | /** Test if this extension module is available in the server. \since 0.9.12 */ 55 | pa_operation *pa_ext_stream_restore_test( 56 | pa_context *c, 57 | pa_ext_stream_restore_test_cb_t cb, 58 | void *userdata); 59 | 60 | /** Callback prototype for pa_ext_stream_restore_read(). \since 0.9.12 */ 61 | typedef void (*pa_ext_stream_restore_read_cb_t)( 62 | pa_context *c, 63 | const pa_ext_stream_restore_info *info, 64 | int eol, 65 | void *userdata); 66 | 67 | /** Read all entries from the stream database. \since 0.9.12 */ 68 | pa_operation *pa_ext_stream_restore_read( 69 | pa_context *c, 70 | pa_ext_stream_restore_read_cb_t cb, 71 | void *userdata); 72 | 73 | /** Store entries in the stream database. \since 0.9.12 */ 74 | pa_operation *pa_ext_stream_restore_write( 75 | pa_context *c, 76 | pa_update_mode_t mode, 77 | const pa_ext_stream_restore_info data[], 78 | unsigned n, 79 | int apply_immediately, 80 | pa_context_success_cb_t cb, 81 | void *userdata); 82 | 83 | /** Delete entries from the stream database. \since 0.9.12 */ 84 | pa_operation *pa_ext_stream_restore_delete( 85 | pa_context *c, 86 | const char *const s[], 87 | pa_context_success_cb_t cb, 88 | void *userdata); 89 | 90 | /** Subscribe to changes in the stream database. \since 0.9.12 */ 91 | pa_operation *pa_ext_stream_restore_subscribe( 92 | pa_context *c, 93 | int enable, 94 | pa_context_success_cb_t cb, 95 | void *userdata); 96 | 97 | /** Callback prototype for pa_ext_stream_restore_set_subscribe_cb(). \since 0.9.12 */ 98 | typedef void (*pa_ext_stream_restore_subscribe_cb_t)( 99 | pa_context *c, 100 | void *userdata); 101 | 102 | /** Set the subscription callback that is called when 103 | * pa_ext_stream_restore_subscribe() was called. \since 0.9.12 */ 104 | void pa_ext_stream_restore_set_subscribe_cb( 105 | pa_context *c, 106 | pa_ext_stream_restore_subscribe_cb_t cb, 107 | void *userdata); 108 | 109 | PA_C_DECL_END 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/format.h: -------------------------------------------------------------------------------- 1 | #ifndef fooformathfoo 2 | #define fooformathfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2011 Intel Corporation 8 | Copyright 2011 Collabora Multimedia 9 | Copyright 2011 Arun Raghavan 10 | 11 | PulseAudio is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU Lesser General Public License as published 13 | by the Free Software Foundation; either version 2.1 of the License, 14 | or (at your option) any later version. 15 | 16 | PulseAudio is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public License 22 | along with PulseAudio; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 24 | USA. 25 | ***/ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | /** \file 34 | * Utility functions for handling a stream or sink format. */ 35 | 36 | PA_C_DECL_BEGIN 37 | 38 | /** Represents the type of encoding used in a stream or accepted by a sink. \since 1.0 */ 39 | typedef enum pa_encoding { 40 | PA_ENCODING_ANY, 41 | /**< Any encoding format, PCM or compressed */ 42 | 43 | PA_ENCODING_PCM, 44 | /**< Any PCM format */ 45 | 46 | PA_ENCODING_AC3_IEC61937, 47 | /**< AC3 data encapsulated in IEC 61937 header/padding */ 48 | 49 | PA_ENCODING_EAC3_IEC61937, 50 | /**< EAC3 data encapsulated in IEC 61937 header/padding */ 51 | 52 | PA_ENCODING_MPEG_IEC61937, 53 | /**< MPEG-1 or MPEG-2 (Part 3, not AAC) data encapsulated in IEC 61937 header/padding */ 54 | 55 | PA_ENCODING_DTS_IEC61937, 56 | /**< DTS data encapsulated in IEC 61937 header/padding */ 57 | 58 | PA_ENCODING_MPEG2_AAC_IEC61937, 59 | /**< MPEG-2 AAC data encapsulated in IEC 61937 header/padding. \since 4.0 */ 60 | 61 | PA_ENCODING_MAX, 62 | /**< Valid encoding types must be less than this value */ 63 | 64 | PA_ENCODING_INVALID = -1, 65 | /**< Represents an invalid encoding */ 66 | } pa_encoding_t; 67 | 68 | /** \cond fulldocs */ 69 | #define PA_ENCODING_ANY PA_ENCODING_ANY 70 | #define PA_ENCODING_PCM PA_ENCODING_PCM 71 | #define PA_ENCODING_AC3_IEC61937 PA_ENCODING_AC3_IEC61937 72 | #define PA_ENCODING_EAC3_IEC61937 PA_ENCODING_EAC3_IEC61937 73 | #define PA_ENCODING_MPEG_IEC61937 PA_ENCODING_MPEG_IEC61937 74 | #define PA_ENCODING_DTS_IEC61937 PA_ENCODING_DTS_IEC61937 75 | #define PA_ENCODING_MPEG2_AAC_IEC61937 PA_ENCODING_MPEG2_AAC_IEC61937 76 | #define PA_ENCODING_MAX PA_ENCODING_MAX 77 | #define PA_ENCODING_INVALID PA_ENCODING_INVALID 78 | /** \endcond */ 79 | 80 | /** Returns a printable string representing the given encoding type. \since 1.0 */ 81 | const char *pa_encoding_to_string(pa_encoding_t e) PA_GCC_CONST; 82 | 83 | /** Converts a string of the form returned by \a pa_encoding_to_string() back to a \a pa_encoding_t. \since 1.0 */ 84 | pa_encoding_t pa_encoding_from_string(const char *encoding); 85 | 86 | /** Represents the format of data provided in a stream or processed by a sink. \since 1.0 */ 87 | typedef struct pa_format_info { 88 | pa_encoding_t encoding; 89 | /**< The encoding used for the format */ 90 | 91 | pa_proplist *plist; 92 | /**< Additional encoding-specific properties such as sample rate, bitrate, etc. */ 93 | } pa_format_info; 94 | 95 | /** Allocates a new \a pa_format_info structure. Clients must initialise at least the encoding field themselves. \since 1.0 */ 96 | pa_format_info* pa_format_info_new(void); 97 | 98 | /** Returns a new \a pa_format_info struct and representing the same format as \a src. \since 1.0 */ 99 | pa_format_info* pa_format_info_copy(const pa_format_info *src); 100 | 101 | /** Frees a \a pa_format_info structure. \since 1.0 */ 102 | void pa_format_info_free(pa_format_info *f); 103 | 104 | /** Returns non-zero when the format info structure is valid. \since 1.0 */ 105 | int pa_format_info_valid(const pa_format_info *f); 106 | 107 | /** Returns non-zero when the format info structure represents a PCM (i.e.\ uncompressed data) format. \since 1.0 */ 108 | int pa_format_info_is_pcm(const pa_format_info *f); 109 | 110 | /** Returns non-zero if the format represented by \a first is a subset of 111 | * the format represented by \a second. This means that \a second must 112 | * have all the fields that \a first does, but the reverse need not 113 | * be true. This is typically expected to be used to check if a 114 | * stream's format is compatible with a given sink. In such a case, 115 | * \a first would be the sink's format and \a second would be the 116 | * stream's. \since 1.0 */ 117 | int pa_format_info_is_compatible(const pa_format_info *first, const pa_format_info *second); 118 | 119 | /** Maximum required string length for 120 | * pa_format_info_snprint(). Please note that this value can change 121 | * with any release without warning and without being considered API 122 | * or ABI breakage. You should not use this definition anywhere where 123 | * it might become part of an ABI. \since 1.0 */ 124 | #define PA_FORMAT_INFO_SNPRINT_MAX 256 125 | 126 | /** Return a human-readable string representing the given format. \since 1.0 */ 127 | char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f); 128 | 129 | /** Parse a human-readable string of the form generated by 130 | * \a pa_format_info_snprint() into a pa_format_info structure. \since 1.0 */ 131 | pa_format_info* pa_format_info_from_string(const char *str); 132 | 133 | /** Utility function to take a \a pa_sample_spec and generate the corresponding 134 | * \a pa_format_info. 135 | * 136 | * Note that if you want the server to choose some of the stream parameters, 137 | * for example the sample rate, so that they match the device parameters, then 138 | * you shouldn't use this function. In order to allow the server to choose 139 | * a parameter value, that parameter must be left unspecified in the 140 | * pa_format_info object, and this function always specifies all parameters. An 141 | * exception is the channel map: if you pass NULL for the channel map, then the 142 | * channel map will be left unspecified, allowing the server to choose it. 143 | * 144 | * \since 2.0 */ 145 | pa_format_info* pa_format_info_from_sample_spec(const pa_sample_spec *ss, const pa_channel_map *map); 146 | 147 | /** Utility function to generate a \a pa_sample_spec and \a pa_channel_map corresponding to a given \a pa_format_info. The 148 | * conversion for PCM formats is straight-forward. For non-PCM formats, if there is a fixed size-time conversion (i.e. all 149 | * IEC61937-encapsulated formats), a "fake" sample spec whose size-time conversion corresponds to this format is provided and 150 | * the channel map argument is ignored. For formats with variable size-time conversion, this function will fail. Returns a 151 | * negative integer if conversion failed and 0 on success. \since 2.0 */ 152 | int pa_format_info_to_sample_spec(const pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map); 153 | 154 | /** Represents the type of value type of a property on a \ref pa_format_info. \since 2.0 */ 155 | typedef enum pa_prop_type_t { 156 | PA_PROP_TYPE_INT, 157 | /**< Integer property */ 158 | 159 | PA_PROP_TYPE_INT_RANGE, 160 | /**< Integer range property */ 161 | 162 | PA_PROP_TYPE_INT_ARRAY, 163 | /**< Integer array property */ 164 | 165 | PA_PROP_TYPE_STRING, 166 | /**< String property */ 167 | 168 | PA_PROP_TYPE_STRING_ARRAY, 169 | /**< String array property */ 170 | 171 | PA_PROP_TYPE_INVALID = -1, 172 | /**< Represents an invalid type */ 173 | } pa_prop_type_t; 174 | 175 | /** \cond fulldocs */ 176 | #define PA_PROP_TYPE_INT PA_PROP_TYPE_INT 177 | #define PA_PROP_TYPE_INT_RANGE PA_PROP_TYPE_INT_RANGE 178 | #define PA_PROP_TYPE_INT_ARRAY PA_PROP_TYPE_INT_ARRAY 179 | #define PA_PROP_TYPE_STRING PA_PROP_TYPE_STRING 180 | #define PA_PROP_TYPE_STRING_ARRAY PA_PROP_TYPE_STRING_ARRAY 181 | #define PA_PROP_TYPE_INVALID PA_PROP_TYPE_INVALID 182 | /** \endcond */ 183 | 184 | /** Gets the type of property \a key in a given \ref pa_format_info. \since 2.0 */ 185 | pa_prop_type_t pa_format_info_get_prop_type(const pa_format_info *f, const char *key); 186 | 187 | /** Gets an integer property from the given format info. Returns 0 on success and a negative integer on failure. \since 2.0 */ 188 | int pa_format_info_get_prop_int(const pa_format_info *f, const char *key, int *v); 189 | /** Gets an integer range property from the given format info. Returns 0 on success and a negative integer on failure. 190 | * \since 2.0 */ 191 | int pa_format_info_get_prop_int_range(const pa_format_info *f, const char *key, int *min, int *max); 192 | /** Gets an integer array property from the given format info. \a values contains the values and \a n_values contains the 193 | * number of elements. The caller must free \a values using \ref pa_xfree. Returns 0 on success and a negative integer on 194 | * failure. \since 2.0 */ 195 | int pa_format_info_get_prop_int_array(const pa_format_info *f, const char *key, int **values, int *n_values); 196 | /** Gets a string property from the given format info. The caller must free the returned string using \ref pa_xfree. Returns 197 | * 0 on success and a negative integer on failure. \since 2.0 */ 198 | int pa_format_info_get_prop_string(const pa_format_info *f, const char *key, char **v); 199 | /** Gets a string array property from the given format info. \a values contains the values and \a n_values contains 200 | * the number of elements. The caller must free \a values using \ref pa_format_info_free_string_array. Returns 0 on success and 201 | * a negative integer on failure. \since 2.0 */ 202 | int pa_format_info_get_prop_string_array(const pa_format_info *f, const char *key, char ***values, int *n_values); 203 | 204 | /** Frees a string array returned by \ref pa_format_info_get_prop_string_array. \since 2.0 */ 205 | void pa_format_info_free_string_array(char **values, int n_values); 206 | 207 | /** Sets an integer property on the given format info. \since 1.0 */ 208 | void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value); 209 | /** Sets a property with a list of integer values on the given format info. \since 1.0 */ 210 | void pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values); 211 | /** Sets a property which can have any value in a given integer range on the given format info. \since 1.0 */ 212 | void pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max); 213 | /** Sets a string property on the given format info. \since 1.0 */ 214 | void pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value); 215 | /** Sets a property with a list of string values on the given format info. \since 1.0 */ 216 | void pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values); 217 | 218 | /** Convenience method to set the sample format as a property on the given 219 | * format. 220 | * 221 | * Note for PCM: If the sample format is left unspecified in the pa_format_info 222 | * object, then the server will select the stream sample format. In that case 223 | * the stream sample format will most likely match the device sample format, 224 | * meaning that sample format conversion will be avoided. 225 | * 226 | * \since 1.0 */ 227 | void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf); 228 | 229 | /** Convenience method to set the sampling rate as a property on the given 230 | * format. 231 | * 232 | * Note for PCM: If the sample rate is left unspecified in the pa_format_info 233 | * object, then the server will select the stream sample rate. In that case the 234 | * stream sample rate will most likely match the device sample rate, meaning 235 | * that sample rate conversion will be avoided. 236 | * 237 | * \since 1.0 */ 238 | void pa_format_info_set_rate(pa_format_info *f, int rate); 239 | 240 | /** Convenience method to set the number of channels as a property on the given 241 | * format. 242 | * 243 | * Note for PCM: If the channel count is left unspecified in the pa_format_info 244 | * object, then the server will select the stream channel count. In that case 245 | * the stream channel count will most likely match the device channel count, 246 | * meaning that up/downmixing will be avoided. 247 | * 248 | * \since 1.0 */ 249 | void pa_format_info_set_channels(pa_format_info *f, int channels); 250 | 251 | /** Convenience method to set the channel map as a property on the given 252 | * format. 253 | * 254 | * Note for PCM: If the channel map is left unspecified in the pa_format_info 255 | * object, then the server will select the stream channel map. In that case the 256 | * stream channel map will most likely match the device channel map, meaning 257 | * that remixing will be avoided. 258 | * 259 | * \since 1.0 */ 260 | void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map); 261 | 262 | PA_C_DECL_END 263 | 264 | #endif 265 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/gccmacro.h: -------------------------------------------------------------------------------- 1 | #ifndef foopulsegccmacrohfoo 2 | #define foopulsegccmacrohfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | 9 | PulseAudio is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published 11 | by the Free Software Foundation; either version 2.1 of the License, 12 | or (at your option) any later version. 13 | 14 | PulseAudio is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with PulseAudio; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 22 | USA. 23 | ***/ 24 | 25 | /** \file 26 | * GCC attribute macros */ 27 | 28 | #if defined(__GNUC__) 29 | #ifdef __MINGW32__ 30 | /* libintl overrides printf with a #define. As this breaks this attribute, 31 | * it has a workaround. However the workaround isn't enabled for MINGW 32 | * builds (only cygwin) */ 33 | #define PA_GCC_PRINTF_ATTR(a,b) __attribute__ ((format (__printf__, a, b))) 34 | #else 35 | #define PA_GCC_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b))) 36 | #endif 37 | #else 38 | /** If we're in GNU C, use some magic for detecting invalid format strings */ 39 | #define PA_GCC_PRINTF_ATTR(a,b) 40 | #endif 41 | 42 | #if defined(__GNUC__) && (__GNUC__ >= 4) 43 | #define PA_GCC_SENTINEL __attribute__ ((sentinel)) 44 | #else 45 | /** Macro for usage of GCC's sentinel compilation warnings */ 46 | #define PA_GCC_SENTINEL 47 | #endif 48 | 49 | #ifdef __GNUC__ 50 | #define PA_GCC_NORETURN __attribute__((noreturn)) 51 | #else 52 | /** Macro for no-return functions */ 53 | #define PA_GCC_NORETURN 54 | #endif 55 | 56 | #ifdef __GNUC__ 57 | #define PA_GCC_UNUSED __attribute__ ((unused)) 58 | #else 59 | /** Macro for not used function, variable or parameter */ 60 | #define PA_GCC_UNUSED 61 | #endif 62 | 63 | #ifdef __GNUC__ 64 | #define PA_GCC_DESTRUCTOR __attribute__ ((destructor)) 65 | #else 66 | /** Call this function when process terminates */ 67 | #define PA_GCC_DESTRUCTOR 68 | #endif 69 | 70 | #ifndef PA_GCC_PURE 71 | #ifdef __GNUC__ 72 | #define PA_GCC_PURE __attribute__ ((pure)) 73 | #else 74 | /** This function's return value depends only the arguments list and global state **/ 75 | #define PA_GCC_PURE 76 | #endif 77 | #endif 78 | 79 | #ifndef PA_GCC_CONST 80 | #ifdef __GNUC__ 81 | #define PA_GCC_CONST __attribute__ ((const)) 82 | #else 83 | /** This function's return value depends only the arguments list (stricter version of PA_GCC_PURE) **/ 84 | #define PA_GCC_CONST 85 | #endif 86 | #endif 87 | 88 | #ifndef PA_GCC_DEPRECATED 89 | #ifdef __GNUC__ 90 | #define PA_GCC_DEPRECATED __attribute__ ((deprecated)) 91 | #else 92 | /** This function is deprecated **/ 93 | #define PA_GCC_DEPRECATED 94 | #endif 95 | #endif 96 | 97 | #ifndef PA_GCC_PACKED 98 | #ifdef __GNUC__ 99 | #define PA_GCC_PACKED __attribute__ ((packed)) 100 | #else 101 | /** Structure shall be packed in memory **/ 102 | #define PA_GCC_PACKED 103 | #endif 104 | #endif 105 | 106 | #ifndef PA_GCC_ALLOC_SIZE 107 | #if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3) 108 | #define PA_GCC_ALLOC_SIZE(x) __attribute__ ((__alloc_size__(x))) 109 | #define PA_GCC_ALLOC_SIZE2(x,y) __attribute__ ((__alloc_size__(x,y))) 110 | #else 111 | /** Macro for usage of GCC's alloc_size attribute */ 112 | #define PA_GCC_ALLOC_SIZE(x) 113 | /** Macro for usage of GCC's alloc_size attribute */ 114 | #define PA_GCC_ALLOC_SIZE2(x,y) 115 | #endif 116 | #endif 117 | 118 | #ifndef PA_GCC_MALLOC 119 | #ifdef __GNUC__ 120 | #define PA_GCC_MALLOC __attribute__ ((malloc)) 121 | #else 122 | /** Macro for usage of GCC's malloc attribute */ 123 | #define PA_GCC_MALLOC 124 | #endif 125 | #endif 126 | 127 | #ifndef PA_GCC_WEAKREF 128 | #if defined(__GNUC__) && defined(__ELF__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ > 1)) || (__GNUC__ > 4)) 129 | /** Macro for usage of GCC's weakref attribute */ 130 | #define PA_GCC_WEAKREF(x) __attribute__((weakref(#x))) 131 | #endif 132 | #endif 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/glib-mainloop.h: -------------------------------------------------------------------------------- 1 | #ifndef fooglibmainloophfoo 2 | #define fooglibmainloophfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | Copyright 2006 Pierre Ossman for Cendio AB 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as published 12 | by the Free Software Foundation; either version 2.1 of the License, 13 | or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public License 21 | along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | /** \page glib-mainloop GLIB Main Loop Bindings 33 | * 34 | * \section overv_sec Overview 35 | * 36 | * The GLIB main loop bindings are extremely easy to use. All that is 37 | * required is to create a pa_glib_mainloop object using 38 | * pa_glib_mainloop_new(). When the main loop abstraction is needed, it is 39 | * provided by pa_glib_mainloop_get_api(). 40 | * 41 | */ 42 | 43 | /** \file 44 | * GLIB main loop support 45 | * 46 | * See also \subpage glib-mainloop 47 | */ 48 | 49 | PA_C_DECL_BEGIN 50 | 51 | /** An opaque GLIB main loop object */ 52 | typedef struct pa_glib_mainloop pa_glib_mainloop; 53 | 54 | /** Create a new GLIB main loop object for the specified GLIB main 55 | * loop context. Takes an argument c for the 56 | * GMainContext to use. If c is NULL the default context is used. */ 57 | pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c); 58 | 59 | /** Free the GLIB main loop object */ 60 | void pa_glib_mainloop_free(pa_glib_mainloop* g); 61 | 62 | /** Return the abstract main loop API vtable for the GLIB main loop 63 | object. No need to free the API as it is owned by the loop 64 | and is destroyed when the loop is freed. */ 65 | pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g); 66 | 67 | PA_C_DECL_END 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/mainloop-api.h: -------------------------------------------------------------------------------- 1 | #ifndef foomainloopapihfoo 2 | #define foomainloopapihfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | Copyright 2006 Pierre Ossman for Cendio AB 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as 12 | published by the Free Software Foundation; either version 2.1 of the 13 | License, or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | /** \file 32 | * 33 | * Main loop abstraction layer. Both the PulseAudio core and the 34 | * PulseAudio client library use a main loop abstraction layer. Due to 35 | * this it is possible to embed PulseAudio into other 36 | * applications easily. Two main loop implementations are 37 | * currently available: 38 | * \li A minimal implementation based on the C library's poll() function (See \ref mainloop.h) 39 | * \li A wrapper around the GLIB main loop. Use this to embed PulseAudio into your GLIB/GTK+/GNOME programs (See \ref glib-mainloop.h) 40 | * 41 | * The structure pa_mainloop_api is used as vtable for the main loop abstraction. 42 | * 43 | * This mainloop abstraction layer has no direct support for UNIX signals. Generic, mainloop implementation agnostic support is available through \ref mainloop-signal.h. 44 | * */ 45 | 46 | PA_C_DECL_BEGIN 47 | 48 | /** An abstract mainloop API vtable */ 49 | typedef struct pa_mainloop_api pa_mainloop_api; 50 | 51 | /** A bitmask for IO events */ 52 | typedef enum pa_io_event_flags { 53 | PA_IO_EVENT_NULL = 0, /**< No event */ 54 | PA_IO_EVENT_INPUT = 1, /**< Input event */ 55 | PA_IO_EVENT_OUTPUT = 2, /**< Output event */ 56 | PA_IO_EVENT_HANGUP = 4, /**< Hangup event */ 57 | PA_IO_EVENT_ERROR = 8 /**< Error event */ 58 | } pa_io_event_flags_t; 59 | 60 | /** An opaque IO event source object */ 61 | typedef struct pa_io_event pa_io_event; 62 | /** An IO event callback prototype \since 0.9.3 */ 63 | typedef void (*pa_io_event_cb_t)(pa_mainloop_api*ea, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata); 64 | /** A IO event destroy callback prototype \ since 0.9.3 */ 65 | typedef void (*pa_io_event_destroy_cb_t)(pa_mainloop_api*a, pa_io_event *e, void *userdata); 66 | 67 | /** An opaque timer event source object */ 68 | typedef struct pa_time_event pa_time_event; 69 | /** A time event callback prototype \since 0.9.3 */ 70 | typedef void (*pa_time_event_cb_t)(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata); 71 | /** A time event destroy callback prototype \ since 0.9.3 */ 72 | typedef void (*pa_time_event_destroy_cb_t)(pa_mainloop_api*a, pa_time_event *e, void *userdata); 73 | 74 | /** An opaque deferred event source object. Events of this type are triggered once in every main loop iteration */ 75 | typedef struct pa_defer_event pa_defer_event; 76 | /** A defer event callback prototype \since 0.9.3 */ 77 | typedef void (*pa_defer_event_cb_t)(pa_mainloop_api*a, pa_defer_event* e, void *userdata); 78 | /** A defer event destroy callback prototype \ since 0.9.3 */ 79 | typedef void (*pa_defer_event_destroy_cb_t)(pa_mainloop_api*a, pa_defer_event *e, void *userdata); 80 | 81 | /** An abstract mainloop API vtable */ 82 | struct pa_mainloop_api { 83 | /** A pointer to some private, arbitrary data of the main loop implementation */ 84 | void *userdata; 85 | 86 | /** Create a new IO event source object */ 87 | pa_io_event* (*io_new)(pa_mainloop_api*a, int fd, pa_io_event_flags_t events, pa_io_event_cb_t cb, void *userdata); 88 | /** Enable or disable IO events on this object */ 89 | void (*io_enable)(pa_io_event* e, pa_io_event_flags_t events); 90 | /** Free a IO event source object */ 91 | void (*io_free)(pa_io_event* e); 92 | /** Set a function that is called when the IO event source is destroyed. Use this to free the userdata argument if required */ 93 | void (*io_set_destroy)(pa_io_event *e, pa_io_event_destroy_cb_t cb); 94 | 95 | /** Create a new timer event source object for the specified Unix time */ 96 | pa_time_event* (*time_new)(pa_mainloop_api*a, const struct timeval *tv, pa_time_event_cb_t cb, void *userdata); 97 | /** Restart a running or expired timer event source with a new Unix time */ 98 | void (*time_restart)(pa_time_event* e, const struct timeval *tv); 99 | /** Free a deferred timer event source object */ 100 | void (*time_free)(pa_time_event* e); 101 | /** Set a function that is called when the timer event source is destroyed. Use this to free the userdata argument if required */ 102 | void (*time_set_destroy)(pa_time_event *e, pa_time_event_destroy_cb_t cb); 103 | 104 | /** Create a new deferred event source object */ 105 | pa_defer_event* (*defer_new)(pa_mainloop_api*a, pa_defer_event_cb_t cb, void *userdata); 106 | /** Enable or disable a deferred event source temporarily */ 107 | void (*defer_enable)(pa_defer_event* e, int b); 108 | /** Free a deferred event source object */ 109 | void (*defer_free)(pa_defer_event* e); 110 | /** Set a function that is called when the deferred event source is destroyed. Use this to free the userdata argument if required */ 111 | void (*defer_set_destroy)(pa_defer_event *e, pa_defer_event_destroy_cb_t cb); 112 | 113 | /** Exit the main loop and return the specified retval*/ 114 | void (*quit)(pa_mainloop_api*a, int retval); 115 | }; 116 | 117 | /** Run the specified callback function once from the main loop using an anonymous defer event. Note that this performs 118 | * multiple mainloop operations non-atomically. If, for example, you are using a \ref pa_threaded_mainloop, you will need to 119 | * take the mainloop lock before this call. */ 120 | void pa_mainloop_api_once(pa_mainloop_api*m, void (*callback)(pa_mainloop_api*m, void *userdata), void *userdata); 121 | 122 | PA_C_DECL_END 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/mainloop-signal.h: -------------------------------------------------------------------------------- 1 | #ifndef foomainloopsignalhfoo 2 | #define foomainloopsignalhfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2008 Lennart Poettering 8 | Copyright 2006 Pierre Ossman for Cendio AB 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as published 12 | by the Free Software Foundation; either version 2.1 of the License, 13 | or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public License 21 | along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | #include 28 | 29 | PA_C_DECL_BEGIN 30 | 31 | /** \file 32 | * UNIX signal support for main loops. In contrast to other 33 | * main loop event sources such as timer and IO events, UNIX signal 34 | * support requires modification of the global process 35 | * environment. Due to this the generic main loop abstraction layer as 36 | * defined in \ref mainloop-api.h doesn't have direct support for UNIX 37 | * signals. However, you may hook signal support into an abstract main loop via the routines defined herein. 38 | */ 39 | 40 | /** An opaque UNIX signal event source object */ 41 | typedef struct pa_signal_event pa_signal_event; 42 | 43 | /** Callback prototype for signal events */ 44 | typedef void (*pa_signal_cb_t) (pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata); 45 | 46 | /** Destroy callback prototype for signal events */ 47 | typedef void (*pa_signal_destroy_cb_t) (pa_mainloop_api *api, pa_signal_event*e, void *userdata); 48 | 49 | /** Initialize the UNIX signal subsystem and bind it to the specified main loop */ 50 | int pa_signal_init(pa_mainloop_api *api); 51 | 52 | /** Cleanup the signal subsystem */ 53 | void pa_signal_done(void); 54 | 55 | /** Create a new UNIX signal event source object */ 56 | pa_signal_event* pa_signal_new(int sig, pa_signal_cb_t callback, void *userdata); 57 | 58 | /** Free a UNIX signal event source object */ 59 | void pa_signal_free(pa_signal_event *e); 60 | 61 | /** Set a function that is called when the signal event source is destroyed. Use this to free the userdata argument if required */ 62 | void pa_signal_set_destroy(pa_signal_event *e, pa_signal_destroy_cb_t callback); 63 | 64 | PA_C_DECL_END 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/mainloop.h: -------------------------------------------------------------------------------- 1 | #ifndef foomainloophfoo 2 | #define foomainloophfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | Copyright 2006 Pierre Ossman for Cendio AB 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as published 12 | by the Free Software Foundation; either version 2.1 of the License, 13 | or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public License 21 | along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | #include 28 | 29 | PA_C_DECL_BEGIN 30 | 31 | struct pollfd; 32 | 33 | /** \page mainloop Main Loop 34 | * 35 | * \section overv_sec Overview 36 | * 37 | * The built-in main loop implementation is based on the poll() system call. 38 | * It supports the functions defined in the main loop abstraction and very 39 | * little else. 40 | * 41 | * The main loop is created using pa_mainloop_new() and destroyed using 42 | * pa_mainloop_free(). To get access to the main loop abstraction, 43 | * pa_mainloop_get_api() is used. 44 | * 45 | * \section iter_sec Iteration 46 | * 47 | * The main loop is designed around the concept of iterations. Each iteration 48 | * consists of three steps that repeat during the application's entire 49 | * lifetime: 50 | * 51 | * -# Prepare - Build a list of file descriptors 52 | * that need to be monitored and calculate the next timeout. 53 | * -# Poll - Execute the actual poll() system call. 54 | * -# Dispatch - Dispatch any events that have fired. 55 | * 56 | * When using the main loop, the application can either execute each 57 | * iteration, one at a time, using pa_mainloop_iterate(), or let the library 58 | * iterate automatically using pa_mainloop_run(). 59 | * 60 | * \section thread_sec Threads 61 | * 62 | * The main loop functions are designed to be thread safe, but the objects 63 | * are not. What this means is that multiple main loops can be used, but only 64 | * one object per thread. 65 | * 66 | */ 67 | 68 | /** \file 69 | * 70 | * A minimal main loop implementation based on the C library's poll() 71 | * function. Using the routines defined herein you may create a simple 72 | * main loop supporting the generic main loop abstraction layer as 73 | * defined in \ref mainloop-api.h. This implementation is thread safe 74 | * as long as you access the main loop object from a single thread only. 75 | * 76 | * See also \subpage mainloop 77 | */ 78 | 79 | /** An opaque main loop object */ 80 | typedef struct pa_mainloop pa_mainloop; 81 | 82 | /** Allocate a new main loop object */ 83 | pa_mainloop *pa_mainloop_new(void); 84 | 85 | /** Free a main loop object */ 86 | void pa_mainloop_free(pa_mainloop* m); 87 | 88 | /** Prepare for a single iteration of the main loop. Returns a negative value 89 | on error or exit request. timeout specifies a maximum timeout for the subsequent 90 | poll, or -1 for blocking behaviour. .*/ 91 | int pa_mainloop_prepare(pa_mainloop *m, int timeout); 92 | 93 | /** Execute the previously prepared poll. Returns a negative value on error.*/ 94 | int pa_mainloop_poll(pa_mainloop *m); 95 | 96 | /** Dispatch timeout, io and deferred events from the previously executed poll. Returns 97 | a negative value on error. On success returns the number of source dispatched. */ 98 | int pa_mainloop_dispatch(pa_mainloop *m); 99 | 100 | /** Return the return value as specified with the main loop's quit() routine. */ 101 | int pa_mainloop_get_retval(pa_mainloop *m); 102 | 103 | /** Run a single iteration of the main loop. This is a convenience function 104 | for pa_mainloop_prepare(), pa_mainloop_poll() and pa_mainloop_dispatch(). 105 | Returns a negative value on error or exit request. If block is nonzero, 106 | block for events if none are queued. Optionally return the return value as 107 | specified with the main loop's quit() routine in the integer variable retval points 108 | to. On success returns the number of sources dispatched in this iteration. */ 109 | int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval); 110 | 111 | /** Run unlimited iterations of the main loop object until the main loop's quit() routine is called. */ 112 | int pa_mainloop_run(pa_mainloop *m, int *retval); 113 | 114 | /** Return the abstract main loop abstraction layer vtable for this 115 | main loop. No need to free the API as it is owned by the loop 116 | and is destroyed when the loop is freed. */ 117 | pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m); 118 | 119 | /** Shutdown the main loop */ 120 | void pa_mainloop_quit(pa_mainloop *m, int r); 121 | 122 | /** Interrupt a running poll (for threaded systems) */ 123 | void pa_mainloop_wakeup(pa_mainloop *m); 124 | 125 | /** Generic prototype of a poll() like function */ 126 | typedef int (*pa_poll_func)(struct pollfd *ufds, unsigned long nfds, int timeout, void*userdata); 127 | 128 | /** Change the poll() implementation */ 129 | void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata); 130 | 131 | PA_C_DECL_END 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/operation.h: -------------------------------------------------------------------------------- 1 | #ifndef foooperationhfoo 2 | #define foooperationhfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | 9 | PulseAudio is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published 11 | by the Free Software Foundation; either version 2.1 of the License, 12 | or (at your option) any later version. 13 | 14 | PulseAudio is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with PulseAudio; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 22 | USA. 23 | ***/ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | /** \file 30 | * Asynchronous operations */ 31 | 32 | PA_C_DECL_BEGIN 33 | 34 | /** An asynchronous operation object */ 35 | typedef struct pa_operation pa_operation; 36 | 37 | /** A callback for operation state changes */ 38 | typedef void (*pa_operation_notify_cb_t) (pa_operation *o, void *userdata); 39 | 40 | /** Increase the reference count by one */ 41 | pa_operation *pa_operation_ref(pa_operation *o); 42 | 43 | /** Decrease the reference count by one */ 44 | void pa_operation_unref(pa_operation *o); 45 | 46 | /** Cancel the operation. Beware! This will not necessarily cancel the 47 | * execution of the operation on the server side. However it will make 48 | * sure that the callback associated with this operation will not be 49 | * called anymore, effectively disabling the operation from the client 50 | * side's view. */ 51 | void pa_operation_cancel(pa_operation *o); 52 | 53 | /** Return the current status of the operation */ 54 | pa_operation_state_t pa_operation_get_state(pa_operation *o); 55 | 56 | /** Set the callback function that is called when the operation state 57 | * changes. Usually this is not necessary, since the functions that 58 | * create pa_operation objects already take a callback that is called 59 | * when the operation finishes. Registering a state change callback is 60 | * mainly useful, if you want to get called back also if the operation 61 | * gets cancelled. \since 4.0 */ 62 | void pa_operation_set_state_callback(pa_operation *o, pa_operation_notify_cb_t cb, void *userdata); 63 | 64 | PA_C_DECL_END 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/pulseaudio.h: -------------------------------------------------------------------------------- 1 | #ifndef foopulseaudiohfoo 2 | #define foopulseaudiohfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | Copyright 2006 Pierre Ossman for Cendio AB 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as 12 | published by the Free Software Foundation; either version 2.1 of the 13 | License, or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | 50 | /** \file 51 | * Include all libpulse header files at once. The following files are 52 | * included: \ref mainloop-api.h, \ref sample.h, \ref def.h, \ref 53 | * context.h, \ref stream.h, \ref introspect.h, \ref subscribe.h, \ref 54 | * scache.h, \ref version.h, \ref error.h, \ref channelmap.h, \ref 55 | * operation.h,\ref volume.h, \ref xmalloc.h, \ref utf8.h, \ref 56 | * thread-mainloop.h, \ref mainloop.h, \ref util.h, \ref proplist.h, 57 | * \ref timeval.h, \ref rtclock.h and \ref mainloop-signal.h at 58 | * once */ 59 | 60 | /** \mainpage 61 | * 62 | * \section intro_sec Introduction 63 | * 64 | * This document describes the client API for the PulseAudio sound 65 | * server. The API comes in two flavours to accommodate different styles 66 | * of applications and different needs in complexity: 67 | * 68 | * \li The complete but somewhat complicated to use asynchronous API 69 | * \li The simplified, easy to use, but limited synchronous API 70 | * 71 | * All strings in PulseAudio are in the UTF-8 encoding, regardless of current 72 | * locale. Some functions will filter invalid sequences from the string, some 73 | * will simply fail. To ensure reliable behaviour, make sure everything you 74 | * pass to the API is already in UTF-8. 75 | 76 | * \section simple_sec Simple API 77 | * 78 | * Use this if you develop your program in synchronous style and just 79 | * need a way to play or record data on the sound server. See 80 | * \subpage simple for more details. 81 | * 82 | * \section async_sec Asynchronous API 83 | * 84 | * Use this if you develop your programs in asynchronous, event loop 85 | * based style or if you want to use the advanced features of the 86 | * PulseAudio API. A guide can be found in \subpage async. 87 | * 88 | * By using the built-in threaded main loop, it is possible to achieve a 89 | * pseudo-synchronous API, which can be useful in synchronous applications 90 | * where the simple API is insufficient. See the \ref async page for 91 | * details. 92 | * 93 | * \section thread_sec Threads 94 | * 95 | * The PulseAudio client libraries are not designed to be directly 96 | * thread-safe. They are however designed to be reentrant and 97 | * threads-aware. 98 | * 99 | * To use the libraries in a threaded environment, you must assure that 100 | * all objects are only used in one thread at a time. Normally, this means 101 | * that all objects belonging to a single context must be accessed from the 102 | * same thread. 103 | * 104 | * The included main loop implementation is also not thread safe. Take care 105 | * to make sure event objects are not manipulated when any other code is 106 | * using the main loop. 107 | * 108 | * \section error_sec Error Handling 109 | * 110 | * Every function should explicitly document how errors are reported to 111 | * the caller. Unfortunately, currently a lot of that documentation is 112 | * missing. Here is an overview of the general conventions used. 113 | * 114 | * The PulseAudio API indicates error conditions by returning a negative 115 | * integer value or a NULL pointer. On success, zero or a positive integer 116 | * value or a valid pointer is returned. 117 | * 118 | * Functions of the \ref simple generally return -1 or NULL on failure and 119 | * can optionally store an error code (see ::pa_error_code) using a pointer 120 | * argument. 121 | * 122 | * Functions of the \ref async return an negative error code or NULL on 123 | * failure (see ::pa_error_code). In the later case, pa_context_errno() 124 | * can be used to obtain the error code of the last failed operation. 125 | * 126 | * An error code can be turned into a human readable message using 127 | * pa_strerror(). 128 | * 129 | * \section pkgconfig pkg-config 130 | * 131 | * The PulseAudio libraries provide pkg-config snippets for the different 132 | * modules: 133 | * 134 | * \li libpulse - The asynchronous API and the internal main loop implementation. 135 | * \li libpulse-mainloop-glib - GLIB 2.x main loop bindings. 136 | * \li libpulse-simple - The simple PulseAudio API. 137 | */ 138 | 139 | #endif 140 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/rtclock.h: -------------------------------------------------------------------------------- 1 | #ifndef foortclockfoo 2 | #define foortclockfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2009 Lennart Poettering 8 | 9 | PulseAudio is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as 11 | published by the Free Software Foundation; either version 2.1 of the 12 | License, or (at your option) any later version. 13 | 14 | PulseAudio is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public 20 | License along with PulseAudio; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 22 | USA. 23 | ***/ 24 | 25 | #include 26 | #include 27 | 28 | /** \file 29 | * Monotonic clock utilities. */ 30 | 31 | PA_C_DECL_BEGIN 32 | 33 | /** Return the current monotonic system time in usec, if such a clock 34 | * is available. If it is not available this will return the 35 | * wallclock time instead. \since 0.9.16 */ 36 | pa_usec_t pa_rtclock_now(void); 37 | 38 | PA_C_DECL_END 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/scache.h: -------------------------------------------------------------------------------- 1 | #ifndef fooscachehfoo 2 | #define fooscachehfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | Copyright 2006 Pierre Ossman for Cendio AB 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as published 12 | by the Free Software Foundation; either version 2.1 of the License, 13 | or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public License 21 | along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | /** \page scache Sample Cache 34 | * 35 | * \section overv_sec Overview 36 | * 37 | * The sample cache provides a simple way of overcoming high network latencies 38 | * and reducing bandwidth. Instead of streaming a sound precisely when it 39 | * should be played, it is stored on the server and only the command to start 40 | * playing it needs to be sent. 41 | * 42 | * \section create_sec Creation 43 | * 44 | * To create a sample, the normal stream API is used (see \ref streams). The 45 | * function pa_stream_connect_upload() will make sure the stream is stored as 46 | * a sample on the server. 47 | * 48 | * To complete the upload, pa_stream_finish_upload() is called and the sample 49 | * will receive the same name as the stream. If the upload should be aborted, 50 | * simply call pa_stream_disconnect(). 51 | * 52 | * \section play_sec Playing samples 53 | * 54 | * To play back a sample, simply call pa_context_play_sample(): 55 | * 56 | * \code 57 | * pa_operation *o; 58 | * 59 | * o = pa_context_play_sample(my_context, 60 | * "sample2", // Name of my sample 61 | * NULL, // Use default sink 62 | * PA_VOLUME_NORM, // Full volume 63 | * NULL, // Don't need a callback 64 | * NULL 65 | * ); 66 | * if (o) 67 | * pa_operation_unref(o); 68 | * \endcode 69 | * 70 | * \section rem_sec Removing samples 71 | * 72 | * When a sample is no longer needed, it should be removed on the server to 73 | * save resources. The sample is deleted using pa_context_remove_sample(). 74 | */ 75 | 76 | /** \file 77 | * All sample cache related routines 78 | * 79 | * See also \subpage scache 80 | */ 81 | 82 | PA_C_DECL_BEGIN 83 | 84 | /** Callback prototype for pa_context_play_sample_with_proplist(). The 85 | * idx value is the index of the sink input object, or 86 | * PA_INVALID_INDEX on failure. \since 0.9.11 */ 87 | typedef void (*pa_context_play_sample_cb_t)(pa_context *c, uint32_t idx, void *userdata); 88 | 89 | /** Make this stream a sample upload stream */ 90 | int pa_stream_connect_upload(pa_stream *s, size_t length); 91 | 92 | /** Finish the sample upload, the stream name will become the sample 93 | * name. You cancel a sample upload by issuing 94 | * pa_stream_disconnect() */ 95 | int pa_stream_finish_upload(pa_stream *s); 96 | 97 | /** Remove a sample from the sample cache. Returns an operation object which may be used to cancel the operation while it is running */ 98 | pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata); 99 | 100 | /** Play a sample from the sample cache to the specified device. If 101 | * the latter is NULL use the default sink. Returns an operation 102 | * object */ 103 | pa_operation* pa_context_play_sample( 104 | pa_context *c /**< Context */, 105 | const char *name /**< Name of the sample to play */, 106 | const char *dev /**< Sink to play this sample on */, 107 | pa_volume_t volume /**< Volume to play this sample with. Starting with 0.9.15 you may pass here PA_VOLUME_INVALID which will leave the decision about the volume to the server side which is a good idea. */ , 108 | pa_context_success_cb_t cb /**< Call this function after successfully starting playback, or NULL */, 109 | void *userdata /**< Userdata to pass to the callback */); 110 | 111 | /** Play a sample from the sample cache to the specified device, 112 | * allowing specification of a property list for the playback 113 | * stream. If the latter is NULL use the default sink. Returns an 114 | * operation object. \since 0.9.11 */ 115 | pa_operation* pa_context_play_sample_with_proplist( 116 | pa_context *c /**< Context */, 117 | const char *name /**< Name of the sample to play */, 118 | const char *dev /**< Sink to play this sample on */, 119 | pa_volume_t volume /**< Volume to play this sample with. Starting with 0.9.15 you may pass here PA_VOLUME_INVALID which will leave the decision about the volume to the server side which is a good idea. */ , 120 | pa_proplist *proplist /**< Property list for this sound. The property list of the cached entry will be merged into this property list */, 121 | pa_context_play_sample_cb_t cb /**< Call this function after successfully starting playback, or NULL */, 122 | void *userdata /**< Userdata to pass to the callback */); 123 | 124 | PA_C_DECL_END 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/simple.h: -------------------------------------------------------------------------------- 1 | #ifndef foosimplehfoo 2 | #define foosimplehfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | Copyright 2006 Pierre Ossman for Cendio AB 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as published 12 | by the Free Software Foundation; either version 2.1 of the License, 13 | or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public License 21 | along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | /** \page simple Simple API 35 | * 36 | * \section overv_sec Overview 37 | * 38 | * The simple API is designed for applications with very basic sound 39 | * playback or capture needs. It can only support a single stream per 40 | * connection and has no support for handling of complex features like 41 | * events, channel mappings and volume control. It is, however, very simple 42 | * to use and quite sufficient for many programs. 43 | * 44 | * \section conn_sec Connecting 45 | * 46 | * The first step before using the sound system is to connect to the 47 | * server. This is normally done this way: 48 | * 49 | * \code 50 | * pa_simple *s; 51 | * pa_sample_spec ss; 52 | * 53 | * ss.format = PA_SAMPLE_S16NE; 54 | * ss.channels = 2; 55 | * ss.rate = 44100; 56 | * 57 | * s = pa_simple_new(NULL, // Use the default server. 58 | * "Fooapp", // Our application's name. 59 | * PA_STREAM_PLAYBACK, 60 | * NULL, // Use the default device. 61 | * "Music", // Description of our stream. 62 | * &ss, // Our sample format. 63 | * NULL, // Use default channel map 64 | * NULL, // Use default buffering attributes. 65 | * NULL, // Ignore error code. 66 | * ); 67 | * \endcode 68 | * 69 | * At this point a connected object is returned, or NULL if there was a 70 | * problem connecting. 71 | * 72 | * \section transfer_sec Transferring data 73 | * 74 | * Once the connection is established to the server, data can start flowing. 75 | * Using the connection is very similar to the normal read() and write() 76 | * system calls. The main difference is that they're called pa_simple_read() 77 | * and pa_simple_write(). Note that these operations always block. 78 | * 79 | * \section ctrl_sec Buffer control 80 | * 81 | * \li pa_simple_get_latency() - Will return the total latency of 82 | * the playback or record pipeline, respectively. 83 | * \li pa_simple_flush() - Will throw away all data currently in buffers. 84 | * 85 | * If a playback stream is used then the following operation is available: 86 | * 87 | * \li pa_simple_drain() - Will wait for all sent data to finish playing. 88 | * 89 | * \section cleanup_sec Cleanup 90 | * 91 | * Once playback or capture is complete, the connection should be closed 92 | * and resources freed. This is done through: 93 | * 94 | * \code 95 | * pa_simple_free(s); 96 | * \endcode 97 | */ 98 | 99 | /** \file 100 | * A simple but limited synchronous playback and recording 101 | * API. This is a synchronous, simplified wrapper around the standard 102 | * asynchronous API. 103 | * 104 | * See also \subpage simple 105 | */ 106 | 107 | /** \example pacat-simple.c 108 | * A simple playback tool using the simple API */ 109 | 110 | /** \example parec-simple.c 111 | * A simple recording tool using the simple API */ 112 | 113 | PA_C_DECL_BEGIN 114 | 115 | /** \struct pa_simple 116 | * An opaque simple connection object */ 117 | typedef struct pa_simple pa_simple; 118 | 119 | /** Create a new connection to the server. */ 120 | pa_simple* pa_simple_new( 121 | const char *server, /**< Server name, or NULL for default */ 122 | const char *name, /**< A descriptive name for this client (application name, ...) */ 123 | pa_stream_direction_t dir, /**< Open this stream for recording or playback? */ 124 | const char *dev, /**< Sink (resp. source) name, or NULL for default */ 125 | const char *stream_name, /**< A descriptive name for this stream (application name, song title, ...) */ 126 | const pa_sample_spec *ss, /**< The sample type to use */ 127 | const pa_channel_map *map, /**< The channel map to use, or NULL for default */ 128 | const pa_buffer_attr *attr, /**< Buffering attributes, or NULL for default */ 129 | int *error /**< A pointer where the error code is stored when the routine returns NULL. It is OK to pass NULL here. */ 130 | ); 131 | 132 | /** Close and free the connection to the server. The connection object becomes invalid when this is called. */ 133 | void pa_simple_free(pa_simple *s); 134 | 135 | /** Write some data to the server. */ 136 | int pa_simple_write(pa_simple *s, const void *data, size_t bytes, int *error); 137 | 138 | /** Wait until all data already written is played by the daemon. */ 139 | int pa_simple_drain(pa_simple *s, int *error); 140 | 141 | /** Read some data from the server. This function blocks until \a bytes amount 142 | * of data has been received from the server, or until an error occurs. 143 | * Returns a negative value on failure. */ 144 | int pa_simple_read( 145 | pa_simple *s, /**< The connection object. */ 146 | void *data, /**< A pointer to a buffer. */ 147 | size_t bytes, /**< The number of bytes to read. */ 148 | int *error 149 | /**< A pointer where the error code is stored when the function returns 150 | * a negative value. It is OK to pass NULL here. */ 151 | ); 152 | 153 | /** Return the playback or record latency. */ 154 | pa_usec_t pa_simple_get_latency(pa_simple *s, int *error); 155 | 156 | /** Flush the playback or record buffer. This discards any audio in the buffer. */ 157 | int pa_simple_flush(pa_simple *s, int *error); 158 | 159 | PA_C_DECL_END 160 | 161 | #endif 162 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/subscribe.h: -------------------------------------------------------------------------------- 1 | #ifndef foosubscribehfoo 2 | #define foosubscribehfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | Copyright 2006 Pierre Ossman for Cendio AB 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as published 12 | by the Free Software Foundation; either version 2.1 of the License, 13 | or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public License 21 | along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | /** \page subscribe Event Subscription 34 | * 35 | * \section overv_sec Overview 36 | * 37 | * The application can be notified, asynchronously, whenever the internal 38 | * layout of the server changes. Possible notifications are described in the 39 | * \ref pa_subscription_event_type and \ref pa_subscription_mask 40 | * enumerations. 41 | * 42 | * The application sets the notification mask using pa_context_subscribe() 43 | * and the function that will be called whenever a notification occurs using 44 | * pa_context_set_subscribe_callback(). 45 | * 46 | * The callback will be called with a \ref pa_subscription_event_type_t 47 | * representing the event that caused the callback. Clients can examine what 48 | * object changed using \ref PA_SUBSCRIPTION_EVENT_FACILITY_MASK. The actual 49 | * event type can then be extracted with \ref PA_SUBSCRIPTION_EVENT_TYPE_MASK. 50 | * Please note that the masked values are integers, not flags (so you will 51 | * check the object/event type using a comparison not a binary AND). For 52 | * example, the callback might look something like: 53 | * 54 | @verbatim 55 | void my_subscription_callback(pa_context *c, pa_subscription_event_type_t t, 56 | uint32_t idx, void *userdata) { 57 | if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE) { 58 | if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { 59 | ... a source was added, let's do stuff! ... 60 | } 61 | } 62 | } 63 | @endverbatim 64 | */ 65 | 66 | /** \file 67 | * Daemon introspection event subscription subsystem. 68 | * 69 | * See also \subpage subscribe 70 | */ 71 | 72 | PA_C_DECL_BEGIN 73 | 74 | /** Subscription event callback prototype */ 75 | typedef void (*pa_context_subscribe_cb_t)(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata); 76 | 77 | /** Enable event notification */ 78 | pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata); 79 | 80 | /** Set the context specific call back function that is called whenever the state of the daemon changes */ 81 | void pa_context_set_subscribe_callback(pa_context *c, pa_context_subscribe_cb_t cb, void *userdata); 82 | 83 | PA_C_DECL_END 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/timeval.h: -------------------------------------------------------------------------------- 1 | #ifndef footimevalhfoo 2 | #define footimevalhfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | Copyright 2006 Pierre Ossman for Cendio AB 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as 12 | published by the Free Software Foundation; either version 2.1 of the 13 | License, or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | /** \file 32 | * Utility functions for handling timeval calculations */ 33 | 34 | PA_C_DECL_BEGIN 35 | 36 | /** The number of milliseconds in a second */ 37 | #define PA_MSEC_PER_SEC ((pa_usec_t) 1000ULL) 38 | 39 | /** The number of microseconds in a second */ 40 | #define PA_USEC_PER_SEC ((pa_usec_t) 1000000ULL) 41 | 42 | /** The number of nanoseconds in a second */ 43 | #define PA_NSEC_PER_SEC ((unsigned long long) 1000000000ULL) 44 | 45 | /** The number of microseconds in a millisecond */ 46 | #define PA_USEC_PER_MSEC ((pa_usec_t) 1000ULL) 47 | 48 | /** The number of nanoseconds in a millisecond */ 49 | #define PA_NSEC_PER_MSEC ((unsigned long long) 1000000ULL) 50 | 51 | /** The number of nanoseconds in a microsecond */ 52 | #define PA_NSEC_PER_USEC ((unsigned long long) 1000ULL) 53 | 54 | /** Invalid time in usec. \since 0.9.15 */ 55 | #define PA_USEC_INVALID ((pa_usec_t) -1) 56 | 57 | /** Biggest time in usec. \since 0.9.18 */ 58 | #define PA_USEC_MAX ((pa_usec_t) -2) 59 | 60 | struct timeval; 61 | 62 | /** Return the current wallclock timestamp, just like UNIX gettimeofday(). */ 63 | struct timeval *pa_gettimeofday(struct timeval *tv); 64 | 65 | /** Calculate the difference between the two specified timeval 66 | * structs. */ 67 | pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) PA_GCC_PURE; 68 | 69 | /** Compare the two timeval structs and return 0 when equal, negative when a < b, positive otherwise */ 70 | int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) PA_GCC_PURE; 71 | 72 | /** Return the time difference between now and the specified timestamp */ 73 | pa_usec_t pa_timeval_age(const struct timeval *tv); 74 | 75 | /** Add the specified time in microseconds to the specified timeval structure */ 76 | struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v); 77 | 78 | /** Subtract the specified time in microseconds to the specified timeval structure. \since 0.9.11 */ 79 | struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v); 80 | 81 | /** Store the specified usec value in the timeval struct. \since 0.9.7 */ 82 | struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v); 83 | 84 | /** Load the specified tv value and return it in usec. \since 0.9.7 */ 85 | pa_usec_t pa_timeval_load(const struct timeval *tv); 86 | 87 | PA_C_DECL_END 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/utf8.h: -------------------------------------------------------------------------------- 1 | #ifndef fooutf8hfoo 2 | #define fooutf8hfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2006 Lennart Poettering 8 | Copyright 2006 Pierre Ossman for Cendio AB 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as 12 | published by the Free Software Foundation; either version 2.1 of the 13 | License, or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | /** \file 31 | * UTF-8 validation functions 32 | */ 33 | 34 | PA_C_DECL_BEGIN 35 | 36 | /** Test if the specified strings qualifies as valid UTF8. Return the string if so, otherwise NULL */ 37 | char *pa_utf8_valid(const char *str) PA_GCC_PURE; 38 | 39 | /** Test if the specified strings qualifies as valid 7-bit ASCII. Return the string if so, otherwise NULL. \since 0.9.15 */ 40 | char *pa_ascii_valid(const char *str) PA_GCC_PURE; 41 | 42 | /** Filter all invalid UTF8 characters from the specified string, returning a new fully UTF8 valid string. Don't forget to free the returned string with pa_xfree() */ 43 | char *pa_utf8_filter(const char *str); 44 | 45 | /** Filter all invalid ASCII characters from the specified string, returning a new fully ASCII valid string. Don't forget to free the returned string with pa_xfree(). \since 0.9.15 */ 46 | char *pa_ascii_filter(const char *str); 47 | 48 | /** Convert a UTF-8 string to the current locale. Free the string using pa_xfree(). */ 49 | char* pa_utf8_to_locale (const char *str); 50 | 51 | /** Convert a string in the current locale to UTF-8. Free the string using pa_xfree(). */ 52 | char* pa_locale_to_utf8 (const char *str); 53 | 54 | PA_C_DECL_END 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/util.h: -------------------------------------------------------------------------------- 1 | #ifndef fooutilhfoo 2 | #define fooutilhfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | Copyright 2006 Pierre Ossman for Cendio AB 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as 12 | published by the Free Software Foundation; either version 2.1 of the 13 | License, or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | /** \file 32 | * Assorted utility functions */ 33 | 34 | PA_C_DECL_BEGIN 35 | 36 | /** Return the current username in the specified string buffer. */ 37 | char *pa_get_user_name(char *s, size_t l); 38 | 39 | /** Return the current hostname in the specified buffer. */ 40 | char *pa_get_host_name(char *s, size_t l); 41 | 42 | /** Return the fully qualified domain name in s */ 43 | char *pa_get_fqdn(char *s, size_t l); 44 | 45 | /** Return the home directory of the current user */ 46 | char *pa_get_home_dir(char *s, size_t l); 47 | 48 | /** Return the binary file name of the current process. This is not 49 | * supported on all architectures, in which case NULL is returned. */ 50 | char *pa_get_binary_name(char *s, size_t l); 51 | 52 | /** Return a pointer to the filename inside a path (which is the last 53 | * component). If passed NULL will return NULL. */ 54 | char *pa_path_get_filename(const char *p); 55 | 56 | /** Wait t milliseconds */ 57 | int pa_msleep(unsigned long t); 58 | 59 | PA_C_DECL_END 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/version.h: -------------------------------------------------------------------------------- 1 | #ifndef fooversionhfoo /*-*-C-*-*/ 2 | #define fooversionhfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | Copyright 2006 Pierre Ossman for Cendio AB 9 | 10 | PulseAudio is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU Lesser General Public License as published 12 | by the Free Software Foundation; either version 2 of the License, 13 | or (at your option) any later version. 14 | 15 | PulseAudio is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public License 21 | along with PulseAudio; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 | USA. 24 | ***/ 25 | 26 | /* WARNING: Make sure to edit the real source file version.h.in! */ 27 | 28 | #include 29 | 30 | /** \file 31 | * Define header version */ 32 | 33 | PA_C_DECL_BEGIN 34 | 35 | /** Return the version of the header files. Keep in mind that this is 36 | a macro and not a function, so it is impossible to get the pointer of 37 | it. */ 38 | #define pa_get_headers_version() ("5.0.0") 39 | 40 | /** Return the version of the library the current application is 41 | * linked to. */ 42 | const char* pa_get_library_version(void); 43 | 44 | /** The current API version. Version 6 relates to Polypaudio 45 | * 0.6. Prior versions (i.e. Polypaudio 0.5.1 and older) have 46 | * PA_API_VERSION undefined. Please note that this is only ever 47 | * increased on incompatible API changes! */ 48 | #define PA_API_VERSION 12 49 | 50 | /** The current protocol version. Version 8 relates to Polypaudio 51 | * 0.8/PulseAudio 0.9. */ 52 | #define PA_PROTOCOL_VERSION 29 53 | 54 | /** The major version of PA. \since 0.9.15 */ 55 | #define PA_MAJOR 5 56 | 57 | /** The minor version of PA. \since 0.9.15 */ 58 | #define PA_MINOR 0 59 | 60 | /** The micro version of PA (will always be 0 from v1.0 onwards). \since 0.9.15 */ 61 | #define PA_MICRO 0 62 | 63 | /** Evaluates to TRUE if the PulseAudio library version is equal or 64 | * newer than the specified. \since 0.9.16 */ 65 | #define PA_CHECK_VERSION(major,minor,micro) \ 66 | ((PA_MAJOR > (major)) || \ 67 | (PA_MAJOR == (major) && PA_MINOR > (minor)) || \ 68 | (PA_MAJOR == (major) && PA_MINOR == (minor) && PA_MICRO >= (micro))) 69 | 70 | PA_C_DECL_END 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /3rdparty/pulseaudio-headers/pulse/xmalloc.h: -------------------------------------------------------------------------------- 1 | #ifndef foomemoryhfoo 2 | #define foomemoryhfoo 3 | 4 | /*** 5 | This file is part of PulseAudio. 6 | 7 | Copyright 2004-2006 Lennart Poettering 8 | 9 | PulseAudio is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published 11 | by the Free Software Foundation; either version 2.1 of the License, 12 | or (at your option) any later version. 13 | 14 | PulseAudio is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with PulseAudio; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 22 | USA. 23 | ***/ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | /** \file 35 | * Memory allocation functions. 36 | */ 37 | 38 | PA_C_DECL_BEGIN 39 | 40 | /** Allocate the specified number of bytes, just like malloc() does. However, in case of OOM, terminate */ 41 | void* pa_xmalloc(size_t l) PA_GCC_MALLOC PA_GCC_ALLOC_SIZE(1); 42 | 43 | /** Same as pa_xmalloc(), but initialize allocated memory to 0 */ 44 | void *pa_xmalloc0(size_t l) PA_GCC_MALLOC PA_GCC_ALLOC_SIZE(1); 45 | 46 | /** The combination of pa_xmalloc() and realloc() */ 47 | void *pa_xrealloc(void *ptr, size_t size) PA_GCC_ALLOC_SIZE(2); 48 | 49 | /** Free allocated memory */ 50 | void pa_xfree(void *p); 51 | 52 | /** Duplicate the specified string, allocating memory with pa_xmalloc() */ 53 | char *pa_xstrdup(const char *s) PA_GCC_MALLOC; 54 | 55 | /** Duplicate the specified string, but truncate after l characters */ 56 | char *pa_xstrndup(const char *s, size_t l) PA_GCC_MALLOC; 57 | 58 | /** Duplicate the specified memory block */ 59 | void* pa_xmemdup(const void *p, size_t l) PA_GCC_MALLOC PA_GCC_ALLOC_SIZE(2); 60 | 61 | /** Internal helper for pa_xnew() */ 62 | static void* _pa_xnew_internal(size_t n, size_t k) PA_GCC_MALLOC PA_GCC_ALLOC_SIZE2(1,2); 63 | 64 | static inline void* _pa_xnew_internal(size_t n, size_t k) { 65 | assert(n < INT_MAX/k); 66 | return pa_xmalloc(n*k); 67 | } 68 | 69 | /** Allocate n new structures of the specified type. */ 70 | #define pa_xnew(type, n) ((type*) _pa_xnew_internal((n), sizeof(type))) 71 | 72 | /** Internal helper for pa_xnew0() */ 73 | static void* _pa_xnew0_internal(size_t n, size_t k) PA_GCC_MALLOC PA_GCC_ALLOC_SIZE2(1,2); 74 | 75 | static inline void* _pa_xnew0_internal(size_t n, size_t k) { 76 | assert(n < INT_MAX/k); 77 | return pa_xmalloc0(n*k); 78 | } 79 | 80 | /** Same as pa_xnew() but set the memory to zero */ 81 | #define pa_xnew0(type, n) ((type*) _pa_xnew0_internal((n), sizeof(type))) 82 | 83 | /** Internal helper for pa_xnew0() */ 84 | static void* _pa_xnewdup_internal(const void *p, size_t n, size_t k) PA_GCC_MALLOC PA_GCC_ALLOC_SIZE2(2,3); 85 | 86 | static inline void* _pa_xnewdup_internal(const void *p, size_t n, size_t k) { 87 | assert(n < INT_MAX/k); 88 | return pa_xmemdup(p, n*k); 89 | } 90 | 91 | /** Same as pa_xnew() but duplicate the specified data */ 92 | #define pa_xnewdup(type, p, n) ((type*) _pa_xnewdup_internal((p), (n), sizeof(type))) 93 | 94 | /** Internal helper for pa_xrenew() */ 95 | static void* _pa_xrenew_internal(void *p, size_t n, size_t k) PA_GCC_MALLOC PA_GCC_ALLOC_SIZE2(2,3); 96 | 97 | static inline void* _pa_xrenew_internal(void *p, size_t n, size_t k) { 98 | assert(n < INT_MAX/k); 99 | return pa_xrealloc(p, n*k); 100 | } 101 | 102 | /** Reallocate n new structures of the specified type. */ 103 | #define pa_xrenew(type, p, n) ((type*) _pa_xrenew_internal(p, (n), sizeof(type))) 104 | 105 | PA_C_DECL_END 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8...4.0) 2 | project(apulse) 3 | 4 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -fPIC -fvisibility=hidden") 5 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration") 6 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") 7 | 8 | find_package(PkgConfig REQUIRED) 9 | 10 | pkg_check_modules(REQ glib-2.0 alsa REQUIRED) 11 | 12 | list(APPEND REQ_LIBRARIES m) 13 | 14 | set(WITH_TRACE 0 CACHE STRING "trace level: no tracing (0) / unimplemented only (1) / all (2)") 15 | set(LOG_TO_STDERR 0 CACHE STRING "send all log output to stderr") 16 | 17 | # Options. 18 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCONFIG_TRACE_LEVEL=${WITH_TRACE}") 19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCONFIG_LOG_TO_STDERR=${LOG_TO_STDERR}") 20 | 21 | include_directories(${REQ_INCLUDE_DIRS}) 22 | 23 | set(USE_BUNDLED_PULSEAUDIO_HEADERS 1 CACHE BOOL "Use bundled PulseAudio headers instead of system ones") 24 | if (${USE_BUNDLED_PULSEAUDIO_HEADERS}) 25 | include_directories(3rdparty/pulseaudio-headers) 26 | else() 27 | pkg_check_modules(PA libpulse>=5.0 REQUIRED) 28 | include_directories(${PA_INCLUDE_DIRECTORIES}) 29 | endif() 30 | 31 | link_directories(${REQ_LIBRARY_DIRS}) 32 | 33 | add_library(trace-helper STATIC 34 | src/trace.c 35 | ) 36 | 37 | add_library(pulse SHARED 38 | src/apulse-channel-map.c 39 | src/apulse-common.c 40 | src/apulse-context.c 41 | src/apulse-ext.c 42 | src/apulse-format-info.c 43 | src/apulse-mainloop.c 44 | src/apulse-misc.c 45 | src/apulse-operation.c 46 | src/apulse-proplist.c 47 | src/apulse-signal.c 48 | src/apulse-stream.c 49 | src/apulse-threaded-mainloop.c 50 | src/apulse-volume.c 51 | src/ringbuffer.c 52 | src/util.c 53 | ) 54 | 55 | add_library(pulse-simple SHARED 56 | src/apulse-simple.c 57 | ) 58 | 59 | add_library(pulse-mainloop-glib SHARED 60 | src/apulse-mainloop-glib.c 61 | ) 62 | 63 | set_target_properties(pulse PROPERTIES VERSION 0) 64 | set_target_properties(pulse-mainloop-glib PROPERTIES VERSION 0) 65 | set_target_properties(pulse-simple PROPERTIES VERSION 0) 66 | 67 | set(CMAKE_SHARED_LINKER_FLAGS 68 | "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-version-script=\"${CMAKE_SOURCE_DIR}/src/symbolmap\"") 69 | 70 | target_link_libraries(pulse trace-helper ${REQ_LIBRARIES}) 71 | target_link_libraries(pulse-mainloop-glib trace-helper pulse ${REQ_LIBRARIES}) 72 | target_link_libraries(pulse-simple trace-helper pulse ${REQ_LIBRARIES}) 73 | 74 | add_subdirectory(tests) 75 | 76 | set(APULSEPATH "${CMAKE_INSTALL_PREFIX}/lib/apulse" CACHE PATH "library installation directory") 77 | set(APULSE_SEARCH_PATHS "${APULSEPATH}" CACHE PATH "directory list for LD_LIBRARY_PATH") 78 | configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/apulse.template" 79 | "${CMAKE_CURRENT_BINARY_DIR}/apulse" @ONLY) 80 | 81 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/apulse" DESTINATION bin 82 | PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) 83 | install(TARGETS pulse-simple pulse pulse-mainloop-glib DESTINATION "${APULSEPATH}") 84 | install(FILES "${CMAKE_SOURCE_DIR}/man/apulse.1" DESTINATION share/man/man1) 85 | -------------------------------------------------------------------------------- /LICENSE.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | About 2 | ===== 3 | 4 | PulseAudio emulation for ALSA. 5 | 6 | The program provides an alternative partial implementation of the PulseAudio 7 | API. It consists of a loader script and a number of shared libraries with the 8 | same names as from original PulseAudio, so applications could dynamically load 9 | them and think they are talking to PulseAudio. Internally, no separate sound 10 | mixing daemon is used. Instead, apulse relies on ALSA's `dmix`, `dsnoop`, and 11 | `plug` plugins to handle multiple sound sources and capture streams running at 12 | the same time. `dmix` plugin muxes multiple playback streams; `dsnoop` plugin 13 | allow multiple applications to capture from a single microphone; and `plug` 14 | plugin transparently converts audio between various sample formats, sample rates 15 | and channel numbers. For more than a decade now, ALSA comes with these plugins 16 | enabled and configured by default. 17 | 18 | `apulse` wasn't designed to be a drop-in replacement of PulseAudio. It's 19 | pointless, since that will be just reimplementation of original PulseAudio, with 20 | the same client-daemon architecture, required by the complete feature 21 | set. Instead, only parts of the API that are crucial to specific applications 22 | are implemented. That's why there is a loader script, named `apulse`. It updates 23 | value of `LD_LIBRARY_PATH` environment variable to point also to the directory 24 | where apulse's libraries are installed, making them available to the 25 | application. 26 | 27 | Name comes from names of both ALSA and PulseAudio. As `aoss` was a compatibility 28 | layer between OSS programs and ALSA, `apulse` was designed to be compatibility 29 | layer between PulseAudio applications and ALSA. 30 | 31 | 32 | Install 33 | ======= 34 | 35 | You need ALSA libraries and GLib installed. On Debian-based distributions, they 36 | are in packages `libasound2-dev` and `libglib2.0-dev`. 37 | 38 | To build and install, run in source directory: 39 | 40 | ``` 41 | $ mkdir build && cd build 42 | $ cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release .. 43 | $ make 44 | # make install 45 | ``` 46 | 47 | That will create directory named `build`, and build there. It's possible to 48 | install just by running `make install` as `root`, as shown above. But you won't 49 | be able to uninstall installed files. That's why it's recommended to wrap files 50 | into a package. Use `checkinstall`, or some alternative. 51 | 52 | If you want 32-bit binaries on 64-bit machine (for example, for Skype), use: 53 | ``` 54 | $ mkdir build && cd build 55 | $ CFLAGS=-m32 cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release .. 56 | $ make 57 | # make install 58 | ``` 59 | 60 | Recent GLib versions use different `.pc` files for `i386` and `amd64`. To help 61 | `pkg-config` find 32-bit versions, use `PKG_CONFIG_PATH` variable. So, on 62 | Debian it will be something like: 63 | 64 | ``` 65 | $ PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig CFLAGS=-m32 cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release .. 66 | ``` 67 | 68 | There is a way to configure where apulse libraries will be installed, via 69 | `APULSEPATH` cmake variable. For example, if you want to install libraries 70 | into default path, `/usr/lib`, use 71 | ``` 72 | cmake -DAPULSEPATH=/usr/lib -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release .. 73 | ``` 74 | 75 | If libraries are installed to a regular library path, you don't need run applications 76 | through `apulse` wrapper. 77 | 78 | 79 | Usage 80 | ===== 81 | 82 | ``` 83 | $ apulse [program-parameters] 84 | ``` 85 | 86 | Environment variables `APULSE_CAPTURE_DEVICE` and `APULSE_PLAYBACK_DEVICE` can be used 87 | to configure capture and playback devices. Try `hw:0,0`, `plughw:0,0` and the like. 88 | Refer to the ALSA user guide for a full list of device names. 89 | 90 | System directory versus separate directory installations 91 | -------------------------------------------------------- 92 | 93 | By default, libraries from `apulse` are installed into a separate directory, in 94 | order to hide them from all applications. 95 | 96 | Most applications in the wild, that support both PulseAudio and ALSA, try to 97 | autodetect which sound system is used. First, applications try to start with 98 | PulseAudio. Original client libraries fail early if no PulseAudio daemon is 99 | running or can be started. Then they switch to ALSA. Decision is made once, at 100 | the beginning. It works fine with PulseAudio, but doesn't work with 101 | `apulse`. Latter has no daemons, it happily says that everything is fine, and 102 | it's capable of playing audio. Applications then try to call more functions, and 103 | eventually touch unimplemented parts, often with crashes. So, libraries are 104 | hidden, and become visible only when a program is called through `apulse` 105 | wrapper script. 106 | 107 | It's possible to install apulse libraries to `/usr/lib`. Wrapper script won't 108 | be required, but then all applications will try to use PulseAudio API, despite 109 | they can use ALSA. 110 | 111 | Per-app RPATH trick 112 | ------------------- 113 | 114 | There is the RPATH property of ELF executable format, which is used to specify 115 | paths to search for dynamic libraries. It's like LD_LIBRARY_PATH variable, but 116 | per-executable. Since all that `apulse` launcher script does is setting 117 | LD_LIBRARY_PATH value before launching an application, it's possible to bake 118 | paths to apulse libraries into target executable itself. And so to launch it 119 | as usual, without helper script. 120 | 121 | For example, for Firefox it would be: 122 | 123 | ``` 124 | # patchelf --set-rpath /usr/lib/apulse /usr/lib/firefox/libxul.so 125 | ``` 126 | 127 | For some reason, it doesn't work if RPATH is set for `/usr/lib/firefox/firefox` 128 | itself, so some experiments are required to make it work. 129 | 130 | Known issues 131 | ============ 132 | 133 | Not implemented functions, application crashes 134 | ---------------------------------------------- 135 | 136 | Large portion of PulseAudio API is not implemented. There are functions that do 137 | nothing and return some arbitraty values. Often, if application tries to call 138 | something not implemented, it crashes while trying to dereference a NULL 139 | pointer. By default, tracing level is set to `0`, which means no messages are 140 | printed to standard output. It's possible to increase that value to `1`, which 141 | shows unimplemented function calls, or to `2`, which shows all function calls. 142 | 143 | To change level, use `WITH_TRACE` parameter when calling `cmake`. Something like 144 | `cmake -DWITH_TRACE=1 ..` 145 | 146 | Building apulse with trace level 1 won't fix issues, but will at least help to 147 | identify if crashes are caused by not implemented functions. 148 | 149 | Generic errors in do_connect_pcm 150 | -------------------------------- 151 | 152 | Apulse acts as a generic ALSA client. It tries to open audio device, and 153 | sometimes fails. At its core, apulse does neither audio mixing nor 154 | resampling. Instead, it relies on `plug`, `dmix`, and `dsnoop` ALSA plugins, 155 | which are usually enabled by default. These plugins handle multiple audio 156 | sources, performing resampling and mixing transparently. For years now ALSA 157 | comes with those plugins enabled. Audio just works without configuring 158 | anything. But not everybody use default settings. 159 | 160 | On custom configurations apulse may fail to output and/or capture audio. There 161 | could be no sound at all, or just a single audio stream playing at a time. It's 162 | also possible that adapters with hardware mixers, which capable of playing 163 | multiple streams, may still be unable to handle multiple capture 164 | streams. Depending on hardware, you may still need either `dmix` or `dsnoop` 165 | plugins. Or both. 166 | 167 | In other words, for apulse to work, your setup should be capable of playing and 168 | capturing multiple streams simultaneously. 169 | 170 | Access errors in do_connect_pcm 171 | ------------------------------- 172 | 173 | If other applications output sound just fine, it's possible that application you 174 | are using restricts itself. 175 | 176 | For example, Firefox now have a sandbox, that blocks file access. It has 177 | predefined list of allowed paths, but ALSA devices are not included by 178 | default. Fortunately, it's possible to add those path by hand. Add "/dev/snd/" 179 | to "security.sandbox.content.write_path_whitelist" parameter in 180 | `about:config`. Note that trailing slash in "/dev/snd/" is required. 181 | 182 | 183 | Firefox 58 tabs crashing when trying to play audio 184 | -------------------------------------------------- 185 | 186 | Firefox 58 (Nightly) tightened its sandbox a bit more. Now `ioctl()` calls are 187 | forbidden too, but are used by ALSA libraries. That causes sandbox violation 188 | with subsequent process termination. Exception can be added by setting parameter 189 | `security.sandbox.content.syscall_whitelist` in `about:config`. That field 190 | accepts a comma separated list of system call numbers. Add there `16` for 191 | x86-64, or `54` for x86 or ARM. 192 | 193 | Firefox 60 tighened its content sandbox more, but at the same time moved audio 194 | accesses from content processes to the main process. From Firefox 60 onwards no 195 | changes to the sandbox settings are necessary. 196 | 197 | License 198 | ======= 199 | 200 | Source code is distributed under the terms of the MIT License. See LICENSE.MIT for full text. 201 | 202 | Third party code 203 | ================ 204 | 205 | `/3rdparty/pulseaudio-headers` contains part of PulseAudio project and is distributed 206 | under LGPLv2.1+ terms. See content of the files for details. 207 | -------------------------------------------------------------------------------- /man/apulse.1: -------------------------------------------------------------------------------- 1 | .TH APULSE 1 2017-10-23 "apulse" "apulse" 2 | .SH NAME 3 | .B apulse 4 | \- The PulseAudio emulator for \fBALSA\fR 5 | .SH SYNOPSIS 6 | .B apulse 7 | .RI 8 | .RI [program-parameters]... 9 | 10 | .SH DESCRIPTION 11 | 12 | The program provides an alternative partial implementation of the PulseAudio 13 | API. It consists of a loader script and a number of shared libraries with the 14 | same names as from original PulseAudio, so applications could dynamically load 15 | them and think they are talking to PulseAudio. Internally, no separate sound 16 | mixing daemon is used. Instead, \fBapulse\fR relies on \fBALSA\fR's \fBdmix\fR, 17 | \fBdsnoop\fR, and \fBplug\fR plugins to handle multiple sound sources and 18 | capture streams running at the same time. \fBdmix\fR plugin muxes multiple 19 | playback streams; \fBdsnoop\fR plugin allow multiple applications to capture 20 | from a single microphone; and \fBplug\fR plugin transparently converts audio 21 | between various sample formats, sample rates and channel numbers. For more than 22 | a decade now, \fBALSA\fR comes with these plugins enabled and configured by 23 | default. 24 | 25 | \fBapulse\fR wasn't designed to be a drop-in replacement of PulseAudio. It's 26 | pointless, since that will be just reimplementation of original PulseAudio, 27 | with the same client-daemon architecture, required by the complete feature set. 28 | Instead, only parts of the API that are crucial to specific applications are 29 | implemented. That's why there is a loader script, named \fBapulse\fR. It 30 | updates value of LD_LIBRARY_PATH environment variable to point also to the 31 | directory where \fBapulse\fR's libraries are installed, making them available 32 | to the application. 33 | 34 | Name comes from names of both \fBALSA\fR and PulseAudio. As \fBaoss\fR was a 35 | compatibility layer between OSS programs and \fBALSA\fR, \fBapulse\fR was 36 | designed to be compatibility layer between PulseAudio applications and 37 | \fBALSA\fR. 38 | 39 | .SH ENVIRONMENT 40 | 41 | The following environment variables can be used to configure the devices used 42 | by \fBapulse\fR. Try \fIhw:0,0\fR, \fIplughw:0,0\fR and the like. 43 | Refer to the ALSA user guide for a full list of device names. 44 | 45 | \fIAPULSE_CAPTURE_DEVICE\fR: Can be used to configure the capture device. 46 | 47 | \fIAPULSE_PLAYBACK_DEVICE\fR: Can be used to configure the playback device. 48 | 49 | .SH RETURN VALUE 50 | 51 | \fBapulse\fR is a simple shell wrapper script that calls \fBexec\fR on the 52 | program given in parameters. Except for cases when the wrapper itself fails to 53 | load, return value is the return value of that program. 54 | 55 | .SH EXAMPLE 56 | 57 | Run a newer Firefox browser with fake PulseAudio: 58 | 59 | .nf 60 | .sp 61 | apulse firefox 62 | .fi 63 | 64 | .SH AUTHORS 65 | 66 | \fBapulse\fR was written by Rinat Ibragimov in 2014-2017. 67 | -------------------------------------------------------------------------------- /src/apulse-common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "apulse.h" 26 | #include "trace.h" 27 | 28 | typedef enum pa_log_level { 29 | PA_LOG_ERROR = 0, 30 | PA_LOG_WARN = 1, 31 | PA_LOG_NOTICE = 2, 32 | PA_LOG_INFO = 3, 33 | PA_LOG_DEBUG = 4, 34 | PA_LOG_LEVEL_MAX 35 | } pa_log_level_t; 36 | 37 | APULSE_EXPORT 38 | void 39 | pa_log_level_meta(pa_log_level_t level, const char *file, int line, 40 | const char *func, const char *format, ...) 41 | { 42 | char buf[2048]; 43 | 44 | int written = 0; 45 | snprintf(buf, sizeof(buf), "pa_log: <%d> %s:%d %s %n", level, file, line, 46 | func, &written); 47 | 48 | va_list args; 49 | va_start(args, format); 50 | vsnprintf(buf + written, sizeof(buf) - written, format, args); 51 | va_end(args); 52 | 53 | trace_info("%s\n", buf); 54 | } 55 | 56 | APULSE_EXPORT 57 | void 58 | pa_disable_sigpipe(void) 59 | { 60 | trace_info_z("Z %s\n", __func__); 61 | } 62 | 63 | APULSE_EXPORT 64 | int 65 | pa_open_cloexec(const char *fn, int flags, mode_t mode) 66 | { 67 | int fd = open(fn, flags, mode); 68 | if (fd < 0) 69 | return fd; 70 | fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); 71 | return fd; 72 | } 73 | 74 | APULSE_EXPORT 75 | int 76 | pa_close(int fd) 77 | { 78 | close(fd); 79 | return 0; 80 | } 81 | 82 | APULSE_EXPORT 83 | char * 84 | pa_ascii_filter(const char *str) 85 | { 86 | trace_info_z("Z %s\n", __func__); 87 | return NULL; 88 | } 89 | 90 | APULSE_EXPORT 91 | char * 92 | pa_ascii_valid(const char *str) 93 | { 94 | trace_info_z("Z %s\n", __func__); 95 | return NULL; 96 | } 97 | 98 | APULSE_EXPORT 99 | char * 100 | pa_utf8_filter(const char *str) 101 | { 102 | trace_info_z("Z %s\n", __func__); 103 | return NULL; 104 | } 105 | 106 | APULSE_EXPORT 107 | char * 108 | pa_utf8_to_locale(const char *str) 109 | { 110 | trace_info_z("Z %s\n", __func__); 111 | return NULL; 112 | } 113 | 114 | APULSE_EXPORT 115 | char * 116 | pa_utf8_valid(const char *str) 117 | { 118 | trace_info_z("Z %s\n", __func__); 119 | return NULL; 120 | } 121 | 122 | APULSE_EXPORT 123 | char * 124 | pa_bytes_snprint(char *s, size_t l, unsigned v) 125 | { 126 | trace_info_z("Z %s\n", __func__); 127 | return NULL; 128 | } 129 | 130 | APULSE_EXPORT 131 | const char * 132 | pa_encoding_to_string(pa_encoding_t e) 133 | { 134 | trace_info_z("Z %s\n", __func__); 135 | return NULL; 136 | } 137 | 138 | APULSE_EXPORT 139 | pa_encoding_t 140 | pa_encoding_from_string(const char *encoding) 141 | { 142 | trace_info_z("Z %s\n", __func__); 143 | return 0; 144 | } 145 | 146 | APULSE_EXPORT 147 | char * 148 | pa_get_fqdn(char *s, size_t l) 149 | { 150 | trace_info_z("Z %s\n", __func__); 151 | return NULL; 152 | } 153 | 154 | APULSE_EXPORT 155 | char * 156 | pa_get_home_dir(char *s, size_t l) 157 | { 158 | trace_info_z("Z %s\n", __func__); 159 | return NULL; 160 | } 161 | 162 | APULSE_EXPORT 163 | int 164 | pa_msleep(unsigned long t) 165 | { 166 | trace_info_z("Z %s\n", __func__); 167 | return 0; 168 | } 169 | 170 | APULSE_EXPORT 171 | pa_usec_t 172 | pa_timeval_diff(const struct timeval *a, const struct timeval *b) 173 | { 174 | trace_info_z("Z %s\n", __func__); 175 | return 0; 176 | } 177 | 178 | APULSE_EXPORT 179 | int 180 | pa_timeval_cmp(const struct timeval *a, const struct timeval *b) 181 | { 182 | trace_info_z("Z %s\n", __func__); 183 | return 0; 184 | } 185 | 186 | APULSE_EXPORT 187 | pa_usec_t 188 | pa_timeval_age(const struct timeval *tv) 189 | { 190 | trace_info_z("Z %s\n", __func__); 191 | return 0; 192 | } 193 | 194 | APULSE_EXPORT 195 | struct timeval * 196 | pa_timeval_add(struct timeval *tv, pa_usec_t v) 197 | { 198 | trace_info_z("Z %s\n", __func__); 199 | return NULL; 200 | } 201 | 202 | APULSE_EXPORT 203 | struct timeval * 204 | pa_timeval_sub(struct timeval *tv, pa_usec_t v) 205 | { 206 | trace_info_z("Z %s\n", __func__); 207 | return NULL; 208 | } 209 | 210 | APULSE_EXPORT 211 | struct timeval * 212 | pa_timeval_store(struct timeval *tv, pa_usec_t v) 213 | { 214 | trace_info_z("Z %s\n", __func__); 215 | return NULL; 216 | } 217 | 218 | APULSE_EXPORT 219 | pa_usec_t 220 | pa_timeval_load(const struct timeval *tv) 221 | { 222 | trace_info_z("Z %s\n", __func__); 223 | return 0; 224 | } 225 | 226 | APULSE_EXPORT 227 | char * 228 | pa_get_host_name(char *s, size_t l) 229 | { 230 | trace_info_z("Z %s\n", __func__); 231 | return NULL; 232 | } 233 | 234 | APULSE_EXPORT 235 | char * 236 | pa_get_user_name(char *s, size_t l) 237 | { 238 | trace_info_z("Z %s\n", __func__); 239 | return NULL; 240 | } 241 | 242 | APULSE_EXPORT 243 | struct timeval * 244 | pa_gettimeofday(struct timeval *tv) 245 | { 246 | trace_info_z("Z %s\n", __func__); 247 | return NULL; 248 | } 249 | 250 | APULSE_EXPORT 251 | void * 252 | pa_xmemdup(const void *p, size_t l) 253 | { 254 | trace_info_z("Z %s\n", __func__); 255 | return NULL; 256 | } 257 | 258 | APULSE_EXPORT 259 | void * 260 | pa_xrealloc(void *ptr, size_t size) 261 | { 262 | trace_info_f("F %s ptr=%p, size=%zu\n", __func__, ptr, size); 263 | 264 | void *p = realloc(ptr, size); 265 | if (!p) 266 | return ptr; 267 | 268 | return p; 269 | } 270 | 271 | APULSE_EXPORT 272 | char * 273 | pa_xstrdup(const char *s) 274 | { 275 | trace_info_z("Z %s\n", __func__); 276 | return NULL; 277 | } 278 | 279 | APULSE_EXPORT 280 | char * 281 | pa_xstrndup(const char *s, size_t l) 282 | { 283 | trace_info_z("Z %s\n", __func__); 284 | return NULL; 285 | } 286 | 287 | APULSE_EXPORT 288 | int 289 | pa_sample_format_is_le(pa_sample_format_t f) 290 | { 291 | trace_info_z("Z %s\n", __func__); 292 | return 0; 293 | } 294 | 295 | APULSE_EXPORT 296 | int 297 | pa_sample_format_is_be(pa_sample_format_t f) 298 | { 299 | trace_info_z("Z %s\n", __func__); 300 | return 0; 301 | } 302 | 303 | APULSE_EXPORT 304 | size_t 305 | pa_sample_size_of_format(pa_sample_format_t f) 306 | { 307 | trace_info_z("Z %s\n", __func__); 308 | return 0; 309 | } 310 | 311 | APULSE_EXPORT 312 | pa_sample_spec * 313 | pa_sample_spec_init(pa_sample_spec *spec) 314 | { 315 | trace_info_z("Z %s\n", __func__); 316 | return NULL; 317 | } 318 | 319 | APULSE_EXPORT 320 | int 321 | pa_sample_spec_equal(const pa_sample_spec *a, const pa_sample_spec *b) 322 | { 323 | gchar *s_a = trace_pa_sample_spec_as_string(a); 324 | gchar *s_b = trace_pa_sample_spec_as_string(b); 325 | trace_info_z("Z %s a=%s, b=%s\n", __func__, s_a, s_b); 326 | g_free(s_b); 327 | g_free(s_a); 328 | 329 | return 0; 330 | } 331 | 332 | APULSE_EXPORT 333 | pa_sample_format_t 334 | pa_parse_sample_format(const char *format) 335 | { 336 | trace_info_z("Z %s\n", __func__); 337 | return 0; 338 | } 339 | -------------------------------------------------------------------------------- /src/apulse-ext.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "apulse.h" 26 | #include "trace.h" 27 | #include 28 | #include 29 | #include 30 | 31 | APULSE_EXPORT 32 | pa_operation * 33 | pa_ext_device_manager_test(pa_context *c, pa_ext_device_manager_test_cb_t cb, 34 | void *userdata) 35 | { 36 | trace_info_z("Z %s\n", __func__); 37 | return NULL; 38 | } 39 | 40 | APULSE_EXPORT 41 | pa_operation * 42 | pa_ext_device_manager_read(pa_context *c, pa_ext_device_manager_read_cb_t cb, 43 | void *userdata) 44 | { 45 | trace_info_z("Z %s\n", __func__); 46 | return NULL; 47 | } 48 | 49 | APULSE_EXPORT 50 | pa_operation * 51 | pa_ext_device_manager_set_device_description(pa_context *c, const char *device, 52 | const char *description, 53 | pa_context_success_cb_t cb, 54 | void *userdata) 55 | { 56 | trace_info_z("Z %s\n", __func__); 57 | return NULL; 58 | } 59 | 60 | APULSE_EXPORT 61 | pa_operation * 62 | pa_ext_device_manager_delete(pa_context *c, const char *const s[], 63 | pa_context_success_cb_t cb, void *userdata) 64 | { 65 | trace_info_z("Z %s\n", __func__); 66 | return NULL; 67 | } 68 | 69 | APULSE_EXPORT 70 | pa_operation * 71 | pa_ext_device_manager_enable_role_device_priority_routing( 72 | pa_context *c, int enable, pa_context_success_cb_t cb, void *userdata) 73 | { 74 | trace_info_z("Z %s\n", __func__); 75 | return NULL; 76 | } 77 | 78 | APULSE_EXPORT 79 | pa_operation * 80 | pa_ext_device_manager_reorder_devices_for_role(pa_context *c, const char *role, 81 | const char **devices, 82 | pa_context_success_cb_t cb, 83 | void *userdata) 84 | { 85 | trace_info_z("Z %s\n", __func__); 86 | return NULL; 87 | } 88 | 89 | APULSE_EXPORT 90 | pa_operation * 91 | pa_ext_device_manager_subscribe(pa_context *c, int enable, 92 | pa_context_success_cb_t cb, void *userdata) 93 | { 94 | trace_info_z("Z %s\n", __func__); 95 | return NULL; 96 | } 97 | 98 | APULSE_EXPORT 99 | void 100 | pa_ext_device_manager_set_subscribe_cb(pa_context *c, 101 | pa_ext_device_manager_subscribe_cb_t cb, 102 | void *userdata) 103 | { 104 | trace_info_z("Z %s\n", __func__); 105 | } 106 | 107 | APULSE_EXPORT 108 | pa_operation * 109 | pa_ext_device_restore_test(pa_context *c, pa_ext_device_restore_test_cb_t cb, 110 | void *userdata) 111 | { 112 | trace_info_z("Z %s\n", __func__); 113 | return NULL; 114 | } 115 | 116 | APULSE_EXPORT 117 | pa_operation * 118 | pa_ext_device_restore_subscribe(pa_context *c, int enable, 119 | pa_context_success_cb_t cb, void *userdata) 120 | { 121 | trace_info_z("Z %s\n", __func__); 122 | return NULL; 123 | } 124 | 125 | APULSE_EXPORT 126 | void 127 | pa_ext_device_restore_set_subscribe_cb(pa_context *c, 128 | pa_ext_device_restore_subscribe_cb_t cb, 129 | void *userdata) 130 | { 131 | trace_info_z("Z %s\n", __func__); 132 | } 133 | 134 | APULSE_EXPORT 135 | pa_operation * 136 | pa_ext_device_restore_read_formats_all( 137 | pa_context *c, pa_ext_device_restore_read_device_formats_cb_t cb, 138 | void *userdata) 139 | { 140 | trace_info_z("Z %s\n", __func__); 141 | return NULL; 142 | } 143 | 144 | APULSE_EXPORT 145 | pa_operation * 146 | pa_ext_device_restore_read_formats( 147 | pa_context *c, pa_device_type_t type, uint32_t idx, 148 | pa_ext_device_restore_read_device_formats_cb_t cb, void *userdata) 149 | { 150 | trace_info_z("Z %s\n", __func__); 151 | return NULL; 152 | } 153 | 154 | APULSE_EXPORT 155 | pa_operation * 156 | pa_ext_device_restore_save_formats(pa_context *c, pa_device_type_t type, 157 | uint32_t idx, uint8_t n_formats, 158 | pa_format_info **formats, 159 | pa_context_success_cb_t cb, void *userdata) 160 | { 161 | trace_info_z("Z %s\n", __func__); 162 | return NULL; 163 | } 164 | 165 | APULSE_EXPORT 166 | pa_operation * 167 | pa_ext_stream_restore_test(pa_context *c, pa_ext_stream_restore_test_cb_t cb, 168 | void *userdata) 169 | { 170 | trace_info_z("Z %s\n", __func__); 171 | return NULL; 172 | } 173 | 174 | APULSE_EXPORT 175 | pa_operation * 176 | pa_ext_stream_restore_read(pa_context *c, pa_ext_stream_restore_read_cb_t cb, 177 | void *userdata) 178 | { 179 | trace_info_z("Z %s\n", __func__); 180 | return NULL; 181 | } 182 | 183 | APULSE_EXPORT 184 | pa_operation * 185 | pa_ext_stream_restore_write(pa_context *c, pa_update_mode_t mode, 186 | const pa_ext_stream_restore_info data[], unsigned n, 187 | int apply_immediately, pa_context_success_cb_t cb, 188 | void *userdata) 189 | { 190 | trace_info_z("Z %s\n", __func__); 191 | return NULL; 192 | } 193 | 194 | APULSE_EXPORT 195 | pa_operation * 196 | pa_ext_stream_restore_delete(pa_context *c, const char *const s[], 197 | pa_context_success_cb_t cb, void *userdata); 198 | 199 | APULSE_EXPORT 200 | pa_operation * 201 | pa_ext_stream_restore_subscribe(pa_context *c, int enable, 202 | pa_context_success_cb_t cb, void *userdata) 203 | { 204 | trace_info_z("Z %s\n", __func__); 205 | return NULL; 206 | } 207 | 208 | APULSE_EXPORT 209 | void 210 | pa_ext_stream_restore_set_subscribe_cb(pa_context *c, 211 | pa_ext_stream_restore_subscribe_cb_t cb, 212 | void *userdata) 213 | { 214 | trace_info_z("Z %s\n", __func__); 215 | } 216 | -------------------------------------------------------------------------------- /src/apulse-format-info.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "apulse.h" 26 | #include "trace.h" 27 | 28 | APULSE_EXPORT 29 | void 30 | pa_format_info_free(pa_format_info *f) 31 | { 32 | trace_info_f("F %s f=%p\n", __func__, f); 33 | pa_proplist_free(f->plist); 34 | free(f); 35 | } 36 | 37 | APULSE_EXPORT 38 | pa_format_info * 39 | pa_format_info_new(void) 40 | { 41 | trace_info_f("F %s (void)\n", __func__); 42 | pa_format_info *fi = malloc(sizeof(pa_format_info)); 43 | if (!fi) 44 | return NULL; 45 | 46 | fi->encoding = PA_ENCODING_INVALID; 47 | fi->plist = pa_proplist_new(); 48 | 49 | return fi; 50 | } 51 | 52 | APULSE_EXPORT 53 | void 54 | pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) 55 | { 56 | gchar *s_map = trace_pa_channel_map_as_string(map); 57 | trace_info_f("F %s f=%p, map=%s\n", __func__, f, s_map); 58 | g_free(s_map); 59 | 60 | char buf[PA_CHANNEL_MAP_SNPRINT_MAX]; 61 | pa_channel_map_snprint(buf, sizeof(buf), map); 62 | pa_proplist_sets(f->plist, PA_PROP_FORMAT_CHANNEL_MAP, buf); 63 | } 64 | 65 | APULSE_EXPORT 66 | void 67 | pa_format_info_set_channels(pa_format_info *f, int channels) 68 | { 69 | trace_info_f("F %s f=%p, channels=%d\n", __func__, f, channels); 70 | char buf[20]; 71 | snprintf(buf, sizeof(buf), "%d", channels); 72 | pa_proplist_sets(f->plist, PA_PROP_FORMAT_CHANNELS, buf); 73 | } 74 | 75 | APULSE_EXPORT 76 | void 77 | pa_format_info_set_rate(pa_format_info *f, int rate) 78 | { 79 | trace_info_f("F %s f=%p, rate=%d\n", __func__, f, rate); 80 | char buf[20]; 81 | snprintf(buf, sizeof(buf), "%d", rate); 82 | pa_proplist_sets(f->plist, PA_PROP_FORMAT_RATE, buf); 83 | } 84 | 85 | APULSE_EXPORT 86 | void 87 | pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) 88 | { 89 | trace_info_f("F %s f=%p, sf=%u\n", __func__, f, sf); 90 | pa_proplist_sets(f->plist, PA_PROP_FORMAT_SAMPLE_FORMAT, 91 | pa_sample_format_to_string(sf)); 92 | } 93 | 94 | APULSE_EXPORT 95 | int 96 | pa_format_info_valid(const pa_format_info *f) 97 | { 98 | trace_info_f("F %s f=%p\n", __func__, f); 99 | 100 | int encoding_valid = (f->encoding >= 0 && f->encoding < PA_ENCODING_MAX); 101 | int plist_valid = (f->plist != NULL); 102 | 103 | return encoding_valid && plist_valid; 104 | } 105 | 106 | APULSE_EXPORT 107 | pa_format_info * 108 | pa_format_info_copy(const pa_format_info *src) 109 | { 110 | trace_info_z("Z %s\n", __func__); 111 | return NULL; 112 | } 113 | 114 | APULSE_EXPORT 115 | int 116 | pa_format_info_is_pcm(const pa_format_info *f) 117 | { 118 | trace_info_z("Z %s\n", __func__); 119 | return 0; 120 | } 121 | 122 | APULSE_EXPORT 123 | int 124 | pa_format_info_is_compatible(const pa_format_info *first, 125 | const pa_format_info *second) 126 | { 127 | trace_info_z("Z %s\n", __func__); 128 | return 0; 129 | } 130 | 131 | APULSE_EXPORT 132 | char * 133 | pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) 134 | { 135 | trace_info_z("Z %s\n", __func__); 136 | return NULL; 137 | } 138 | 139 | APULSE_EXPORT 140 | pa_format_info * 141 | pa_format_info_from_string(const char *str) 142 | { 143 | trace_info_z("Z %s\n", __func__); 144 | return NULL; 145 | } 146 | 147 | APULSE_EXPORT 148 | pa_format_info * 149 | pa_format_info_from_sample_spec(const pa_sample_spec *ss, 150 | const pa_channel_map *map) 151 | { 152 | gchar *s_ss = trace_pa_sample_spec_as_string(ss); 153 | gchar *s_map = trace_pa_channel_map_as_string(map); 154 | trace_info_z("Z %s ss=%s, map=%s\n", __func__, s_ss, s_map); 155 | g_free(s_map); 156 | g_free(s_ss); 157 | 158 | return NULL; 159 | } 160 | 161 | APULSE_EXPORT 162 | int 163 | pa_format_info_to_sample_spec(const pa_format_info *f, pa_sample_spec *ss, 164 | pa_channel_map *map) 165 | { 166 | trace_info_z("Z %s\n", __func__); 167 | return 0; 168 | } 169 | 170 | APULSE_EXPORT 171 | pa_prop_type_t 172 | pa_format_info_get_prop_type(const pa_format_info *f, const char *key) 173 | { 174 | trace_info_z("Z %s\n", __func__); 175 | return 0; 176 | } 177 | 178 | APULSE_EXPORT 179 | int 180 | pa_format_info_get_prop_int(const pa_format_info *f, const char *key, int *v) 181 | { 182 | trace_info_z("Z %s\n", __func__); 183 | return 0; 184 | } 185 | 186 | APULSE_EXPORT 187 | int 188 | pa_format_info_get_prop_int_range(const pa_format_info *f, const char *key, 189 | int *min, int *max) 190 | { 191 | trace_info_z("Z %s\n", __func__); 192 | return 0; 193 | } 194 | 195 | APULSE_EXPORT 196 | int 197 | pa_format_info_get_prop_int_array(const pa_format_info *f, const char *key, 198 | int **values, int *n_values) 199 | { 200 | trace_info_z("Z %s\n", __func__); 201 | return 0; 202 | } 203 | 204 | APULSE_EXPORT 205 | int 206 | pa_format_info_get_prop_string(const pa_format_info *f, const char *key, 207 | char **v) 208 | { 209 | trace_info_z("Z %s\n", __func__); 210 | return 0; 211 | } 212 | 213 | APULSE_EXPORT 214 | int 215 | pa_format_info_get_prop_string_array(const pa_format_info *f, const char *key, 216 | char ***values, int *n_values) 217 | { 218 | trace_info_z("Z %s\n", __func__); 219 | return 0; 220 | } 221 | 222 | APULSE_EXPORT 223 | void 224 | pa_format_info_free_string_array(char **values, int n_values) 225 | { 226 | trace_info_z("Z %s\n", __func__); 227 | } 228 | 229 | APULSE_EXPORT 230 | void 231 | pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) 232 | { 233 | trace_info_z("Z %s\n", __func__); 234 | } 235 | 236 | APULSE_EXPORT 237 | void 238 | pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, 239 | const int *values, int n_values) 240 | { 241 | trace_info_z("Z %s\n", __func__); 242 | } 243 | 244 | APULSE_EXPORT 245 | void 246 | pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, 247 | int max) 248 | { 249 | trace_info_z("Z %s\n", __func__); 250 | } 251 | 252 | APULSE_EXPORT 253 | void 254 | pa_format_info_set_prop_string(pa_format_info *f, const char *key, 255 | const char *value) 256 | { 257 | trace_info_z("Z %s\n", __func__); 258 | } 259 | 260 | APULSE_EXPORT 261 | void 262 | pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, 263 | const char **values, int n_values) 264 | { 265 | trace_info_z("Z %s\n", __func__); 266 | } 267 | -------------------------------------------------------------------------------- /src/apulse-mainloop-glib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "apulse.h" 26 | #include "trace.h" 27 | #include 28 | 29 | static pa_io_event * 30 | gml_api_io_new(pa_mainloop_api *a, int fd, pa_io_event_flags_t events, 31 | pa_io_event_cb_t cb, void *userdata) 32 | { 33 | trace_info_z("Z %s a=%p, fd=%d, events=0x%x, cb=%p, userdata=%p\n", 34 | __func__, a, fd, events, cb, userdata); 35 | return NULL; 36 | } 37 | 38 | static void 39 | gml_api_io_enable(pa_io_event *e, pa_io_event_flags_t events) 40 | { 41 | trace_info_z("Z %s e=%p, events=0x%x\n", __func__, e, events); 42 | } 43 | 44 | static void 45 | gml_api_io_free(pa_io_event *e) 46 | { 47 | trace_info_z("Z %s e=%p\n", __func__, e); 48 | } 49 | 50 | static void 51 | gml_api_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t cb) 52 | { 53 | trace_info_z("Z %s\n", __func__); 54 | } 55 | 56 | static pa_time_event * 57 | gml_api_time_new(pa_mainloop_api *a, const struct timeval *tv, 58 | pa_time_event_cb_t cb, void *userdata) 59 | { 60 | trace_info_z("Z %s a=%p, tv=%p {%ld, %ld}, cb=%p, userdata=%p\n", __func__, 61 | a, tv, tv ? tv->tv_sec : 0, tv ? tv->tv_usec : 0, cb, 62 | userdata); 63 | return NULL; 64 | } 65 | 66 | static void 67 | gml_api_time_restart(pa_time_event *e, const struct timeval *tv) 68 | { 69 | trace_info_z("Z %s e=%p, tv=%p {%ld, %ld}\n", __func__, e, tv, 70 | tv ? tv->tv_sec : 0, tv ? tv->tv_usec : 0); 71 | } 72 | 73 | static void 74 | gml_api_time_free(pa_time_event *e) 75 | { 76 | trace_info_z("Z %s e=%p\n", __func__, e); 77 | } 78 | 79 | static void 80 | gml_api_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t cb) 81 | { 82 | trace_info_f("Z %s e=%p, cb=%p\n", __func__, e, cb); 83 | } 84 | 85 | static pa_defer_event * 86 | gml_api_defer_new(pa_mainloop_api *a, pa_defer_event_cb_t cb, void *userdata) 87 | { 88 | trace_info_z("Z %s\n", __func__); 89 | return NULL; 90 | } 91 | 92 | static void 93 | gml_api_defer_enable(pa_defer_event *e, int b) 94 | { 95 | trace_info_z("Z %s\n", __func__); 96 | } 97 | 98 | static void 99 | gml_api_defer_free(pa_defer_event *e) 100 | { 101 | trace_info_z("Z %s\n", __func__); 102 | } 103 | 104 | static void 105 | gml_api_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t cb) 106 | { 107 | trace_info_z("Z %s\n", __func__); 108 | } 109 | 110 | static void 111 | gml_api_quit(pa_mainloop_api *a, int retval) 112 | { 113 | trace_info_z("Z %s a=%p, retval=%d\n", __func__, a, retval); 114 | } 115 | 116 | APULSE_EXPORT 117 | pa_glib_mainloop * 118 | pa_glib_mainloop_new(GMainContext *c) 119 | { 120 | trace_info_z("Z %s c=%p\n", __func__, c); 121 | 122 | pa_glib_mainloop *m = g_malloc0(sizeof(pa_glib_mainloop)); 123 | 124 | m->api = (pa_mainloop_api){ 125 | .userdata = m, 126 | .io_new = gml_api_io_new, 127 | .io_enable = gml_api_io_enable, 128 | .io_free = gml_api_io_free, 129 | .io_set_destroy = gml_api_io_set_destroy, 130 | .time_new = gml_api_time_new, 131 | .time_restart = gml_api_time_restart, 132 | .time_free = gml_api_time_free, 133 | .time_set_destroy = gml_api_time_set_destroy, 134 | .defer_new = gml_api_defer_new, 135 | .defer_enable = gml_api_defer_enable, 136 | .defer_free = gml_api_defer_free, 137 | .defer_set_destroy = gml_api_defer_set_destroy, 138 | .quit = gml_api_quit, 139 | }; 140 | 141 | return m; 142 | } 143 | 144 | APULSE_EXPORT 145 | void 146 | pa_glib_mainloop_free(pa_glib_mainloop *g) 147 | { 148 | trace_info_f("F %s g=%p\n", __func__, g); 149 | g_free(g); 150 | } 151 | 152 | APULSE_EXPORT 153 | pa_mainloop_api * 154 | pa_glib_mainloop_get_api(pa_glib_mainloop *g) 155 | { 156 | trace_info_f("F %s g=%p\n", __func__, g); 157 | return &g->api; 158 | } 159 | -------------------------------------------------------------------------------- /src/apulse-misc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include "apulse.h" 28 | #include "trace.h" 29 | #include "util.h" 30 | 31 | APULSE_EXPORT 32 | const char * 33 | pa_get_library_version(void) 34 | { 35 | trace_info_f("F %s (void)\n", __func__); 36 | 37 | return pa_get_headers_version(); 38 | } 39 | 40 | APULSE_EXPORT 41 | int 42 | pa_sample_format_valid(unsigned format) 43 | { 44 | return format < PA_SAMPLE_MAX; 45 | } 46 | 47 | APULSE_EXPORT 48 | int 49 | pa_sample_rate_valid(uint32_t rate) 50 | { 51 | return 0 < rate && rate <= PA_RATE_MAX; 52 | } 53 | 54 | APULSE_EXPORT 55 | int 56 | pa_channels_valid(uint8_t channels) 57 | { 58 | return 0 < channels && channels <= PA_CHANNELS_MAX; 59 | } 60 | 61 | APULSE_EXPORT 62 | int 63 | pa_sample_spec_valid(const pa_sample_spec *spec) 64 | { 65 | return spec && pa_sample_format_valid(spec->format) && 66 | pa_sample_rate_valid(spec->rate) && 67 | pa_channels_valid(spec->channels); 68 | } 69 | 70 | APULSE_EXPORT 71 | const char * 72 | pa_strerror(int error) 73 | { 74 | trace_info_f("P %s error=%d\n", __func__, error); 75 | 76 | return "Oops."; 77 | } 78 | 79 | APULSE_EXPORT 80 | size_t 81 | pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) 82 | { 83 | return t * pa_bytes_per_second(spec) / (1000 * 1000); 84 | } 85 | 86 | APULSE_EXPORT 87 | pa_usec_t 88 | pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) 89 | { 90 | size_t bytes_per_second = pa_bytes_per_second(spec); 91 | if (bytes_per_second == 0) 92 | return 0; 93 | 94 | return 1000 * 1000 * length / bytes_per_second; 95 | } 96 | 97 | APULSE_EXPORT 98 | size_t 99 | pa_bytes_per_second(const pa_sample_spec *spec) 100 | { 101 | return spec->rate * pa_frame_size(spec); 102 | } 103 | 104 | APULSE_EXPORT 105 | size_t 106 | pa_frame_size(const pa_sample_spec *spec) 107 | { 108 | return spec->channels * pa_sample_size(spec); 109 | } 110 | 111 | APULSE_EXPORT 112 | size_t 113 | pa_sample_size(const pa_sample_spec *spec) 114 | { 115 | switch (spec->format) { 116 | case PA_SAMPLE_U8: 117 | case PA_SAMPLE_ALAW: 118 | case PA_SAMPLE_ULAW: 119 | return 1; 120 | 121 | case PA_SAMPLE_S16LE: 122 | case PA_SAMPLE_S16BE: 123 | return 2; 124 | 125 | case PA_SAMPLE_S24LE: 126 | case PA_SAMPLE_S24BE: 127 | return 3; 128 | 129 | case PA_SAMPLE_FLOAT32LE: 130 | case PA_SAMPLE_FLOAT32BE: 131 | case PA_SAMPLE_S32LE: 132 | case PA_SAMPLE_S32BE: 133 | case PA_SAMPLE_S24_32LE: 134 | case PA_SAMPLE_S24_32BE: 135 | case PA_SAMPLE_MAX: 136 | return 4; 137 | 138 | case PA_SAMPLE_INVALID: 139 | default: 140 | return 0; 141 | } 142 | } 143 | 144 | APULSE_EXPORT 145 | pa_cvolume * 146 | pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) 147 | { 148 | trace_info_f("F %s a=%p, channels=%u, v=%u\n", __func__, a, channels, v); 149 | 150 | a->channels = MIN(channels, PA_CHANNELS_MAX); 151 | for (unsigned int k = 0; k < a->channels; k++) 152 | a->values[k] = CLAMP(v, PA_VOLUME_MUTED, PA_VOLUME_MAX); 153 | 154 | return a; 155 | } 156 | 157 | APULSE_EXPORT 158 | pa_volume_t 159 | pa_cvolume_avg(const pa_cvolume *a) 160 | { 161 | trace_info_z("Z %s a=%p\n", __func__, a); 162 | 163 | return 0; 164 | } 165 | 166 | APULSE_EXPORT 167 | const char * 168 | pa_sample_format_to_string(pa_sample_format_t format) 169 | { 170 | switch (format) { 171 | case PA_SAMPLE_U8: 172 | return "u8"; 173 | case PA_SAMPLE_ALAW: 174 | return "aLaw"; 175 | case PA_SAMPLE_ULAW: 176 | return "uLaw"; 177 | case PA_SAMPLE_S16LE: 178 | return "s16le"; 179 | case PA_SAMPLE_S16BE: 180 | return "s16be"; 181 | case PA_SAMPLE_FLOAT32LE: 182 | return "float32le"; 183 | case PA_SAMPLE_FLOAT32BE: 184 | return "float32be"; 185 | case PA_SAMPLE_S32LE: 186 | return "s32le"; 187 | case PA_SAMPLE_S32BE: 188 | return "s32be"; 189 | case PA_SAMPLE_S24LE: 190 | return "s24le"; 191 | case PA_SAMPLE_S24BE: 192 | return "s24be"; 193 | case PA_SAMPLE_S24_32LE: 194 | return "s24-32le"; 195 | case PA_SAMPLE_S24_32BE: 196 | return "s24-32be"; 197 | default: 198 | return NULL; 199 | } 200 | } 201 | 202 | APULSE_EXPORT 203 | char * 204 | pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) 205 | { 206 | gchar *s_spec = trace_pa_sample_spec_as_string(spec); 207 | trace_info_f("F %s s=%p, l=%u, spec=%s\n", __func__, s, (unsigned)l, 208 | s_spec); 209 | g_free(s_spec); 210 | 211 | if (spec && pa_sample_spec_valid(spec)) { 212 | snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), 213 | spec->channels, spec->rate); 214 | } else { 215 | snprintf(s, l, "invalid"); 216 | } 217 | 218 | return s; 219 | } 220 | 221 | APULSE_EXPORT 222 | char * 223 | pa_path_get_filename(const char *p) 224 | { 225 | char *last_slash; 226 | if (!p) 227 | return NULL; 228 | last_slash = strrchr(p, '/'); 229 | if (!last_slash) 230 | return (char *)p; 231 | return last_slash + 1; 232 | } 233 | 234 | APULSE_EXPORT 235 | pa_usec_t 236 | pa_rtclock_now(void) 237 | { 238 | trace_info_f("F %s (void)\n", __func__); 239 | 240 | struct timespec now; 241 | clock_gettime(CLOCK_MONOTONIC, &now); 242 | 243 | return (pa_usec_t)now.tv_sec * 1000000 + now.tv_nsec / 1000; 244 | } 245 | 246 | APULSE_EXPORT 247 | void 248 | pa_xfree(void *p) 249 | { 250 | free(p); 251 | } 252 | 253 | APULSE_EXPORT 254 | void * 255 | pa_xmalloc(size_t size) 256 | { 257 | return malloc(size); 258 | } 259 | 260 | APULSE_EXPORT 261 | void * 262 | pa_xmalloc0(size_t l) 263 | { 264 | return calloc(l, 1); 265 | } 266 | 267 | APULSE_EXPORT 268 | char * 269 | pa_locale_to_utf8(const char *str) 270 | { 271 | trace_info_z("Z %s\n", __func__); 272 | 273 | return strdup(str); 274 | } 275 | 276 | APULSE_EXPORT 277 | char * 278 | pa_get_binary_name(char *s, size_t len) 279 | { 280 | trace_info_f("F %s s=%p, len=%d\n", __func__, s, (int)len); 281 | 282 | if (len == 0) 283 | return NULL; 284 | 285 | char fullpath[PATH_MAX]; 286 | ssize_t flen = readlink("/proc/self/exe", fullpath, sizeof(fullpath) - 1); 287 | 288 | if (flen < 0) 289 | return NULL; 290 | 291 | // ensure fullpath ends with '\0' 292 | flen = MIN(flen, sizeof(fullpath) - 1); 293 | fullpath[flen] = 0; 294 | 295 | char *name = basename(fullpath); 296 | size_t name_len = strlen(name); 297 | 298 | // copy no more than len bytes to s 299 | name_len = MIN(name_len, len - 1); 300 | memcpy(s, name, name_len); 301 | s[name_len] = 0; 302 | 303 | return s; 304 | } 305 | -------------------------------------------------------------------------------- /src/apulse-operation.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "apulse.h" 26 | #include "trace.h" 27 | 28 | static void 29 | deh_perform_operation(pa_mainloop_api *api, pa_defer_event *de, void *userdata) 30 | { 31 | pa_operation *op = userdata; 32 | op->handler(op); 33 | } 34 | 35 | pa_operation * 36 | pa_operation_new(pa_mainloop_api *api, void (*handler)(pa_operation *op)) 37 | { 38 | pa_operation *o = g_slice_new0(pa_operation); 39 | o->state = PA_OPERATION_RUNNING; 40 | o->ref_cnt = 1; 41 | o->api = api; 42 | o->handler = handler; 43 | 44 | return o; 45 | } 46 | 47 | void 48 | pa_operation_launch(pa_operation *op) 49 | { 50 | pa_mainloop_api *api = op->api; 51 | api->defer_new(api, deh_perform_operation, pa_operation_ref(op)); 52 | } 53 | 54 | void 55 | pa_operation_done(pa_operation *op) 56 | { 57 | op->state = PA_OPERATION_DONE; 58 | pa_operation_unref(op); 59 | } 60 | 61 | APULSE_EXPORT 62 | void 63 | pa_operation_cancel(pa_operation *o) 64 | { 65 | trace_info_z("Z %s o=%p\n", __func__, o); 66 | } 67 | 68 | APULSE_EXPORT 69 | pa_operation_state_t 70 | pa_operation_get_state(pa_operation *o) 71 | { 72 | trace_info_f("F %s o=%p\n", __func__, o); 73 | if (!o) { 74 | trace_error("Z %s operation is NULL\n", __func__); 75 | return PA_OPERATION_DONE; 76 | } 77 | return o->state; 78 | } 79 | 80 | APULSE_EXPORT 81 | pa_operation * 82 | pa_operation_ref(pa_operation *o) 83 | { 84 | trace_info_f("F %s o=%p\n", __func__, o); 85 | 86 | if (!o) 87 | return NULL; 88 | o->ref_cnt++; 89 | return o; 90 | } 91 | 92 | APULSE_EXPORT 93 | void 94 | pa_operation_unref(pa_operation *o) 95 | { 96 | trace_info_f("F %s o=%p\n", __func__, o); 97 | 98 | if (!o) 99 | return; 100 | o->ref_cnt--; 101 | if (o->ref_cnt == 0) 102 | g_slice_free(pa_operation, o); 103 | } 104 | 105 | APULSE_EXPORT 106 | void 107 | pa_operation_set_state_callback(pa_operation *o, pa_operation_notify_cb_t cb, 108 | void *userdata) 109 | { 110 | trace_info_z("Z %s\n", __func__); 111 | } 112 | -------------------------------------------------------------------------------- /src/apulse-proplist.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "apulse.h" 26 | #include "trace.h" 27 | 28 | struct prop { 29 | size_t len; 30 | char *data; 31 | }; 32 | 33 | APULSE_EXPORT 34 | void 35 | pa_proplist_free(pa_proplist *p) 36 | { 37 | trace_info_f("F %s p=%p\n", __func__, p); 38 | 39 | g_hash_table_destroy(p->ht); 40 | free(p); 41 | } 42 | 43 | static void 44 | string_destroy_func(gpointer data) 45 | { 46 | free(data); 47 | } 48 | 49 | static void 50 | prop_destroy_func(gpointer data) 51 | { 52 | struct prop *p = data; 53 | 54 | free(p->data); 55 | g_slice_free1(sizeof(*p), p); 56 | } 57 | 58 | APULSE_EXPORT 59 | pa_proplist * 60 | pa_proplist_new(void) 61 | { 62 | trace_info_f("F %s (void)\n", __func__); 63 | 64 | pa_proplist *p = calloc(1, sizeof(pa_proplist)); 65 | p->ht = g_hash_table_new_full(g_str_hash, g_str_equal, string_destroy_func, 66 | prop_destroy_func); 67 | return p; 68 | } 69 | 70 | APULSE_EXPORT 71 | int 72 | pa_proplist_set(pa_proplist *p, const char *key, const void *data, 73 | size_t nbytes) 74 | { 75 | trace_info_f("F %s p=%p, key=%s, data=%p, nbytes=%d\n", __func__, p, key, 76 | data, (int)nbytes); 77 | 78 | struct prop *v = g_slice_alloc(sizeof(*v)); 79 | if (!v) 80 | return -1; 81 | 82 | v->data = g_memdup(data, nbytes); 83 | v->len = nbytes; 84 | 85 | g_hash_table_insert(p->ht, strdup(key), v); 86 | return 0; 87 | } 88 | 89 | APULSE_EXPORT 90 | int 91 | pa_proplist_sets(pa_proplist *p, const char *key, const char *value) 92 | { 93 | trace_info_f("F %s p=%p, key=%s, value=%s\n", __func__, p, key, value); 94 | 95 | struct prop *v = g_slice_alloc(sizeof(*v)); 96 | if (!v) 97 | return -1; 98 | v->data = strdup(value); 99 | v->len = strlen(value) + 1; 100 | 101 | g_hash_table_insert(p->ht, strdup(key), v); 102 | return 0; 103 | } 104 | 105 | APULSE_EXPORT 106 | void 107 | pa_proplist_clear(pa_proplist *p) 108 | { 109 | trace_info_z("Z %s\n", __func__); 110 | } 111 | 112 | APULSE_EXPORT 113 | void 114 | pa_proplist_update(pa_proplist *p, pa_update_mode_t mode, 115 | const pa_proplist *other) 116 | { 117 | trace_info_z("Z %s\n", __func__); 118 | } 119 | 120 | APULSE_EXPORT 121 | int 122 | pa_proplist_contains(pa_proplist *p, const char *key) 123 | { 124 | trace_info_f("F %s p=%p, key=%s\n", __func__, p, key); 125 | 126 | return g_hash_table_lookup(p->ht, key) != NULL; 127 | } 128 | 129 | APULSE_EXPORT 130 | const char * 131 | pa_proplist_gets(pa_proplist *p, const char *key) 132 | { 133 | trace_info_f("F %s p=%p, key=%s\n", __func__, p, key); 134 | 135 | struct prop *v = g_hash_table_lookup(p->ht, key); 136 | 137 | if (!v) 138 | return NULL; 139 | 140 | if (v->len == 0) 141 | return NULL; 142 | 143 | if (v->data[v->len - 1] != '\0') 144 | return NULL; // not a string 145 | 146 | return v->data; 147 | } 148 | 149 | APULSE_EXPORT 150 | pa_proplist * 151 | pa_proplist_copy(const pa_proplist *p) 152 | { 153 | trace_info_z("Z %s\n", __func__); 154 | return NULL; 155 | } 156 | 157 | APULSE_EXPORT 158 | unsigned 159 | pa_proplist_size(pa_proplist *p) 160 | { 161 | trace_info_z("Z %s\n", __func__); 162 | return 0; 163 | } 164 | 165 | APULSE_EXPORT 166 | int 167 | pa_proplist_isempty(pa_proplist *p) 168 | { 169 | trace_info_z("Z %s\n", __func__); 170 | return 0; 171 | } 172 | 173 | APULSE_EXPORT 174 | int 175 | pa_proplist_equal(pa_proplist *a, pa_proplist *b) 176 | { 177 | trace_info_z("Z %s\n", __func__); 178 | return 0; 179 | } 180 | 181 | APULSE_EXPORT 182 | int 183 | pa_proplist_key_valid(const char *key) 184 | { 185 | trace_info_z("Z %s\n", __func__); 186 | return 0; 187 | } 188 | 189 | APULSE_EXPORT 190 | int 191 | pa_proplist_setp(pa_proplist *p, const char *pair) 192 | { 193 | trace_info_z("Z %s\n", __func__); 194 | return 0; 195 | } 196 | 197 | APULSE_EXPORT 198 | int 199 | pa_proplist_setf(pa_proplist *p, const char *key, const char *format, ...) 200 | { 201 | trace_info_z("Z %s\n", __func__); 202 | return 0; 203 | } 204 | 205 | APULSE_EXPORT 206 | int 207 | pa_proplist_get(pa_proplist *p, const char *key, const void **data, 208 | size_t *nbytes) 209 | { 210 | trace_info_z("Z %s\n", __func__); 211 | return 0; 212 | } 213 | 214 | APULSE_EXPORT 215 | int 216 | pa_proplist_unset(pa_proplist *p, const char *key) 217 | { 218 | trace_info_z("Z %s\n", __func__); 219 | return 0; 220 | } 221 | 222 | APULSE_EXPORT 223 | int 224 | pa_proplist_unset_many(pa_proplist *p, const char *const keys[]) 225 | { 226 | trace_info_z("Z %s\n", __func__); 227 | return 0; 228 | } 229 | 230 | APULSE_EXPORT 231 | const char * 232 | pa_proplist_iterate(pa_proplist *p, void **state) 233 | { 234 | trace_info_z("Z %s\n", __func__); 235 | return NULL; 236 | } 237 | 238 | APULSE_EXPORT 239 | char * 240 | pa_proplist_to_string(pa_proplist *p) 241 | { 242 | trace_info_z("Z %s\n", __func__); 243 | return NULL; 244 | } 245 | 246 | APULSE_EXPORT 247 | char * 248 | pa_proplist_to_string_sep(pa_proplist *p, const char *sep) 249 | { 250 | trace_info_z("Z %s\n", __func__); 251 | return NULL; 252 | } 253 | 254 | APULSE_EXPORT 255 | pa_proplist * 256 | pa_proplist_from_string(const char *str) 257 | { 258 | trace_info_z("Z %s\n", __func__); 259 | return NULL; 260 | } 261 | -------------------------------------------------------------------------------- /src/apulse-signal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "apulse.h" 26 | #include "trace.h" 27 | 28 | APULSE_EXPORT 29 | int 30 | pa_signal_init(pa_mainloop_api *api) 31 | { 32 | trace_info_z("Z %s\n", __func__); 33 | 34 | return 0; 35 | } 36 | 37 | APULSE_EXPORT 38 | void 39 | pa_signal_done(void) 40 | { 41 | trace_info_z("Z %s\n", __func__); 42 | } 43 | 44 | APULSE_EXPORT 45 | pa_signal_event * 46 | pa_signal_new(int sig, pa_signal_cb_t callback, void *userdata) 47 | { 48 | trace_info_z("Z %s\n", __func__); 49 | 50 | return NULL; 51 | } 52 | 53 | APULSE_EXPORT 54 | void 55 | pa_signal_free(pa_signal_event *e) 56 | { 57 | trace_info_z("Z %s\n", __func__); 58 | } 59 | 60 | APULSE_EXPORT 61 | void 62 | pa_signal_set_destroy(pa_signal_event *e, pa_signal_destroy_cb_t callback) 63 | { 64 | trace_info_z("Z %s\n", __func__); 65 | } 66 | -------------------------------------------------------------------------------- /src/apulse-simple.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "apulse.h" 26 | #include "trace.h" 27 | #include 28 | 29 | APULSE_EXPORT 30 | void 31 | pa_simple_free(pa_simple *s) 32 | { 33 | trace_info_f("F %s s=%p\n", __func__, s); 34 | 35 | if (s->initialized) { 36 | pa_stream_unref(s->stream); 37 | pa_context_disconnect(s->context); 38 | pa_context_unref(s->context); 39 | pa_threaded_mainloop_free(s->mainloop); 40 | 41 | s->initialized = 0; 42 | } 43 | 44 | free(s); 45 | } 46 | 47 | static void 48 | pai_simple_context_state_cb(pa_context *c, void *user_data) 49 | { 50 | pa_threaded_mainloop *mainloop = user_data; 51 | 52 | switch (pa_context_get_state(c)) { 53 | case PA_CONTEXT_READY: 54 | case PA_CONTEXT_TERMINATED: 55 | case PA_CONTEXT_FAILED: 56 | pa_threaded_mainloop_signal(mainloop, 0); 57 | break; 58 | default: 59 | break; 60 | } 61 | } 62 | 63 | static void 64 | pai_simple_stream_state_cb(pa_stream *s, void *user_data) 65 | { 66 | pa_simple *simple = user_data; 67 | 68 | switch (pa_stream_get_state(s)) { 69 | case PA_STREAM_READY: 70 | case PA_STREAM_FAILED: 71 | case PA_STREAM_TERMINATED: 72 | pa_threaded_mainloop_signal(simple->mainloop, 0); 73 | break; 74 | default: 75 | break; 76 | } 77 | } 78 | 79 | static void 80 | pai_simple_stream_write_cb(pa_stream *s, size_t length, void *user_data) 81 | { 82 | pa_simple *simple = user_data; 83 | pa_threaded_mainloop_signal(simple->mainloop, 0); 84 | } 85 | 86 | static void 87 | pai_simple_stream_read_cb(pa_stream *s, size_t length, void *user_data) 88 | { 89 | pa_simple *simple = user_data; 90 | pa_threaded_mainloop_signal(simple->mainloop, 0); 91 | } 92 | 93 | static void 94 | pai_simple_stream_latency_update_cb(pa_stream *s, void *user_data) 95 | { 96 | pa_simple *simple = user_data; 97 | pa_threaded_mainloop_signal(simple->mainloop, 0); 98 | } 99 | 100 | static int 101 | pai_simple_stream_connect(pa_simple *simple, pa_stream_direction_t dir, 102 | const char *stream_name, const pa_sample_spec *ss, 103 | const pa_buffer_attr *attr) 104 | { 105 | simple->stream = pa_stream_new(simple->context, stream_name, ss, NULL); 106 | if (!simple->stream) { 107 | trace_error("%s: can't create stream", __func__); 108 | goto err_1; 109 | } 110 | 111 | pa_stream_set_state_callback(simple->stream, pai_simple_stream_state_cb, 112 | simple); 113 | pa_stream_set_read_callback(simple->stream, pai_simple_stream_read_cb, 114 | simple); 115 | pa_stream_set_write_callback(simple->stream, pai_simple_stream_write_cb, 116 | simple); 117 | pa_stream_set_latency_update_callback( 118 | simple->stream, pai_simple_stream_latency_update_cb, simple); 119 | 120 | if (dir == PA_STREAM_PLAYBACK) { 121 | if (pa_stream_connect_playback(simple->stream, NULL, attr, 0, NULL, 122 | NULL) < 0) 123 | { 124 | trace_error("%s: can't connect playback stream", __func__); 125 | goto err_2; 126 | } 127 | } else { 128 | int flags = PA_STREAM_ADJUST_LATENCY; 129 | if (pa_stream_connect_record(simple->stream, NULL, attr, flags) < 0) { 130 | trace_error("%s: can't connect record stream", __func__); 131 | goto err_2; 132 | } 133 | } 134 | 135 | while (1) { 136 | pa_stream_state_t state = pa_stream_get_state(simple->stream); 137 | if (state == PA_STREAM_READY) 138 | break; 139 | if (!PA_STREAM_IS_GOOD(state)) { 140 | trace_error("%s, stream is not ready\n", __func__); 141 | goto err_2; 142 | } 143 | pa_threaded_mainloop_wait(simple->mainloop); 144 | } 145 | 146 | return 0; 147 | 148 | err_2: 149 | pa_stream_unref(simple->stream); 150 | 151 | err_1: 152 | return -1; 153 | } 154 | 155 | APULSE_EXPORT 156 | pa_simple * 157 | pa_simple_new(const char *server, const char *name, pa_stream_direction_t dir, 158 | const char *dev, const char *stream_name, 159 | const pa_sample_spec *ss, const pa_channel_map *map, 160 | const pa_buffer_attr *attr, int *error) 161 | { 162 | gchar *s_map = trace_pa_channel_map_as_string(map); 163 | gchar *s_ss = trace_pa_sample_spec_as_string(ss); 164 | trace_info_f( 165 | "F %s server=%s, name=%s, dir=%d, dev=%s, stream_name=%s, ss=%s, " 166 | "map=%s, attr=%p\n", 167 | __func__, server, name, dir, dev, stream_name, s_ss, s_map, attr); 168 | g_free(s_ss); 169 | g_free(s_map); 170 | 171 | pa_simple *simple = calloc(sizeof(*simple), 1); 172 | if (!simple) { 173 | trace_error("%s: can't allocate memory", __func__); 174 | return NULL; 175 | } 176 | 177 | simple->mainloop = pa_threaded_mainloop_new(); 178 | if (!simple->mainloop) { 179 | trace_error("%s: can't create mainloop", __func__); 180 | goto err_1; 181 | } 182 | 183 | simple->context = 184 | pa_context_new(pa_threaded_mainloop_get_api(simple->mainloop), name); 185 | if (!simple->context) { 186 | trace_error("%s: can't create context", __func__); 187 | goto err_2; 188 | } 189 | 190 | pa_context_set_state_callback(simple->context, pai_simple_context_state_cb, 191 | simple->mainloop); 192 | 193 | if (pa_context_connect(simple->context, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) 194 | { 195 | trace_error("%s: can't connect context", __func__); 196 | goto err_3; 197 | } 198 | 199 | pa_threaded_mainloop_lock(simple->mainloop); 200 | 201 | if (pa_threaded_mainloop_start(simple->mainloop) < 0) { 202 | trace_error("%s: can't start mainloop", __func__); 203 | goto err_4; 204 | } 205 | 206 | pa_threaded_mainloop_wait(simple->mainloop); 207 | 208 | if (pa_context_get_state(simple->context) != PA_CONTEXT_READY) { 209 | trace_error("%s: can't get context ready", __func__); 210 | goto err_5; 211 | } 212 | 213 | if (pai_simple_stream_connect(simple, dir, stream_name, ss, attr) < 0) { 214 | trace_error("%s: can't connect stream", __func__); 215 | goto err_5; 216 | } 217 | 218 | pa_threaded_mainloop_unlock(simple->mainloop); 219 | 220 | simple->initialized = 1; 221 | return simple; 222 | 223 | err_5: 224 | pa_threaded_mainloop_unlock(simple->mainloop); 225 | 226 | err_4: 227 | pa_context_disconnect(simple->context); 228 | 229 | err_3: 230 | pa_context_unref(simple->context); 231 | 232 | err_2: 233 | pa_threaded_mainloop_free(simple->mainloop); 234 | 235 | err_1: 236 | free(simple); 237 | 238 | // TODO: error codes 239 | if (error) 240 | *error = -1; 241 | 242 | return NULL; 243 | } 244 | 245 | APULSE_EXPORT 246 | int 247 | pa_simple_write(pa_simple *s, const void *data, size_t bytes, int *error) 248 | { 249 | trace_info_f("F %s s=%p, data=%p, bytes=%zu, error=%p\n", __func__, s, data, 250 | bytes, error); 251 | 252 | size_t to_write = bytes; 253 | const char *p = data; 254 | 255 | pa_threaded_mainloop_lock(s->mainloop); 256 | 257 | while (to_write > 0) { 258 | size_t chunk_size = pa_stream_writable_size(s->stream); 259 | while (chunk_size == 0) { 260 | // Sleep here until write callback is called. 261 | pa_threaded_mainloop_wait(s->mainloop); 262 | chunk_size = pa_stream_writable_size(s->stream); 263 | } 264 | 265 | chunk_size = MIN(chunk_size, to_write); 266 | if (pa_stream_write(s->stream, p, chunk_size, NULL, 0, 267 | PA_SEEK_RELATIVE) < 0) 268 | { 269 | trace_error("%s: can't write", __func__); 270 | goto err; 271 | } 272 | 273 | p += chunk_size; 274 | to_write -= chunk_size; 275 | } 276 | 277 | pa_threaded_mainloop_unlock(s->mainloop); 278 | 279 | return 0; 280 | 281 | err: 282 | pa_threaded_mainloop_unlock(s->mainloop); 283 | return -1; 284 | } 285 | 286 | APULSE_EXPORT 287 | int 288 | pa_simple_drain(pa_simple *s, int *error) 289 | { 290 | trace_info_z("Z %s\n", __func__); 291 | return -1; 292 | } 293 | 294 | APULSE_EXPORT 295 | int 296 | pa_simple_read(pa_simple *s, void *data, size_t bytes, int *error) 297 | { 298 | trace_info_z("Z %s\n", __func__); 299 | return -1; 300 | } 301 | 302 | APULSE_EXPORT 303 | pa_usec_t 304 | pa_simple_get_latency(pa_simple *s, int *error) 305 | { 306 | trace_info_f("F %s s=%p, error=%p\n", __func__, s, error); 307 | 308 | pa_usec_t latency = 0; 309 | int negative; 310 | pa_stream_get_latency(s->stream, &latency, &negative); 311 | 312 | return latency; 313 | } 314 | 315 | APULSE_EXPORT 316 | int 317 | pa_simple_flush(pa_simple *s, int *error) 318 | { 319 | trace_info_z("Z %s\n", __func__); 320 | return -1; 321 | } 322 | -------------------------------------------------------------------------------- /src/apulse-threaded-mainloop.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #define _XOPEN_SOURCE 500 26 | #include "apulse.h" 27 | #include "trace.h" 28 | 29 | static void * 30 | mainloop_thread(void *param) 31 | { 32 | pa_threaded_mainloop *m = param; 33 | int retval; 34 | 35 | pthread_mutex_lock(&m->lock); 36 | pa_mainloop_run(m->m, &retval); 37 | pthread_mutex_unlock(&m->lock); 38 | 39 | return NULL; 40 | } 41 | 42 | static int 43 | poll_func(struct pollfd *fds, nfds_t nfds, int timeout, void *userdata) 44 | { 45 | pthread_mutex_t *lock = userdata; 46 | 47 | pthread_mutex_unlock(lock); 48 | int ret = poll(fds, nfds, timeout); 49 | pthread_mutex_lock(lock); 50 | 51 | return ret; 52 | } 53 | 54 | APULSE_EXPORT 55 | void 56 | pa_threaded_mainloop_free(pa_threaded_mainloop *m) 57 | { 58 | trace_info_f("F %s m=%p\n", __func__, m); 59 | 60 | if (m->running) 61 | pa_threaded_mainloop_stop(m); 62 | 63 | pthread_mutex_destroy(&m->lock); 64 | pthread_cond_destroy(&m->cond); 65 | pa_mainloop_free(m->m); 66 | free(m); 67 | } 68 | 69 | APULSE_EXPORT 70 | pa_mainloop_api * 71 | pa_threaded_mainloop_get_api(pa_threaded_mainloop *m) 72 | { 73 | trace_info_f("F %s m=%p\n", __func__, m); 74 | 75 | return &m->m->api; 76 | } 77 | 78 | APULSE_EXPORT 79 | int 80 | pa_threaded_mainloop_in_thread(pa_threaded_mainloop *m) 81 | { 82 | trace_info_f("F %s m=%p\n", __func__, m); 83 | 84 | return pthread_equal(pthread_self(), m->t); 85 | } 86 | 87 | APULSE_EXPORT 88 | void 89 | pa_threaded_mainloop_lock(pa_threaded_mainloop *m) 90 | { 91 | trace_info_f("F %s m=%p\n", __func__, m); 92 | 93 | pthread_mutex_lock(&m->lock); 94 | } 95 | 96 | APULSE_EXPORT 97 | pa_threaded_mainloop * 98 | pa_threaded_mainloop_new(void) 99 | { 100 | trace_info_f("F %s (void)\n", __func__); 101 | 102 | pthread_mutexattr_t mutex_attr; 103 | pa_threaded_mainloop *m = calloc(1, sizeof(*m)); 104 | m->m = pa_mainloop_new(); 105 | 106 | pthread_mutexattr_init(&mutex_attr); 107 | pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); 108 | pthread_mutex_init(&m->lock, &mutex_attr); 109 | pthread_mutexattr_destroy(&mutex_attr); 110 | 111 | pthread_cond_init(&m->cond, NULL); 112 | 113 | pa_mainloop_set_poll_func(m->m, poll_func, &m->lock); 114 | 115 | return m; 116 | } 117 | 118 | APULSE_EXPORT 119 | void 120 | pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) 121 | { 122 | trace_info_f("F %s m=%p, wait_for_accept=%d\n", __func__, m, 123 | wait_for_accept); 124 | 125 | if (wait_for_accept != 0) 126 | trace_error("%s, not implemented branch\n", __func__); 127 | 128 | pthread_cond_signal(&m->cond); 129 | } 130 | 131 | APULSE_EXPORT 132 | int 133 | pa_threaded_mainloop_start(pa_threaded_mainloop *m) 134 | { 135 | trace_info_f("F %s m=%p\n", __func__, m); 136 | 137 | if (m->running) 138 | return 1; 139 | pthread_create(&m->t, NULL, mainloop_thread, m); 140 | m->running = 1; 141 | return 0; 142 | } 143 | 144 | APULSE_EXPORT 145 | void 146 | pa_threaded_mainloop_stop(pa_threaded_mainloop *m) 147 | { 148 | trace_info_f("F %s m=%p\n", __func__, m); 149 | 150 | pa_mainloop_quit(m->m, 0); 151 | pthread_join(m->t, NULL); 152 | m->running = 0; 153 | } 154 | 155 | APULSE_EXPORT 156 | void 157 | pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) 158 | { 159 | trace_info_f("F %s m=%p\n", __func__, m); 160 | 161 | pthread_mutex_unlock(&m->lock); 162 | } 163 | 164 | APULSE_EXPORT 165 | void 166 | pa_threaded_mainloop_wait(pa_threaded_mainloop *m) 167 | { 168 | trace_info_f("F %s m=%p\n", __func__, m); 169 | 170 | pthread_cond_wait(&m->cond, &m->lock); 171 | } 172 | 173 | APULSE_EXPORT 174 | void 175 | pa_threaded_mainloop_accept(pa_threaded_mainloop *m) 176 | { 177 | trace_info_z("Z %s\n", __func__); 178 | } 179 | 180 | APULSE_EXPORT 181 | int 182 | pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) 183 | { 184 | trace_info_z("Z %s\n", __func__); 185 | return 0; 186 | } 187 | 188 | APULSE_EXPORT 189 | void 190 | pa_threaded_mainloop_set_name(pa_threaded_mainloop *m, const char *name) 191 | { 192 | trace_info_z("Z %s\n", __func__); 193 | } 194 | -------------------------------------------------------------------------------- /src/apulse-volume.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "apulse.h" 26 | #include "trace.h" 27 | #include 28 | #include 29 | 30 | APULSE_EXPORT 31 | pa_volume_t 32 | pa_sw_volume_from_linear(double v) 33 | { 34 | trace_info_f("F %s v=%f\n", __func__, v); 35 | 36 | if (v <= 0.0) 37 | return PA_VOLUME_MUTED; 38 | 39 | int64_t v_linear = lround(PA_VOLUME_NORM * cbrt(v)); 40 | assert(v_linear >= 0); 41 | 42 | return MIN(v_linear, PA_VOLUME_MAX); 43 | } 44 | 45 | APULSE_EXPORT 46 | double 47 | pa_sw_volume_to_linear(pa_volume_t v) 48 | { 49 | trace_info_f("F %s v=%u\n", __func__, v); 50 | 51 | uint32_t v_clamped = MIN(v, PA_VOLUME_MAX); 52 | 53 | double v_linear = v_clamped * (1.0 / PA_VOLUME_NORM); 54 | return v_linear * v_linear * v_linear; 55 | } 56 | 57 | APULSE_EXPORT 58 | char * 59 | pa_cvolume_snprint_verbose(char *s, size_t l, const pa_cvolume *c, 60 | const pa_channel_map *map, int print_dB) 61 | { 62 | trace_info_z("Z %s\n", __func__); 63 | return NULL; 64 | } 65 | 66 | APULSE_EXPORT 67 | char * 68 | pa_volume_snprint(char *s, size_t l, pa_volume_t v) 69 | { 70 | trace_info_z("Z %s\n", __func__); 71 | return NULL; 72 | } 73 | 74 | APULSE_EXPORT 75 | char * 76 | pa_sw_volume_snprint_dB(char *s, size_t l, pa_volume_t v) 77 | { 78 | trace_info_z("Z %s\n", __func__); 79 | return NULL; 80 | } 81 | 82 | APULSE_EXPORT 83 | char * 84 | pa_volume_snprint_verbose(char *s, size_t l, pa_volume_t v, int print_dB) 85 | { 86 | trace_info_z("Z %s\n", __func__); 87 | return NULL; 88 | } 89 | 90 | APULSE_EXPORT 91 | pa_volume_t 92 | pa_cvolume_avg_mask(const pa_cvolume *a, const pa_channel_map *cm, 93 | pa_channel_position_mask_t mask) 94 | { 95 | trace_info_z("Z %s\n", __func__); 96 | return 0; 97 | } 98 | 99 | APULSE_EXPORT 100 | pa_volume_t 101 | pa_cvolume_max(const pa_cvolume *a) 102 | { 103 | trace_info_z("Z %s\n", __func__); 104 | return 0; 105 | } 106 | 107 | APULSE_EXPORT 108 | pa_volume_t 109 | pa_cvolume_max_mask(const pa_cvolume *a, const pa_channel_map *cm, 110 | pa_channel_position_mask_t mask) 111 | { 112 | trace_info_z("Z %s\n", __func__); 113 | return 0; 114 | } 115 | 116 | APULSE_EXPORT 117 | pa_volume_t 118 | pa_cvolume_min(const pa_cvolume *a) 119 | { 120 | trace_info_z("Z %s\n", __func__); 121 | return 0; 122 | } 123 | 124 | APULSE_EXPORT 125 | pa_volume_t 126 | pa_cvolume_min_mask(const pa_cvolume *a, const pa_channel_map *cm, 127 | pa_channel_position_mask_t mask) 128 | { 129 | trace_info_z("Z %s\n", __func__); 130 | return 0; 131 | } 132 | 133 | APULSE_EXPORT 134 | int 135 | pa_cvolume_valid(const pa_cvolume *v) 136 | { 137 | trace_info_z("Z %s\n", __func__); 138 | return 0; 139 | } 140 | 141 | APULSE_EXPORT 142 | int 143 | pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) 144 | { 145 | trace_info_z("Z %s\n", __func__); 146 | return 0; 147 | } 148 | 149 | APULSE_EXPORT 150 | pa_volume_t 151 | pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) 152 | { 153 | trace_info_z("Z %s\n", __func__); 154 | return 0; 155 | } 156 | 157 | APULSE_EXPORT 158 | pa_cvolume * 159 | pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, 160 | const pa_cvolume *b) 161 | { 162 | trace_info_z("Z %s\n", __func__); 163 | return NULL; 164 | } 165 | 166 | APULSE_EXPORT 167 | pa_cvolume * 168 | pa_sw_cvolume_multiply_scalar(pa_cvolume *dest, const pa_cvolume *a, 169 | pa_volume_t b) 170 | { 171 | trace_info_z("Z %s\n", __func__); 172 | return NULL; 173 | } 174 | 175 | APULSE_EXPORT 176 | pa_volume_t 177 | pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) 178 | { 179 | trace_info_z("Z %s\n", __func__); 180 | return 0; 181 | } 182 | 183 | APULSE_EXPORT 184 | pa_cvolume * 185 | pa_sw_cvolume_divide(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) 186 | { 187 | trace_info_z("Z %s\n", __func__); 188 | return NULL; 189 | } 190 | 191 | APULSE_EXPORT 192 | pa_cvolume * 193 | pa_sw_cvolume_divide_scalar(pa_cvolume *dest, const pa_cvolume *a, 194 | pa_volume_t b) 195 | { 196 | trace_info_z("Z %s\n", __func__); 197 | return NULL; 198 | } 199 | 200 | APULSE_EXPORT 201 | pa_volume_t 202 | pa_sw_volume_from_dB(double f) 203 | { 204 | trace_info_z("Z %s\n", __func__); 205 | return 0; 206 | } 207 | 208 | APULSE_EXPORT 209 | double 210 | pa_sw_volume_to_dB(pa_volume_t v) 211 | { 212 | trace_info_z("Z %s\n", __func__); 213 | return 0.0; 214 | } 215 | 216 | APULSE_EXPORT 217 | pa_cvolume * 218 | pa_cvolume_remap(pa_cvolume *v, const pa_channel_map *from, 219 | const pa_channel_map *to) 220 | { 221 | trace_info_z("Z %s\n", __func__); 222 | return NULL; 223 | } 224 | 225 | APULSE_EXPORT 226 | int 227 | pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) 228 | { 229 | trace_info_z("Z %s\n", __func__); 230 | return 0; 231 | } 232 | 233 | APULSE_EXPORT 234 | int 235 | pa_cvolume_compatible_with_channel_map(const pa_cvolume *v, 236 | const pa_channel_map *cm) 237 | { 238 | trace_info_z("Z %s\n", __func__); 239 | return 0; 240 | } 241 | 242 | APULSE_EXPORT 243 | float 244 | pa_cvolume_get_balance(const pa_cvolume *v, const pa_channel_map *map) 245 | { 246 | trace_info_z("Z %s\n", __func__); 247 | return 0.0; 248 | } 249 | 250 | APULSE_EXPORT 251 | pa_cvolume * 252 | pa_cvolume_set_balance(pa_cvolume *v, const pa_channel_map *map, 253 | float new_balance) 254 | { 255 | trace_info_z("Z %s\n", __func__); 256 | return NULL; 257 | } 258 | 259 | APULSE_EXPORT 260 | float 261 | pa_cvolume_get_fade(const pa_cvolume *v, const pa_channel_map *map) 262 | { 263 | trace_info_z("Z %s\n", __func__); 264 | return 0.0; 265 | } 266 | 267 | APULSE_EXPORT 268 | pa_cvolume * 269 | pa_cvolume_set_fade(pa_cvolume *v, const pa_channel_map *map, float new_fade) 270 | { 271 | trace_info_z("Z %s\n", __func__); 272 | return NULL; 273 | } 274 | 275 | APULSE_EXPORT 276 | pa_cvolume * 277 | pa_cvolume_scale(pa_cvolume *v, pa_volume_t max) 278 | { 279 | trace_info_z("Z %s\n", __func__); 280 | return NULL; 281 | } 282 | 283 | APULSE_EXPORT 284 | pa_cvolume * 285 | #if PA_CHECK_VERSION(11, 99, 0) 286 | pa_cvolume_scale_mask(pa_cvolume *v, pa_volume_t max, const pa_channel_map *cm, 287 | pa_channel_position_mask_t mask) 288 | #else 289 | pa_cvolume_scale_mask(pa_cvolume *v, pa_volume_t max, pa_channel_map *cm, 290 | pa_channel_position_mask_t mask) 291 | #endif 292 | { 293 | trace_info_z("Z %s\n", __func__); 294 | return NULL; 295 | } 296 | 297 | APULSE_EXPORT 298 | pa_cvolume * 299 | pa_cvolume_set_position(pa_cvolume *cv, const pa_channel_map *map, 300 | pa_channel_position_t t, pa_volume_t v) 301 | { 302 | gchar *s_map = trace_pa_channel_map_as_string(map); 303 | gchar *s_t = trace_pa_channel_position_t_as_string(t); 304 | trace_info_z("Z %s cv=%p, map=%s, t=%s, v=%u\n", __func__, cv, s_map, s_t, 305 | v); 306 | g_free(s_t); 307 | g_free(s_map); 308 | 309 | return NULL; 310 | } 311 | 312 | APULSE_EXPORT 313 | pa_volume_t 314 | pa_cvolume_get_position(pa_cvolume *cv, const pa_channel_map *map, 315 | pa_channel_position_t t) 316 | { 317 | gchar *s_map = trace_pa_channel_map_as_string(map); 318 | gchar *s_t = trace_pa_channel_position_t_as_string(t); 319 | trace_info_z("Z %s cv=%p, map=%s, t=%s\n", __func__, cv, s_map, s_t); 320 | g_free(s_t); 321 | g_free(s_map); 322 | 323 | return 0; 324 | } 325 | 326 | APULSE_EXPORT 327 | pa_cvolume * 328 | pa_cvolume_merge(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) 329 | { 330 | trace_info_z("Z %s\n", __func__); 331 | return NULL; 332 | } 333 | 334 | APULSE_EXPORT 335 | pa_cvolume * 336 | pa_cvolume_inc_clamp(pa_cvolume *v, pa_volume_t inc, pa_volume_t limit) 337 | { 338 | trace_info_z("Z %s\n", __func__); 339 | return NULL; 340 | } 341 | 342 | APULSE_EXPORT 343 | pa_cvolume * 344 | pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc) 345 | { 346 | trace_info_z("Z %s\n", __func__); 347 | return NULL; 348 | } 349 | 350 | APULSE_EXPORT 351 | pa_cvolume * 352 | pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec) 353 | { 354 | trace_info_z("Z %s\n", __func__); 355 | return NULL; 356 | } 357 | 358 | APULSE_EXPORT 359 | int 360 | pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) 361 | { 362 | trace_info_z("Z %s\n", __func__); 363 | return 0; 364 | } 365 | 366 | APULSE_EXPORT 367 | pa_cvolume * 368 | pa_cvolume_init(pa_cvolume *a) 369 | { 370 | trace_info_z("Z %s\n", __func__); 371 | return NULL; 372 | } 373 | 374 | APULSE_EXPORT 375 | char * 376 | pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) 377 | { 378 | trace_info_z("Z %s\n", __func__); 379 | return NULL; 380 | } 381 | 382 | APULSE_EXPORT 383 | char * 384 | pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) 385 | { 386 | trace_info_z("Z %s\n", __func__); 387 | return NULL; 388 | } 389 | -------------------------------------------------------------------------------- /src/apulse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #define _GNU_SOURCE 28 | #include "ringbuffer.h" 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #define APULSE_EXPORT __attribute__((visibility("default"))) 36 | 37 | struct pa_context { 38 | pa_context_state_t state; 39 | pa_context_state_t new_state; 40 | pa_context_notify_cb_t state_cb; 41 | void *state_cb_userdata; 42 | pa_mainloop_api *mainloop_api; 43 | char *name; 44 | int ref_cnt; 45 | int next_stream_idx; 46 | GHashTable *streams_ht; 47 | pa_volume_t source_volume[PA_CHANNELS_MAX]; 48 | }; 49 | 50 | struct pa_io_event { 51 | int fd; 52 | pa_io_event_flags_t events; 53 | pa_io_event_cb_t cb; 54 | void *cb_userdata; 55 | pa_io_event_destroy_cb_t destroy_cb; 56 | pa_mainloop *mainloop; 57 | struct pollfd *pollfd; 58 | snd_pcm_t *pcm; 59 | }; 60 | 61 | struct pa_mainloop { 62 | pa_mainloop_api api; 63 | GQueue *deferred_events_queue; 64 | GQueue *timed_events_queue; 65 | GHashTable *events_ht; ///< a set of (pa_io_event *) 66 | struct pollfd *fds; 67 | nfds_t nfds; 68 | int recreate_fds; ///< 1 if fds array needs to be recreated from events_ht 69 | int timeout; 70 | int wakeup_pipe[2]; 71 | int terminate; 72 | int retval; 73 | pa_poll_func poll_func; 74 | void *poll_func_userdata; 75 | int alsa_special_cnt; 76 | }; 77 | 78 | struct pa_glib_mainloop { 79 | pa_mainloop_api api; 80 | }; 81 | 82 | struct pa_threaded_mainloop { 83 | pa_mainloop *m; 84 | pthread_mutex_t lock; 85 | pthread_cond_t cond; 86 | pthread_t t; 87 | int running; 88 | }; 89 | 90 | struct pa_proplist { 91 | GHashTable *ht; 92 | }; 93 | 94 | struct pa_stream { 95 | pa_context *c; 96 | pa_stream_state_t state; 97 | pa_stream_direction_t direction; 98 | snd_pcm_t *ph; 99 | pa_sample_spec ss; 100 | pa_buffer_attr buffer_attr; 101 | int ref_cnt; 102 | int idx; 103 | pa_stream_notify_cb_t state_cb; 104 | void *state_cb_userdata; 105 | pa_stream_request_cb_t write_cb; 106 | void *write_cb_userdata; 107 | pa_stream_request_cb_t read_cb; 108 | void *read_cb_userdata; 109 | pa_stream_notify_cb_t latency_update_cb; 110 | void *latency_update_cb_userdata; 111 | char *name; 112 | pa_timing_info timing_info; 113 | pa_io_event **ioe; ///< list of pa_io_events 114 | int nioe; ///< count of pa_io_events 115 | ringbuffer_t *rb; 116 | void *peek_buffer; 117 | size_t peek_buffer_data_len; 118 | void *write_buffer; 119 | volatile int paused; 120 | pa_volume_t volume[PA_CHANNELS_MAX]; 121 | }; 122 | 123 | struct pa_operation { 124 | pa_operation_state_t state; 125 | pa_stream_success_cb_t stream_success_cb; 126 | pa_sink_input_info_cb_t sink_input_info_cb; 127 | pa_sink_info_cb_t sink_info_cb; 128 | pa_context_success_cb_t context_success_cb; 129 | pa_server_info_cb_t server_info_cb; 130 | pa_source_info_cb_t source_info_cb; 131 | void *cb_userdata; 132 | 133 | pa_mainloop_api *api; 134 | 135 | void (*mainloop_api_once_cb)(pa_mainloop_api *m, void *userdata); 136 | 137 | void (*handler)(pa_operation *op); 138 | 139 | int ref_cnt; 140 | int int_arg_1; 141 | char *char_ptr_arg_1; 142 | 143 | pa_cvolume pa_cvolume_arg_1; 144 | 145 | pa_stream *s; 146 | pa_context *c; 147 | }; 148 | 149 | struct pa_defer_event { 150 | int enabled; 151 | pa_defer_event_cb_t cb; 152 | void *userdata; 153 | pa_mainloop *mainloop; 154 | }; 155 | 156 | struct pa_time_event { 157 | int enabled; 158 | struct timeval when; 159 | pa_time_event_cb_t cb; 160 | void *userdata; 161 | pa_mainloop *mainloop; 162 | pa_time_event_destroy_cb_t destroy_cb; 163 | }; 164 | 165 | struct pa_simple { 166 | pa_context *context; 167 | pa_threaded_mainloop *mainloop; 168 | pa_stream *stream; 169 | pa_stream_direction_t direction; 170 | int initialized; 171 | }; 172 | 173 | pa_operation * 174 | pa_operation_new(pa_mainloop_api *api, void (*handler)(pa_operation *op)); 175 | 176 | void 177 | pa_operation_launch(pa_operation *op); 178 | 179 | void 180 | pa_operation_done(pa_operation *op); 181 | -------------------------------------------------------------------------------- /src/apulse.template: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | APULSEPATH="@APULSE_SEARCH_PATHS@" 4 | 5 | LD_LIBRARY_PATH=$APULSEPATH${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} exec "$@" 6 | -------------------------------------------------------------------------------- /src/ringbuffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "ringbuffer.h" 26 | #include 27 | #include 28 | 29 | static inline void 30 | _rb_lock(ringbuffer_t *rb) 31 | { 32 | pthread_mutex_lock(&rb->lock); 33 | } 34 | 35 | static inline void 36 | _rb_unlock(ringbuffer_t *rb) 37 | { 38 | pthread_mutex_unlock(&rb->lock); 39 | } 40 | 41 | ringbuffer_t * 42 | ringbuffer_new(size_t sz) 43 | { 44 | ringbuffer_t *rb = malloc(sizeof(*rb)); 45 | 46 | rb->start = malloc(sz); 47 | rb->end = rb->start + sz; 48 | rb->rpos = rb->start; 49 | rb->wpos = rb->start; 50 | rb->empty = 1; 51 | pthread_mutex_init(&rb->lock, NULL); 52 | 53 | return rb; 54 | } 55 | 56 | void 57 | ringbuffer_free(ringbuffer_t *rb) 58 | { 59 | pthread_mutex_destroy(&rb->lock); 60 | free(rb->start); 61 | free(rb); 62 | } 63 | 64 | static size_t 65 | _ringbuffer_readable_size(ringbuffer_t *rb) 66 | { 67 | if (rb->wpos > rb->rpos) { 68 | return rb->wpos - rb->rpos; 69 | } else if (rb->wpos < rb->rpos) { 70 | return (rb->end - rb->rpos) + (rb->wpos - rb->start); 71 | } else { 72 | // wpos == rpos 73 | if (rb->empty) 74 | return 0; 75 | else 76 | return rb->end - rb->start; 77 | } 78 | } 79 | 80 | size_t 81 | ringbuffer_readable_size(ringbuffer_t *rb) 82 | { 83 | size_t rsz; 84 | 85 | _rb_lock(rb); 86 | rsz = _ringbuffer_readable_size(rb); 87 | _rb_unlock(rb); 88 | 89 | return rsz; 90 | } 91 | 92 | static size_t 93 | _ringbuffer_writable_size(ringbuffer_t *rb) 94 | { 95 | if (rb->wpos > rb->rpos) { 96 | return (rb->end - rb->wpos) + (rb->rpos - rb->start); 97 | } else if (rb->wpos < rb->rpos) { 98 | return rb->rpos - rb->wpos; 99 | } else { 100 | // wpos == rpos 101 | if (rb->empty) 102 | return rb->end - rb->start; 103 | else 104 | return 0; 105 | } 106 | } 107 | 108 | size_t 109 | ringbuffer_writable_size(ringbuffer_t *rb) 110 | { 111 | size_t wsz; 112 | 113 | _rb_lock(rb); 114 | wsz = _ringbuffer_writable_size(rb); 115 | _rb_unlock(rb); 116 | 117 | return wsz; 118 | } 119 | 120 | size_t 121 | ringbuffer_write(ringbuffer_t *rb, const void *data, size_t len) 122 | { 123 | _rb_lock(rb); 124 | 125 | size_t remsz = rb->end - rb->wpos; 126 | size_t writable_size = _ringbuffer_writable_size(rb); 127 | 128 | if (len > writable_size) 129 | len = writable_size; 130 | 131 | if (len <= remsz) { 132 | memcpy(rb->wpos, data, len); 133 | rb->wpos += len; 134 | } else { 135 | memcpy(rb->wpos, data, remsz); 136 | memcpy(rb->start, (char *)data + remsz, len - remsz); 137 | rb->wpos = rb->start + len - remsz; 138 | } 139 | 140 | if (len > 0) 141 | rb->empty = 0; 142 | 143 | _rb_unlock(rb); 144 | return len; 145 | } 146 | 147 | size_t 148 | ringbuffer_read(ringbuffer_t *rb, void *data, size_t len) 149 | { 150 | _rb_lock(rb); 151 | 152 | size_t remsz = rb->end - rb->rpos; 153 | size_t readable_size = _ringbuffer_readable_size(rb); 154 | 155 | if (len > readable_size) 156 | len = readable_size; 157 | 158 | if (len <= remsz) { 159 | memcpy(data, rb->rpos, len); 160 | rb->rpos += len; 161 | } else { 162 | memcpy(data, rb->rpos, remsz); 163 | memcpy((char *)data + remsz, rb->start, len - remsz); 164 | rb->rpos = rb->start + len - remsz; 165 | } 166 | 167 | if (rb->rpos == rb->wpos) 168 | rb->empty = 1; 169 | 170 | _rb_unlock(rb); 171 | return len; 172 | } 173 | 174 | size_t 175 | ringbuffer_peek(ringbuffer_t *rb, void *data, size_t len) 176 | { 177 | _rb_lock(rb); 178 | 179 | size_t remsz = rb->end - rb->rpos; 180 | size_t readable_size = _ringbuffer_readable_size(rb); 181 | 182 | if (len > readable_size) 183 | len = readable_size; 184 | 185 | if (len <= remsz) { 186 | memcpy(data, rb->rpos, len); 187 | } else { 188 | memcpy(data, rb->rpos, remsz); 189 | memcpy((char *)data + remsz, rb->start, len - remsz); 190 | } 191 | 192 | _rb_unlock(rb); 193 | return len; 194 | } 195 | 196 | size_t 197 | ringbuffer_drop(ringbuffer_t *rb, size_t len) 198 | { 199 | _rb_lock(rb); 200 | 201 | size_t remsz = rb->end - rb->rpos; 202 | size_t readable_size = _ringbuffer_readable_size(rb); 203 | 204 | if (len > readable_size) 205 | len = readable_size; 206 | 207 | if (len <= remsz) { 208 | rb->rpos += len; 209 | } else { 210 | rb->rpos = rb->start + len - remsz; 211 | } 212 | 213 | if (rb->rpos == rb->wpos) 214 | rb->empty = 1; 215 | 216 | _rb_unlock(rb); 217 | return len; 218 | } 219 | -------------------------------------------------------------------------------- /src/ringbuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | typedef struct { 30 | char *start; 31 | char *end; 32 | char *rpos; 33 | char *wpos; 34 | pthread_mutex_t lock; 35 | int empty; 36 | } ringbuffer_t; 37 | 38 | ringbuffer_t * 39 | ringbuffer_new(size_t sz); 40 | 41 | void 42 | ringbuffer_free(ringbuffer_t *rb); 43 | 44 | size_t 45 | ringbuffer_readable_size(ringbuffer_t *rb); 46 | 47 | size_t 48 | ringbuffer_writable_size(ringbuffer_t *rb); 49 | 50 | size_t 51 | ringbuffer_write(ringbuffer_t *rb, const void *data, size_t len); 52 | 53 | size_t 54 | ringbuffer_read(ringbuffer_t *rb, void *data, size_t len); 55 | 56 | /** get data from ring buffer without advancing read pointer */ 57 | size_t 58 | ringbuffer_peek(ringbuffer_t *rb, void *data, size_t len); 59 | 60 | size_t 61 | ringbuffer_drop(ringbuffer_t *rb, size_t len); 62 | -------------------------------------------------------------------------------- /src/symbolmap: -------------------------------------------------------------------------------- 1 | PULSE_0 { 2 | global: 3 | pa_*; 4 | local: 5 | *; 6 | }; 7 | -------------------------------------------------------------------------------- /src/trace.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "trace.h" 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 33 | 34 | #if CONFIG_LOG_TO_STDERR 35 | static int log_to_stderr = 1; 36 | #else 37 | static int log_to_stderr = 0; 38 | #endif // CONFIG_LOG_TO_STDERR 39 | 40 | void 41 | trace_info(const char *fmt, ...) 42 | { 43 | FILE *fp = log_to_stderr ? stderr : stdout; 44 | pthread_mutex_lock(&lock); 45 | va_list args; 46 | struct timeval tv; 47 | gettimeofday(&tv, NULL); 48 | fprintf(fp, "%d.%03d [apulse %5d] ", (int)tv.tv_sec, 49 | (int)tv.tv_usec / 1000, (int)syscall(__NR_gettid)); 50 | va_start(args, fmt); 51 | vfprintf(fp, fmt, args); 52 | va_end(args); 53 | pthread_mutex_unlock(&lock); 54 | } 55 | 56 | void 57 | trace_warning(const char *fmt, ...) 58 | { 59 | FILE *fp = log_to_stderr ? stderr : stdout; 60 | pthread_mutex_lock(&lock); 61 | va_list args; 62 | fprintf(fp, "[apulse] [warning] "); 63 | va_start(args, fmt); 64 | vfprintf(fp, fmt, args); 65 | va_end(args); 66 | pthread_mutex_unlock(&lock); 67 | } 68 | 69 | void 70 | trace_error(const char *fmt, ...) 71 | { 72 | static int stdout_tested = 0; 73 | static int stdout_is_a_tty = 0; 74 | 75 | pthread_mutex_lock(&lock); 76 | 77 | if (!stdout_tested) { 78 | stdout_is_a_tty = isatty(1); 79 | stdout_tested = 1; 80 | } 81 | 82 | va_list args; 83 | fprintf(stderr, "[apulse] [error] "); 84 | va_start(args, fmt); 85 | vfprintf(stderr, fmt, args); 86 | va_end(args); 87 | 88 | if (!log_to_stderr && !stdout_is_a_tty) { 89 | // Send a copy to stdout, if it's redirected to a file. 90 | fprintf(stdout, "[apulse] [error] "); 91 | va_start(args, fmt); 92 | vfprintf(stdout, fmt, args); 93 | va_end(args); 94 | } 95 | 96 | pthread_mutex_unlock(&lock); 97 | } 98 | 99 | gchar * 100 | trace_pa_buffer_attr_as_string(const pa_buffer_attr *attr) 101 | { 102 | gchar *res; 103 | if (attr) { 104 | res = g_strdup_printf( 105 | "{.maxlength=%u, .tlength=%u, .prebuf=%u, .minreq=%u, " 106 | ".fragsize=%u}", 107 | attr->maxlength, attr->tlength, attr->prebuf, attr->minreq, 108 | attr->fragsize); 109 | } else { 110 | res = g_strdup_printf("(nil)"); 111 | } 112 | 113 | return res; 114 | } 115 | 116 | gchar * 117 | trace_pa_volume_as_string(const pa_cvolume *v) 118 | { 119 | const unsigned int channel_count = MIN(v->channels, PA_CHANNELS_MAX); 120 | GString *s = g_string_new(NULL); 121 | 122 | g_string_append_printf(s, "%d:{", v->channels); 123 | for (unsigned int k = 0; k < channel_count; k++) { 124 | if (k != 0) 125 | g_string_append(s, ", "); 126 | 127 | g_string_append_printf(s, "%u", v->values[k]); 128 | } 129 | 130 | g_string_append(s, "}"); 131 | 132 | return g_string_free(s, FALSE); 133 | } 134 | 135 | gchar * 136 | trace_pa_channel_position_t_as_string(const pa_channel_position_t pos) 137 | { 138 | const char *s_pos; 139 | 140 | switch (pos) { 141 | case PA_CHANNEL_POSITION_INVALID: 142 | s_pos = "INVALID"; 143 | break; 144 | 145 | case PA_CHANNEL_POSITION_MONO: 146 | s_pos = "MONO"; 147 | break; 148 | 149 | case PA_CHANNEL_POSITION_FRONT_LEFT: 150 | s_pos = "FRONT_LEFT"; 151 | break; 152 | 153 | case PA_CHANNEL_POSITION_FRONT_RIGHT: 154 | s_pos = "FRONT_RIGHT"; 155 | break; 156 | 157 | case PA_CHANNEL_POSITION_FRONT_CENTER: 158 | s_pos = "FRONT_CENTER"; 159 | break; 160 | 161 | case PA_CHANNEL_POSITION_REAR_CENTER: 162 | s_pos = "REAR_CENTER"; 163 | break; 164 | 165 | case PA_CHANNEL_POSITION_REAR_LEFT: 166 | s_pos = "REAR_LEFT"; 167 | break; 168 | 169 | case PA_CHANNEL_POSITION_REAR_RIGHT: 170 | s_pos = "REAR_RIGHT"; 171 | break; 172 | 173 | case PA_CHANNEL_POSITION_LFE: 174 | s_pos = "LFE"; 175 | break; 176 | 177 | case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: 178 | s_pos = "FRONT_LEFT_OF_CENTER"; 179 | break; 180 | 181 | case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: 182 | s_pos = "FRONT_RIGHT_OF_CENTER"; 183 | break; 184 | 185 | case PA_CHANNEL_POSITION_SIDE_LEFT: 186 | s_pos = "SIDE_LEFT"; 187 | break; 188 | 189 | case PA_CHANNEL_POSITION_SIDE_RIGHT: 190 | s_pos = "SIDE_RIGHT"; 191 | break; 192 | 193 | case PA_CHANNEL_POSITION_AUX0: 194 | s_pos = "AUX0"; 195 | break; 196 | 197 | case PA_CHANNEL_POSITION_AUX1: 198 | s_pos = "AUX1"; 199 | break; 200 | 201 | case PA_CHANNEL_POSITION_AUX2: 202 | s_pos = "AUX2"; 203 | break; 204 | 205 | case PA_CHANNEL_POSITION_AUX3: 206 | s_pos = "AUX3"; 207 | break; 208 | 209 | case PA_CHANNEL_POSITION_AUX4: 210 | s_pos = "AUX4"; 211 | break; 212 | 213 | case PA_CHANNEL_POSITION_AUX5: 214 | s_pos = "AUX5"; 215 | break; 216 | 217 | case PA_CHANNEL_POSITION_AUX6: 218 | s_pos = "AUX6"; 219 | break; 220 | 221 | case PA_CHANNEL_POSITION_AUX7: 222 | s_pos = "AUX7"; 223 | break; 224 | 225 | case PA_CHANNEL_POSITION_AUX8: 226 | s_pos = "AUX8"; 227 | break; 228 | 229 | case PA_CHANNEL_POSITION_AUX9: 230 | s_pos = "AUX9"; 231 | break; 232 | 233 | case PA_CHANNEL_POSITION_AUX10: 234 | s_pos = "AUX10"; 235 | break; 236 | 237 | case PA_CHANNEL_POSITION_AUX11: 238 | s_pos = "AUX11"; 239 | break; 240 | 241 | case PA_CHANNEL_POSITION_AUX12: 242 | s_pos = "AUX12"; 243 | break; 244 | 245 | case PA_CHANNEL_POSITION_AUX13: 246 | s_pos = "AUX13"; 247 | break; 248 | 249 | case PA_CHANNEL_POSITION_AUX14: 250 | s_pos = "AUX14"; 251 | break; 252 | 253 | case PA_CHANNEL_POSITION_AUX15: 254 | s_pos = "AUX15"; 255 | break; 256 | 257 | case PA_CHANNEL_POSITION_AUX16: 258 | s_pos = "AUX16"; 259 | break; 260 | 261 | case PA_CHANNEL_POSITION_AUX17: 262 | s_pos = "AUX17"; 263 | break; 264 | 265 | case PA_CHANNEL_POSITION_AUX18: 266 | s_pos = "AUX18"; 267 | break; 268 | 269 | case PA_CHANNEL_POSITION_AUX19: 270 | s_pos = "AUX19"; 271 | break; 272 | 273 | case PA_CHANNEL_POSITION_AUX20: 274 | s_pos = "AUX20"; 275 | break; 276 | 277 | case PA_CHANNEL_POSITION_AUX21: 278 | s_pos = "AUX21"; 279 | break; 280 | 281 | case PA_CHANNEL_POSITION_AUX22: 282 | s_pos = "AUX22"; 283 | break; 284 | 285 | case PA_CHANNEL_POSITION_AUX23: 286 | s_pos = "AUX23"; 287 | break; 288 | 289 | case PA_CHANNEL_POSITION_AUX24: 290 | s_pos = "AUX24"; 291 | break; 292 | 293 | case PA_CHANNEL_POSITION_AUX25: 294 | s_pos = "AUX25"; 295 | break; 296 | 297 | case PA_CHANNEL_POSITION_AUX26: 298 | s_pos = "AUX26"; 299 | break; 300 | 301 | case PA_CHANNEL_POSITION_AUX27: 302 | s_pos = "AUX27"; 303 | break; 304 | 305 | case PA_CHANNEL_POSITION_AUX28: 306 | s_pos = "AUX28"; 307 | break; 308 | 309 | case PA_CHANNEL_POSITION_AUX29: 310 | s_pos = "AUX29"; 311 | break; 312 | 313 | case PA_CHANNEL_POSITION_AUX30: 314 | s_pos = "AUX30"; 315 | break; 316 | 317 | case PA_CHANNEL_POSITION_AUX31: 318 | s_pos = "AUX31"; 319 | break; 320 | 321 | case PA_CHANNEL_POSITION_TOP_CENTER: 322 | s_pos = "TOP_CENTER"; 323 | break; 324 | 325 | case PA_CHANNEL_POSITION_TOP_FRONT_LEFT: 326 | s_pos = "TOP_FRONT_LEFT"; 327 | break; 328 | 329 | case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT: 330 | s_pos = "TOP_FRONT_RIGHT"; 331 | break; 332 | 333 | case PA_CHANNEL_POSITION_TOP_FRONT_CENTER: 334 | s_pos = "TOP_FRONT_CENTER"; 335 | break; 336 | 337 | case PA_CHANNEL_POSITION_TOP_REAR_LEFT: 338 | s_pos = "TOP_REAR_LEFT"; 339 | break; 340 | 341 | case PA_CHANNEL_POSITION_TOP_REAR_RIGHT: 342 | s_pos = "TOP_REAR_RIGHT"; 343 | break; 344 | 345 | case PA_CHANNEL_POSITION_TOP_REAR_CENTER: 346 | s_pos = "TOP_REAR_CENTER"; 347 | break; 348 | 349 | case PA_CHANNEL_POSITION_MAX: 350 | s_pos = "MAX"; 351 | break; 352 | 353 | default: 354 | s_pos = "UNKNOWN"; 355 | break; 356 | } 357 | 358 | return g_strdup_printf("%s(%d)", s_pos, pos); 359 | } 360 | 361 | gchar * 362 | trace_pa_channel_map_as_string(const pa_channel_map *m) 363 | { 364 | if (!m) 365 | return g_strdup("(nil)"); 366 | 367 | GString *s = g_string_new(NULL); 368 | 369 | g_string_append_printf(s, "%u:{", m->channels); 370 | 371 | const unsigned int channel_count = MIN(m->channels, PA_CHANNELS_MAX); 372 | for (unsigned int k = 0; k < channel_count; k++) { 373 | if (k != 0) 374 | g_string_append(s, ","); 375 | gchar *s_channel_pos = trace_pa_channel_position_t_as_string(m->map[k]); 376 | g_string_append(s, s_channel_pos); 377 | g_free(s_channel_pos); 378 | } 379 | 380 | g_string_append(s, "}"); 381 | 382 | return g_string_free(s, FALSE); 383 | } 384 | 385 | gchar * 386 | trace_pa_sample_format_t_as_string(pa_sample_format_t sf) 387 | { 388 | const char *fmt; 389 | switch (sf) { 390 | case PA_SAMPLE_U8: 391 | fmt = "U8"; 392 | break; 393 | 394 | case PA_SAMPLE_ALAW: 395 | fmt = "ALAW"; 396 | break; 397 | 398 | case PA_SAMPLE_ULAW: 399 | fmt = "ULAW"; 400 | break; 401 | 402 | case PA_SAMPLE_S16LE: 403 | fmt = "S16LE"; 404 | break; 405 | 406 | case PA_SAMPLE_S16BE: 407 | fmt = "S16BE"; 408 | break; 409 | 410 | case PA_SAMPLE_FLOAT32LE: 411 | fmt = "FLOAT32LE"; 412 | break; 413 | 414 | case PA_SAMPLE_FLOAT32BE: 415 | fmt = "FLOAT32BE"; 416 | break; 417 | 418 | case PA_SAMPLE_S32LE: 419 | fmt = "S32LE"; 420 | break; 421 | 422 | case PA_SAMPLE_S32BE: 423 | fmt = "S32BE"; 424 | break; 425 | 426 | case PA_SAMPLE_S24LE: 427 | fmt = "S24LE"; 428 | break; 429 | 430 | case PA_SAMPLE_S24BE: 431 | fmt = "S24BE"; 432 | break; 433 | 434 | case PA_SAMPLE_S24_32LE: 435 | fmt = "S24_32LE"; 436 | break; 437 | 438 | case PA_SAMPLE_S24_32BE: 439 | fmt = "S24_32BE"; 440 | break; 441 | 442 | case PA_SAMPLE_MAX: 443 | fmt = "MAX"; 444 | break; 445 | 446 | case PA_SAMPLE_INVALID: 447 | fmt = "INVALID"; 448 | break; 449 | 450 | default: 451 | fmt = "UNKNOWN"; 452 | break; 453 | } 454 | 455 | return g_strdup_printf("%s(%d)", fmt, sf); 456 | } 457 | 458 | gchar * 459 | trace_pa_sample_spec_as_string(const pa_sample_spec *ss) 460 | { 461 | if (!ss) 462 | return g_strdup("(nil)"); 463 | 464 | gchar *s_format = trace_pa_sample_format_t_as_string(ss->format); 465 | gchar *str = g_strdup_printf("{.format=%s,.rate=%u,.channels=%u}", s_format, 466 | ss->rate, ss->channels); 467 | g_free(s_format); 468 | 469 | return str; 470 | } 471 | -------------------------------------------------------------------------------- /src/trace.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #if CONFIG_TRACE_LEVEL >= 2 32 | 33 | #define trace_info_f(...) trace_info(__VA_ARGS__) 34 | #define trace_info_z(...) trace_info(__VA_ARGS__) 35 | 36 | #elif CONFIG_TRACE_LEVEL == 1 37 | 38 | #define trace_info_f(...) 39 | #define trace_info_z(...) trace_info(__VA_ARGS__) 40 | 41 | #else // CONFIG_TRACE_LEVEL == 0 42 | 43 | #define trace_info_f(...) 44 | #define trace_info_z(...) 45 | 46 | #endif 47 | 48 | void 49 | trace_info(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 50 | 51 | void 52 | trace_warning(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 53 | 54 | void 55 | trace_error(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 56 | 57 | gchar * 58 | trace_pa_buffer_attr_as_string(const pa_buffer_attr *attr); 59 | 60 | gchar * 61 | trace_pa_volume_as_string(const pa_cvolume *v); 62 | 63 | gchar * 64 | trace_pa_channel_position_t_as_string(const pa_channel_position_t pos); 65 | 66 | gchar * 67 | trace_pa_channel_map_as_string(const pa_channel_map *m); 68 | 69 | gchar * 70 | trace_pa_sample_format_t_as_string(pa_sample_format_t sf); 71 | 72 | gchar * 73 | trace_pa_sample_spec_as_string(const pa_sample_spec *ss); 74 | -------------------------------------------------------------------------------- /src/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "trace.h" 26 | #include "util.h" 27 | 28 | int 29 | pa_format_to_alsa(pa_sample_format_t format) 30 | { 31 | switch (format) { 32 | case PA_SAMPLE_U8: 33 | return SND_PCM_FORMAT_U8; 34 | case PA_SAMPLE_ALAW: 35 | return SND_PCM_FORMAT_A_LAW; 36 | case PA_SAMPLE_ULAW: 37 | return SND_PCM_FORMAT_MU_LAW; 38 | case PA_SAMPLE_S16LE: 39 | return SND_PCM_FORMAT_S16_LE; 40 | case PA_SAMPLE_S16BE: 41 | return SND_PCM_FORMAT_S16_BE; 42 | case PA_SAMPLE_FLOAT32LE: 43 | return SND_PCM_FORMAT_FLOAT_LE; 44 | case PA_SAMPLE_FLOAT32BE: 45 | return SND_PCM_FORMAT_FLOAT_BE; 46 | case PA_SAMPLE_S32LE: 47 | return SND_PCM_FORMAT_S32_LE; 48 | case PA_SAMPLE_S32BE: 49 | return SND_PCM_FORMAT_S32_BE; 50 | case PA_SAMPLE_S24LE: 51 | return SND_PCM_FORMAT_S24_3LE; 52 | case PA_SAMPLE_S24BE: 53 | return SND_PCM_FORMAT_S24_3BE; 54 | case PA_SAMPLE_S24_32LE: 55 | return SND_PCM_FORMAT_S24_LE; 56 | case PA_SAMPLE_S24_32BE: 57 | return SND_PCM_FORMAT_S24_BE; 58 | default: 59 | return SND_PCM_FORMAT_UNKNOWN; 60 | } 61 | } 62 | 63 | pa_sample_format_t 64 | pa_sample_format_from_string(const char *str) 65 | { 66 | if (!str) 67 | return 0; 68 | 69 | if (strcmp(str, "u8") == 0) { 70 | return PA_SAMPLE_U8; 71 | } else if (strcmp(str, "aLaw") == 0) { 72 | return PA_SAMPLE_ALAW; 73 | } else if (strcmp(str, "uLaw") == 0) { 74 | return PA_SAMPLE_ULAW; 75 | } else if (strcmp(str, "s16le") == 0) { 76 | return PA_SAMPLE_S16LE; 77 | } else if (strcmp(str, "s16be") == 0) { 78 | return PA_SAMPLE_S16BE; 79 | } else if (strcmp(str, "float32le") == 0) { 80 | return PA_SAMPLE_FLOAT32LE; 81 | } else if (strcmp(str, "float32be") == 0) { 82 | return PA_SAMPLE_FLOAT32BE; 83 | } else if (strcmp(str, "s32le") == 0) { 84 | return PA_SAMPLE_S32LE; 85 | } else if (strcmp(str, "s32be") == 0) { 86 | return PA_SAMPLE_S32BE; 87 | } else if (strcmp(str, "s24le") == 0) { 88 | return PA_SAMPLE_S24LE; 89 | } else if (strcmp(str, "s24be") == 0) { 90 | return PA_SAMPLE_S24BE; 91 | } else if (strcmp(str, "s24-32le") == 0) { 92 | return PA_SAMPLE_S24_32LE; 93 | } else if (strcmp(str, "s24-32be") == 0) { 94 | return PA_SAMPLE_S24_32BE; 95 | } else { 96 | return 0; 97 | } 98 | } 99 | 100 | size_t 101 | pa_find_multiple_of(size_t number, size_t multiple_of, 102 | int towards_larger_numbers) 103 | { 104 | if (multiple_of == 0) 105 | return number; 106 | 107 | size_t n = towards_larger_numbers ? (number + multiple_of - 1) : number; 108 | return n - (n % multiple_of); 109 | } 110 | 111 | void 112 | pa_apply_volume_multiplier(void *buf, size_t sz, 113 | const pa_volume_t volume[PA_CHANNELS_MAX], 114 | const pa_sample_spec *ss) 115 | { 116 | char *p = buf; 117 | char *last = p + sz; 118 | float fvol[PA_CHANNELS_MAX]; 119 | uint32_t channels = MIN(ss->channels, PA_CHANNELS_MAX); 120 | 121 | if (channels == 0) { 122 | // No channels — nothing to scale. 123 | return; 124 | } 125 | 126 | int all_normal = 1; 127 | for (uint32_t k = 0; k < channels; k++) 128 | all_normal = all_normal && (volume[k] == PA_VOLUME_NORM); 129 | 130 | if (all_normal) { 131 | // No scaling required. 132 | return; 133 | } 134 | 135 | for (uint32_t k = 0; k < channels; k++) 136 | fvol[k] = pa_sw_volume_to_linear(volume[k]); 137 | 138 | switch (ss->format) { 139 | case PA_SAMPLE_FLOAT32NE: 140 | while (p < last) { 141 | for (uint32_t k = 0; k < channels && p < last; k++) { 142 | float sample; 143 | memcpy(&sample, p, sizeof(sample)); 144 | sample *= fvol[k]; 145 | memcpy(p, &sample, sizeof(sample)); 146 | p += sizeof(sample); 147 | } 148 | } 149 | break; 150 | 151 | case PA_SAMPLE_S16NE: 152 | while (p < last) { 153 | for (uint32_t k = 0; k < channels && p < last; k++) { 154 | int16_t sample; 155 | memcpy(&sample, p, sizeof(sample)); 156 | float sample_scaled = sample * fvol[k]; 157 | sample = CLAMP(sample_scaled, -32768.0, 32767.0); 158 | memcpy(p, &sample, sizeof(sample)); 159 | p += sizeof(sample); 160 | } 161 | } 162 | break; 163 | 164 | case PA_SAMPLE_U8: 165 | case PA_SAMPLE_ALAW: 166 | case PA_SAMPLE_ULAW: 167 | case PA_SAMPLE_S16RE: 168 | case PA_SAMPLE_FLOAT32RE: 169 | case PA_SAMPLE_S32NE: 170 | case PA_SAMPLE_S32RE: 171 | case PA_SAMPLE_S24NE: 172 | case PA_SAMPLE_S24RE: 173 | case PA_SAMPLE_S24_32NE: 174 | case PA_SAMPLE_S24_32RE: 175 | default: 176 | trace_error("format %s is not implemented in %s\n", 177 | pa_sample_format_to_string(ss->format), __func__); 178 | break; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014-2018 Rinat Ibragimov 3 | * 4 | * This file is part of "apulse" project. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | int 31 | pa_format_to_alsa(pa_sample_format_t format); 32 | 33 | pa_sample_format_t 34 | pa_sample_format_from_string(const char *str); 35 | 36 | /// finds largest number that is less or equal than |number| and multiple of 37 | /// |multiple_of|. 38 | size_t 39 | pa_find_multiple_of(size_t number, size_t multiple_of, 40 | int towards_larger_numbers); 41 | 42 | void 43 | pa_apply_volume_multiplier(void *buf, size_t sz, 44 | const pa_volume_t volume[PA_CHANNELS_MAX], 45 | const pa_sample_spec *ss); 46 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | enable_testing() 2 | add_custom_target(check COMMAND "${CMAKE_CTEST_COMMAND}") 3 | 4 | set(test_list 5 | test_ringbuffer 6 | ) 7 | link_directories(${REQ_LIBRARY_DIRS}) 8 | 9 | # simplify inclusion of .c sources 10 | include_directories(..) 11 | 12 | foreach(item ${test_list}) 13 | add_executable(${item} EXCLUDE_FROM_ALL 14 | ${item}.c 15 | ) 16 | target_link_libraries(${item} 17 | "-Wl,-z,muldefs" 18 | dl 19 | ${REQ_LIBRARIES}) 20 | add_test(${item} ${item}) 21 | add_dependencies(check ${item}) 22 | endforeach() 23 | -------------------------------------------------------------------------------- /tests/test_ringbuffer.c: -------------------------------------------------------------------------------- 1 | #undef NDEBUG 2 | #include 3 | #include 4 | #include 5 | 6 | int 7 | main(void) 8 | { 9 | ringbuffer_t *rb = ringbuffer_new(16); 10 | char buf[20]; 11 | 12 | // check initial state 13 | assert(rb); 14 | assert(ringbuffer_readable_size(rb) == 0); 15 | assert(ringbuffer_writable_size(rb) == 16); 16 | 17 | // check for reading from empty buffer 18 | assert(ringbuffer_read(rb, buf, sizeof(buf)) == 0); 19 | 20 | // write some data 21 | assert(ringbuffer_write(rb, "hello", 5) == 5); 22 | assert(ringbuffer_readable_size(rb) == 5); 23 | assert(ringbuffer_writable_size(rb) == 11); 24 | 25 | // read that data 26 | assert(ringbuffer_read(rb, buf, sizeof(buf)) == 5); 27 | assert(memcmp(buf, "hello", 5) == 0); 28 | 29 | // test wrapping 30 | assert(ringbuffer_write(rb, "0123456789abcdef", 16) == 16); 31 | assert(ringbuffer_readable_size(rb) == 16); 32 | assert(ringbuffer_writable_size(rb) == 0); 33 | 34 | // reading of wrapped data in two chunks 35 | assert(ringbuffer_read(rb, buf, 15) == 15); 36 | assert(memcmp(buf, "0123456789abcde", 15) == 0); 37 | assert(ringbuffer_read(rb, buf, 15) == 1); 38 | assert(memcmp(buf, "f", 1) == 0); 39 | 40 | // check readable/writable size functions in case of buffer wrapping 41 | assert(ringbuffer_write(rb, "0123456789abcdef", 16) == 16); 42 | assert(ringbuffer_readable_size(rb) == 16); 43 | assert(ringbuffer_writable_size(rb) == 0); 44 | 45 | assert(ringbuffer_read(rb, buf, 3) == 3); 46 | assert(ringbuffer_readable_size(rb) == 13); 47 | assert(ringbuffer_writable_size(rb) == 3); 48 | 49 | assert(ringbuffer_read(rb, buf, 3) == 3); 50 | assert(ringbuffer_readable_size(rb) == 10); 51 | assert(ringbuffer_writable_size(rb) == 6); 52 | 53 | assert(ringbuffer_read(rb, buf, 3) == 3); 54 | assert(ringbuffer_readable_size(rb) == 7); 55 | assert(ringbuffer_writable_size(rb) == 9); 56 | 57 | assert(ringbuffer_read(rb, buf, 3) == 3); 58 | assert(ringbuffer_readable_size(rb) == 4); 59 | assert(ringbuffer_writable_size(rb) == 12); 60 | 61 | assert(ringbuffer_read(rb, buf, 3) == 3); 62 | assert(ringbuffer_readable_size(rb) == 1); 63 | assert(ringbuffer_writable_size(rb) == 15); 64 | 65 | assert(ringbuffer_read(rb, buf, 3) == 1); 66 | assert(ringbuffer_readable_size(rb) == 0); 67 | assert(ringbuffer_writable_size(rb) == 16); 68 | 69 | // try to write more than buffer have 70 | assert(ringbuffer_write(rb, "01234567890", 10) == 10); 71 | assert(ringbuffer_writable_size(rb) == 6); 72 | assert(ringbuffer_write(rb, "01234567890", 10) == 6); 73 | assert(ringbuffer_writable_size(rb) == 0); 74 | assert(ringbuffer_readable_size(rb) == 16); 75 | 76 | // cleanup 77 | ringbuffer_free(rb); 78 | 79 | printf("pass\n"); 80 | return 0; 81 | } 82 | --------------------------------------------------------------------------------