summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-08-14 20:25:32 +0000
committerLennart Poettering <lennart@poettering.net>2004-08-14 20:25:32 +0000
commit22cb23eedb2eae7c79dc8fcf395be08bfc666256 (patch)
treef0993d4a26cb6e311d052b40ac5b8efc1239c145
parent1c2ec47cf1506ad1c75c088d476ae382170df62c (diff)
implement proper refcounting in polyplib
split polyplib to multiple modules add some prelimenary documentation add doxygen support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@123 fefdeb5f-60dc-0310-8127-8f9354f1896f
-rw-r--r--Makefile.am5
-rw-r--r--configure.ac2
-rw-r--r--doxygen/Makefile.am11
-rw-r--r--doxygen/doxygen.conf.in1153
-rw-r--r--polyp/Makefile.am25
-rw-r--r--polyp/cdecl.h21
-rw-r--r--polyp/glib-mainloop.h20
-rw-r--r--polyp/llist.h39
-rw-r--r--polyp/mainloop-api.h44
-rw-r--r--polyp/mainloop.h5
-rw-r--r--polyp/memblock.c42
-rw-r--r--polyp/memblock.h4
-rw-r--r--polyp/native-common.h18
-rw-r--r--polyp/pacat.c150
-rw-r--r--polyp/pactl.c146
-rw-r--r--polyp/polyplib-context.c1486
-rw-r--r--polyp/polyplib-context.h182
-rw-r--r--polyp/polyplib-def.h17
-rw-r--r--polyp/polyplib-error.h12
-rw-r--r--polyp/polyplib-internal.h1528
-rw-r--r--polyp/polyplib-introspect.c1651
-rw-r--r--polyp/polyplib-introspect.h109
-rw-r--r--polyp/polyplib-operation.c78
-rw-r--r--polyp/polyplib-operation.h56
-rw-r--r--polyp/polyplib-sample.c1550
-rw-r--r--polyp/polyplib-sample.h178
-rw-r--r--polyp/polyplib-scache.c1495
-rw-r--r--polyp/polyplib-scache.h162
-rw-r--r--polyp/polyplib-simple.c68
-rw-r--r--polyp/polyplib-simple.h33
-rw-r--r--polyp/polyplib-stream.c1556
-rw-r--r--polyp/polyplib-stream.h178
-rw-r--r--polyp/polyplib-subscribe.c1514
-rw-r--r--polyp/polyplib-subscribe.h158
-rw-r--r--polyp/polyplib.c1550
-rw-r--r--polyp/polyplib.h156
-rw-r--r--polyp/sample-util.c7
-rw-r--r--polyp/sample-util.h4
-rw-r--r--polyp/sample.c8
-rw-r--r--polyp/sample.h21
-rw-r--r--polyp/socket-client.c2
-rw-r--r--polyp/socket-client.h2
-rw-r--r--polyp/tagstruct.h2
-rw-r--r--polyp/xmalloc.c29
-rw-r--r--polyp/xmalloc.h2
45 files changed, 2766 insertions, 12713 deletions
diff --git a/Makefile.am b/Makefile.am
index a54fd606..3fc81b40 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -41,4 +41,7 @@ homepage: all dist
distcleancheck:
@:
-.PHONY: homepage distcleancheck
+doxygen:
+ $(MAKE) -C doxygen
+
+.PHONY: homepage distcleancheck doxygen
diff --git a/configure.ac b/configure.ac
index 3183d174..b7766e4a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -84,5 +84,5 @@ AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes])
AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false)
-AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html])
+AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf])
AC_OUTPUT
diff --git a/doxygen/Makefile.am b/doxygen/Makefile.am
new file mode 100644
index 00000000..d2f508c7
--- /dev/null
+++ b/doxygen/Makefile.am
@@ -0,0 +1,11 @@
+# $Id$
+
+noinst_DATA=html
+
+html: doxygen.conf
+ doxygen $<
+
+clean-local:
+ rm -rf html
+
+.PHONY: all html
diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in
new file mode 100644
index 00000000..78a43685
--- /dev/null
+++ b/doxygen/doxygen.conf.in
@@ -0,0 +1,1153 @@
+# Doxyfile 1.3.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = @PACKAGE_NAME@
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PACKAGE_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of source
+# files, where putting all generated files in the same directory would otherwise
+# cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is used
+# as the annotated text. Otherwise, the brief description is used as-is. If left
+# blank, the following values are used ("$name" is automatically replaced with the
+# name of the entity): "The $name class" "The $name widget" "The $name file"
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = NO
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = NO
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= NO
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = ../polyp/polyplib-context.h ../polyp/polyplib-stream.h ../polyp/polyplib.h ../polyp/sample.h ../polyp/polyplib-def.h ../polyp/polyplib-subscribe.h ../polyp/polyplib-introspect.h ../polyp/polyplib-scache.h ../polyp/mainloop-api.h ../polyp/cdecl.h ../polyp/glib-mainloop.h ../polyp/mainloop.h ../polyp/mainloop-signal.h ../polyp/native-common.h ../polyp/polyplib-error.h ../polyp/polyplib-operation.h ../polyp/polyplib-simple.h
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = YES
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED = PA_C_DECL_BEGIN=,PA_C_DECL_END
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED = PA_C_DECL_BEGIN, PA_C_DECL_END
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse the
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes that
+# lay further from the root node will be omitted. Note that setting this option to
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that a graph may be further truncated if the graph's image dimensions are
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT).
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index ce753da4..7f70ec9d 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -25,12 +25,19 @@ polypincludedir=$(includedir)/polyp
EXTRA_DIST = polypaudio.pa depmod.py
bin_PROGRAMS = polypaudio pacat pactl
-noinst_PROGRAMS = pacat-simple parec-simple mainloop-test mainloop-test-glib
+noinst_PROGRAMS = mainloop-test mainloop-test-glib pacat-simple parec-simple
polypinclude_HEADERS=polyplib.h \
polyplib-def.h \
polyplib-simple.h \
polyplib-error.h \
+ polyplib-stream.h \
+ polyplib-context.h \
+ polyplib-introspect.h \
+ polyplib-subscribe.h \
+ polyplib-operation.h \
+ polyplib-scache.h \
+ cdecl.h \
mainloop-api.h \
mainloop.h \
mainloop-signal.h \
@@ -72,10 +79,11 @@ pkglib_LTLIBRARIES=libiochannel.la \
module-x11-bell.la
lib_LTLIBRARIES=libpolyp.la \
- libpolyp-simple.la \
libpolyp-error.la \
libpolyp-mainloop.la \
- libpolyp-mainloop-glib.la
+ libpolyp-mainloop-glib.la \
+ libpolyp-simple.la
+
polypaudio_SOURCES = idxset.c idxset.h \
queue.c queue.h \
@@ -261,7 +269,7 @@ module_x11_bell_la_SOURCES = module-x11-bell.c
module_x11_bell_la_LDFLAGS = -module -avoid-version
module_x11_bell_la_LIBADD = $(AM_LIBADD) -lX11 -L/usr/X11R6/lib
-libpolyp_la_SOURCES = polyplib.c polyplib.h \
+libpolyp_la_SOURCES = polyplib.h \
polyplib-def.h \
tagstruct.c tagstruct.h \
iochannel.c iochannel.h \
@@ -281,7 +289,14 @@ libpolyp_la_SOURCES = polyplib.c polyplib.h \
socket-util.c socket-util.h \
native-common.h \
sample.c sample.h \
- xmalloc.c xmalloc.h
+ xmalloc.c xmalloc.h \
+ polyplib-operation.c polyplib-operation.h \
+ polyplib-context.c polyplib-context.h \
+ polyplib-stream.c polyplib-stream.h \
+ polyplib-introspect.c polyplib-introspect.h \
+ polyplib-scache.c polyplib-scache.h \
+ polyplib-subscribe.c polyplib-subscribe.h \
+ cdecl.h
libpolyp_la_CFLAGS = $(AM_CFLAGS)
libpolyp_mainloop_la_SOURCES = mainloop-api.h mainloop-api.c \
diff --git a/polyp/cdecl.h b/polyp/cdecl.h
new file mode 100644
index 00000000..39880a47
--- /dev/null
+++ b/polyp/cdecl.h
@@ -0,0 +1,21 @@
+#ifndef foocdeclhfoo
+#define foocdeclhfoo
+
+/** \file
+ * C++ compatibility support */
+
+#ifdef __cplusplus
+/** If using C++ this macro enables C mode, otherwise does nothing */
+#define PA_C_DECL_BEGIN extern "C" {
+/** If using C++ this macros switches back to C++ mode, otherwise does nothing */
+#define PA_C_DECL_END }
+
+#else
+/** If using C++ this macro enables C mode, otherwise does nothing */
+#define PA_C_DECL_BEGIN
+/** If using C++ this macros switches back to C++ mode, otherwise does nothing */
+#define PA_C_DECL_END
+
+#endif
+
+#endif
diff --git a/polyp/glib-mainloop.h b/polyp/glib-mainloop.h
index 7655108a..c67e72bd 100644
--- a/polyp/glib-mainloop.h
+++ b/polyp/glib-mainloop.h
@@ -4,20 +4,26 @@
#include <glib.h>
#include "mainloop-api.h"
+#include "cdecl.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+/** \file
+ * GLIB main loop support */
+
+PA_C_DECL_BEGIN
+/** \struct pa_glib_mainloop
+ * A GLIB main loop object */
struct pa_glib_mainloop;
+/** Create a new GLIB main loop object for the specified GLIB main loop context. If c is NULL the default context is used. */
struct pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c);
+
+/** Free the GLIB main loop object */
void pa_glib_mainloop_free(struct pa_glib_mainloop* g);
+
+/** Return the abstract main loop API vtable for the GLIB main loop object */
struct pa_mainloop_api* pa_glib_mainloop_get_api(struct pa_glib_mainloop *g);
-
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_BEGIN
#endif
diff --git a/polyp/llist.h b/polyp/llist.h
new file mode 100644
index 00000000..1f145de2
--- /dev/null
+++ b/polyp/llist.h
@@ -0,0 +1,39 @@
+#ifndef foollistfoo
+#define foollistfoo
+
+#define PA_LLIST_HEAD(t,name) t *name
+
+#define PA_LLIST_FIELDS(t) t *next, *prev;
+
+#define PA_LLIST_HEAD_INIT(t,item) do { (item) = NULL; } while(0)
+
+#define PA_LLIST_INIT(t,item) do { \
+ t *_item = (item); \
+ assert(_item); \
+ _item->prev = _item->next = NULL; \
+ } while(0)
+
+#define PA_LLIST_PREPEND(t,head,item) do { \
+ t **_head = &(head), *_item = (item); \
+ assert(_item); \
+ if ((_item->next = *_head)) \
+ _item->next->prev = _item; \
+ _item->prev = NULL; \
+ *_head = _item; \
+ } while (0)
+
+#define PA_LLIST_REMOVE(t,head,item) do { \
+ t **_head = &(head), *_item = (item); \
+ assert(_item); \
+ if (_item->next) \
+ _item->next->prev = _item->prev; \
+ if (_item->prev) \
+ _item->prev->next = _item->next; \
+ else {\
+ assert(*_head == _item); \
+ *_head = _item->next; \
+ } \
+ _item->next = _item->prev = NULL; \
+ } while(0)
+
+#endif
diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h
index 1b9e2783..97ab6a68 100644
--- a/polyp/mainloop-api.h
+++ b/polyp/mainloop-api.h
@@ -22,26 +22,37 @@
USA.
***/
-#include <time.h>
#include <sys/time.h>
+#include <time.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include "cdecl.h"
+PA_C_DECL_BEGIN
+
+/** A bitmask for IO events */
enum pa_io_event_flags {
- PA_IO_EVENT_NULL = 0,
- PA_IO_EVENT_INPUT = 1,
- PA_IO_EVENT_OUTPUT = 2,
- PA_IO_EVENT_HANGUP = 4,
- PA_IO_EVENT_ERROR = 8,
+ PA_IO_EVENT_NULL = 0, /**< No event */
+ PA_IO_EVENT_INPUT = 1, /**< Input event */
+ PA_IO_EVENT_OUTPUT = 2, /**< Output event */
+ PA_IO_EVENT_HANGUP = 4, /**< Hangup event */
+ PA_IO_EVENT_ERROR = 8, /**< Error event */
};
+/** \struct pa_io_event
+ * An IO event source object */
struct pa_io_event;
+
+/** \struct pa_defer_event
+ * A deferred event source object. Events of this type are triggered once in every main loop iteration */
struct pa_defer_event;
+
+/** \struct pa_time_event
+ * A timer event source object */
struct pa_time_event;
+/** An abstract mainloop API vtable */
struct pa_mainloop_api {
+ /** A pointer to some private, arbitrary data of the main loop implementation */
void *userdata;
/* IO sources */
@@ -56,20 +67,25 @@ struct pa_mainloop_api {
void (*time_free)(struct pa_time_event* e);
void (*time_set_destroy)(struct pa_time_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata));
- /* Deferred sources */
+ /** Create a new deferred event source object */
struct pa_defer_event* (*defer_new)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event* e, void *userdata), void *userdata);
+
+ /** Enable or disable a deferred event source temporarily */
void (*defer_enable)(struct pa_defer_event* e, int b);
+
+ /** Free a deferred event source object */
void (*defer_free)(struct pa_defer_event* e);
+
+ /** Set a function that is called when the deferred event source is destroyed. Use this to free the userdata argument if required */
void (*defer_set_destroy)(struct pa_defer_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata));
- /* Exit mainloop */
+ /** Exit the main loop and return the specfied retval*/
void (*quit)(struct pa_mainloop_api*a, int retval);
};
+/** Run the specified callback function once from the main loop using an anonymous defer event. */
void pa_mainloop_api_once(struct pa_mainloop_api*m, void (*callback)(struct pa_mainloop_api*m, void *userdata), void *userdata);
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_END
#endif
diff --git a/polyp/mainloop.h b/polyp/mainloop.h
index 58448c3e..4a4c85df 100644
--- a/polyp/mainloop.h
+++ b/polyp/mainloop.h
@@ -23,6 +23,9 @@
***/
#include "mainloop-api.h"
+#include "cdecl.h"
+
+PA_C_DECL_BEGIN
struct pa_mainloop;
@@ -34,4 +37,6 @@ int pa_mainloop_run(struct pa_mainloop *m, int *retval);
struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m);
+PA_C_DECL_END
+
#endif
diff --git a/polyp/memblock.c b/polyp/memblock.c
index 0571f5da..a4452efa 100644
--- a/polyp/memblock.c
+++ b/polyp/memblock.c
@@ -39,6 +39,7 @@ struct pa_memblock *pa_memblock_new(size_t length) {
b->ref = 1;
b->length = length;
b->data = b+1;
+ b->free_cb = NULL;
memblock_count++;
memblock_total += length;
return b;
@@ -50,6 +51,7 @@ struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length) {
b->ref = 1;
b->length = length;
b->data = d;
+ b->free_cb = NULL;
memblock_count++;
memblock_total += length;
return b;
@@ -61,6 +63,21 @@ struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length) {
b->ref = 1;
b->length = length;
b->data = d;
+ b->free_cb = NULL;
+ memblock_count++;
+ memblock_total += length;
+ return b;
+}
+
+struct pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb)(void *p)) {
+ struct pa_memblock *b;
+ assert(d && length && free_cb);
+ b = pa_xmalloc(sizeof(struct pa_memblock));
+ b->type = PA_MEMBLOCK_USER;
+ b->ref = 1;
+ b->length = length;
+ b->data = d;
+ b->free_cb = free_cb;
memblock_count++;
memblock_total += length;
return b;
@@ -74,31 +91,28 @@ struct pa_memblock* pa_memblock_ref(struct pa_memblock*b) {
void pa_memblock_unref(struct pa_memblock*b) {
assert(b && b->ref >= 1);
- b->ref--;
-
- if (b->ref == 0) {
- if (b->type == PA_MEMBLOCK_DYNAMIC)
- pa_xfree(b->data);
+ if ((--(b->ref)) == 0) {
memblock_count--;
memblock_total -= b->length;
+ if (b->type == PA_MEMBLOCK_USER) {
+ assert(b->free_cb);
+ b->free_cb(b->data);
+ } else if (b->type == PA_MEMBLOCK_DYNAMIC)
+ pa_xfree(b->data);
+
pa_xfree(b);
}
}
void pa_memblock_unref_fixed(struct pa_memblock *b) {
- void *d;
-
- assert(b && b->ref >= 1);
+ assert(b && b->ref >= 1 && b->type == PA_MEMBLOCK_FIXED);
- if (b->ref == 1) {
+ if (b->ref == 1)
pa_memblock_unref(b);
- return;
- } else {
- d = pa_xmalloc(b->length);
- memcpy(d, b->data, b->length);
- b->data = d;
+ else {
+ b->data = pa_xmemdup(b->data, b->length);
b->type = PA_MEMBLOCK_DYNAMIC;
b->ref--;
}
diff --git a/polyp/memblock.h b/polyp/memblock.h
index 4bb02977..6e79aa3e 100644
--- a/polyp/memblock.h
+++ b/polyp/memblock.h
@@ -25,18 +25,20 @@
#include <sys/types.h>
#include <inttypes.h>
-enum pa_memblock_type { PA_MEMBLOCK_FIXED, PA_MEMBLOCK_APPENDED, PA_MEMBLOCK_DYNAMIC };
+enum pa_memblock_type { PA_MEMBLOCK_FIXED, PA_MEMBLOCK_APPENDED, PA_MEMBLOCK_DYNAMIC, PA_MEMBLOCK_USER };
struct pa_memblock {
enum pa_memblock_type type;
unsigned ref;
size_t length;
void *data;
+ void (*free_cb)(void *p);
};
struct pa_memblock *pa_memblock_new(size_t length);
struct pa_memblock *pa_memblock_new_fixed(void *data, size_t length);
struct pa_memblock *pa_memblock_new_dynamic(void *data, size_t length);
+struct pa_memblock *pa_memblock_new_user(void *data, size_t length, void (*free_cb)(void *p));
void pa_memblock_unref(struct pa_memblock*b);
struct pa_memblock* pa_memblock_ref(struct pa_memblock*b);
diff --git a/polyp/native-common.h b/polyp/native-common.h
index 4d5ab53d..fa3213d0 100644
--- a/polyp/native-common.h
+++ b/polyp/native-common.h
@@ -64,6 +64,9 @@ enum {
PA_COMMAND_SUBSCRIBE,
PA_COMMAND_SUBSCRIBE_EVENT,
+
+ PA_COMMAND_SET_SINK_VOLUME,
+ PA_COMMAND_SET_SINK_INPUT_VOLUME,
PA_COMMAND_MAX
};
@@ -90,13 +93,14 @@ enum {
#define PA_NATIVE_COOKIE_FILE ".polypaudio-cookie"
enum pa_subscription_mask {
- PA_SUBSCRIPTION_FACILITY_SINK = 1,
- PA_SUBSCRIPTION_FACILITY_SOURCE = 2,
- PA_SUBSCRIPTION_FACILITY_SINK_INPUT = 4,
- PA_SUBSCRIPTION_FACILITY_SOURCE_OUTPUT = 8,
- PA_SUBSCRIPTION_FACILITY_MODULE = 16,
- PA_SUBSCRIPTION_FACILITY_CLIENT = 32,
- PA_SUBSCRIPTION_FACILITY_SAMPLE_CACHE = 64,
+ PA_SUBSCRIPTION_MASK_NULL = 0,
+ PA_SUBSCRIPTION_MASK_SINK = 1,
+ PA_SUBSCRIPTION_MASK_SOURCE = 2,
+ PA_SUBSCRIPTION_MASK_SINK_INPUT = 4,
+ PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT = 8,
+ PA_SUBSCRIPTION_MASK_MODULE = 16,
+ PA_SUBSCRIPTION_MASK_CLIENT = 32,
+ PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64,
};
enum pa_subscription_event_type {
diff --git a/polyp/pacat.c b/polyp/pacat.c
index 4d8605c7..5d29451a 100644
--- a/polyp/pacat.c
+++ b/polyp/pacat.c
@@ -52,18 +52,6 @@ static void quit(int ret) {
mainloop_api->quit(mainloop_api, ret);
}
-static void context_die_callback(struct pa_context *c, void *userdata) {
- assert(c);
- fprintf(stderr, "Connection to server shut down, exiting.\n");
- quit(1);
-}
-
-static void stream_die_callback(struct pa_stream *s, void *userdata) {
- assert(s);
- fprintf(stderr, "Stream deleted, exiting.\n");
- quit(1);
-}
-
static void do_stream_write(size_t length) {
size_t l;
assert(length);
@@ -75,7 +63,7 @@ static void do_stream_write(size_t length) {
if (l > buffer_length)
l = buffer_length;
- pa_stream_write(stream, buffer+buffer_index, l);
+ pa_stream_write(stream, buffer+buffer_index, l, NULL);
buffer_length -= l;
buffer_index += l;
@@ -115,63 +103,97 @@ static void stream_read_callback(struct pa_stream *s, const void*data, size_t le
buffer_index = 0;
}
-static void stream_complete_callback(struct pa_stream*s, int success, void *userdata) {
+static void stream_state_callback(struct pa_stream *s, void *userdata) {
assert(s);
- if (!success) {
- fprintf(stderr, "Stream creation failed: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
- quit(1);
- return;
+ switch (pa_stream_get_state(s)) {
+ case PA_STREAM_CREATING:
+ break;
+
+ case PA_STREAM_READY:
+ fprintf(stderr, "Stream successfully created\n");
+ break;
+
+ case PA_STREAM_TERMINATED:
+ quit(0);
+ break;
+
+ case PA_STREAM_FAILED:
+ default:
+ fprintf(stderr, "Stream errror: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
+ quit(1);
}
-
- fprintf(stderr, "Stream created.\n");
}
-static void context_complete_callback(struct pa_context *c, int success, void *userdata) {
+static void context_state_callback(struct pa_context *c, void *userdata) {
static const struct pa_sample_spec ss = {
.format = PA_SAMPLE_S16LE,
.rate = 44100,
.channels = 2
};
-
- assert(c && !stream);
- if (!success) {
- fprintf(stderr, "Connection failed: %s\n", pa_strerror(pa_context_errno(c)));
- goto fail;
- }
+ assert(c);
- fprintf(stderr, "Connection established.\n");
-
- if (!(stream = pa_stream_new(c, mode == PLAYBACK ? PA_STREAM_PLAYBACK : PA_STREAM_RECORD, NULL, "pacat", &ss, NULL, stream_complete_callback, NULL))) {
- fprintf(stderr, "pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(c)));
- goto fail;
+ switch (pa_context_get_state(c)) {
+ case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME:
+ break;
+
+ case PA_CONTEXT_READY:
+
+ assert(c && !stream);
+ fprintf(stderr, "Connection established.\n");
+
+ stream = pa_stream_new(c, "pacat", &ss);
+ assert(stream);
+
+ pa_stream_set_state_callback(stream, stream_state_callback, NULL);
+ pa_stream_set_write_callback(stream, stream_write_callback, NULL);
+ pa_stream_set_read_callback(stream, stream_read_callback, NULL);
+
+ if (mode == PLAYBACK)
+ pa_stream_connect_playback(stream, NULL, NULL);
+ else
+ pa_stream_connect_record(stream, NULL, NULL);
+
+ break;
+
+ case PA_CONTEXT_TERMINATED:
+ quit(0);
+ break;
+
+ case PA_CONTEXT_FAILED:
+ default:
+ fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c)));
+ quit(1);
}
-
- pa_stream_set_die_callback(stream, stream_die_callback, NULL);
- pa_stream_set_write_callback(stream, stream_write_callback, NULL);
- pa_stream_set_read_callback(stream, stream_read_callback, NULL);
-
- return;
-
-fail:
- quit(1);
}
static void context_drain_complete(struct pa_context*c, void *userdata) {
- quit(0);
+ pa_context_disconnect(c);
}
-static void stream_drain_complete(struct pa_stream*s, void *userdata) {
+static void stream_drain_complete(struct pa_stream*s, int success, void *userdata) {
+ struct pa_operation *o;
+
+ if (!success) {
+ fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context)));
+ quit(1);
+ }
+
fprintf(stderr, "Playback stream drained.\n");
- pa_stream_free(stream);
+ pa_stream_disconnect(stream);
+ pa_stream_unref(stream);
stream = NULL;
- if (pa_context_drain(context, context_drain_complete, NULL) < 0)
- quit(0);
- else
+ if (!(o = pa_context_drain(context, context_drain_complete, NULL)))
+ pa_context_disconnect(context);
+ else {
+ pa_operation_unref(o);
fprintf(stderr, "Draining connection to server.\n");
+ }
}
static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) {
@@ -184,7 +206,7 @@ static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int
return;
}
- if (!stream || !pa_stream_is_ready(stream) || !(l = w = pa_stream_writable_size(stream)))
+ if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || !(l = w = pa_stream_writable_size(stream)))
l = 4096;
buffer = malloc(l);
@@ -192,7 +214,7 @@ static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int
if ((r = read(fd, buffer, l)) <= 0) {
if (r == 0) {
fprintf(stderr, "Got EOF.\n");
- pa_stream_drain(stream, stream_drain_complete, NULL);
+ pa_operation_unref(pa_stream_drain(stream, stream_drain_complete, NULL));
} else {
fprintf(stderr, "read() failed: %s\n", strerror(errno));
quit(1);
@@ -259,10 +281,11 @@ static void stream_get_latency_callback(struct pa_stream *s, uint32_t latency, v
}
static void sigusr1_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
- if (mode == PLAYBACK) {
- fprintf(stderr, "Got SIGUSR1, requesting latency.\n");
- pa_stream_get_latency(stream, stream_get_latency_callback, NULL);
- }
+ if (mode != PLAYBACK)
+ return;
+
+ fprintf(stderr, "Got SIGUSR1, requesting latency.\n");
+ pa_operation_unref(pa_stream_get_latency(stream, stream_get_latency_callback, NULL));
}
int main(int argc, char *argv[]) {
@@ -306,12 +329,9 @@ int main(int argc, char *argv[]) {
goto quit;
}
- if (pa_context_connect(context, NULL, context_complete_callback, NULL) < 0) {
- fprintf(stderr, "pa_context_connext() failed.\n");
- goto quit;
- }
-
- pa_context_set_die_callback(context, context_die_callback, NULL);
+ pa_context_set_state_callback(context, context_state_callback, NULL);
+
+ pa_context_connect(context, NULL);
if (pa_mainloop_run(m, &ret) < 0) {
fprintf(stderr, "pa_mainloop_run() failed.\n");
@@ -320,15 +340,21 @@ int main(int argc, char *argv[]) {
quit:
if (stream)
- pa_stream_free(stream);
+ pa_stream_unref(stream);
+
if (context)
- pa_context_free(context);
+ pa_context_unref(context);
+ if (stdio_event) {
+ assert(mainloop_api);
+ mainloop_api->io_free(stdio_event);
+ }
+
if (m) {
pa_signal_done();
pa_mainloop_free(m);
}
-
+
if (buffer)
free(buffer);
diff --git a/polyp/pactl.c b/polyp/pactl.c
index 2f3a4833..0ff2aa90 100644
--- a/polyp/pactl.c
+++ b/polyp/pactl.c
@@ -68,31 +68,27 @@ static void quit(int ret) {
mainloop_api->quit(mainloop_api, ret);
}
-static void context_die_callback(struct pa_context *c, void *userdata) {
- assert(c);
- fprintf(stderr, "Connection to server shut down, exiting.\n");
- quit(1);
-}
static void context_drain_complete(struct pa_context *c, void *userdata) {
- assert(c);
- fprintf(stderr, "Connection to server shut down, exiting.\n");
- quit(0);
+ pa_context_disconnect(c);
}
static void drain(void) {
- if (pa_context_drain(context, context_drain_complete, NULL) < 0)
- quit(0);
+ struct pa_operation *o;
+ if (!(o = pa_context_drain(context, context_drain_complete, NULL)))
+ pa_context_disconnect(context);
+ else
+ pa_operation_unref(o);
}
-static void stat_callback(struct pa_context *c, uint32_t blocks, uint32_t total, void *userdata) {
- if (blocks == (uint32_t) -1) {
+static void stat_callback(struct pa_context *c, const struct pa_stat_info *i, void *userdata) {
+ if (!i) {
fprintf(stderr, "Failed to get statistics: %s\n", pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
- fprintf(stderr, "Currently in use: %u blocks containing %u bytes total.\n", blocks, total);
+ fprintf(stderr, "Currently in use: %u blocks containing %u bytes total.\n", i->memblock_count, i->memblock_total);
drain();
}
@@ -116,22 +112,23 @@ static void remove_sample_callback(struct pa_context *c, int success, void *user
drain();
}
-static void stream_die_callback(struct pa_stream *s, void *userdata) {
- assert(s);
- fprintf(stderr, "Stream deleted, exiting.\n");
- quit(1);
-}
-
-static void finish_sample_callback(struct pa_stream *s, int success, void *userdata) {
+static void stream_state_callback(struct pa_stream *s, void *userdata) {
assert(s);
- if (!success) {
- fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(context)));
- quit(1);
- return;
+ switch (pa_stream_get_state(s)) {
+ case PA_STREAM_CREATING:
+ case PA_STREAM_READY:
+ break;
+
+ case PA_STREAM_TERMINATED:
+ drain();
+ break;
+
+ case PA_STREAM_FAILED:
+ default:
+ fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
+ quit(1);
}
-
- drain();
}
static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) {
@@ -151,58 +148,55 @@ static void stream_write_callback(struct pa_stream *s, size_t length, void *user
quit(1);
}
- pa_stream_write(s, d, length);
- free(d);
+ pa_stream_write(s, d, length, free);
sample_length -= length;
if (sample_length <= 0) {
pa_stream_set_write_callback(sample_stream, NULL, NULL);
- pa_stream_finish_sample(sample_stream, finish_sample_callback, NULL);
- }
-}
-
-static void upload_callback(struct pa_stream *s, int success, void *userdata) {
- if (!success) {
- fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(context)));
- quit(1);
+ pa_stream_finish_upload(sample_stream);
}
}
-static void context_complete_callback(struct pa_context *c, int success, void *userdata) {
+static void context_state_callback(struct pa_context *c, void *userdata) {
assert(c);
+ switch (pa_context_get_state(c)) {
+ case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME:
+ break;
+
+ case PA_CONTEXT_READY:
+ if (action == STAT)
+ pa_operation_unref(pa_context_stat(c, stat_callback, NULL));
+ else if (action == PLAY_SAMPLE)
+ pa_operation_unref(pa_context_play_sample(c, process_argv[2], NULL, 0x100, play_sample_callback, NULL));
+ else if (action == REMOVE_SAMPLE)
+ pa_operation_unref(pa_context_remove_sample(c, process_argv[2], remove_sample_callback, NULL));
+ else if (action == UPLOAD_SAMPLE) {
+
+ sample_stream = pa_stream_new(c, sample_name, &sample_spec);
+ assert(sample_stream);
+
+ pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL);
+ pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL);
+ pa_stream_connect_upload(sample_stream, sample_length);
+ } else {
+ assert(action == EXIT);
+ pa_context_exit_daemon(c);
+ drain();
+ }
+ break;
- if (!success) {
- fprintf(stderr, "Connection failed: %s\n", pa_strerror(pa_context_errno(c)));
- goto fail;
- }
+ case PA_CONTEXT_TERMINATED:
+ quit(0);
+ break;
- fprintf(stderr, "Connection established.\n");
-
- if (action == STAT)
- pa_context_stat(c, stat_callback, NULL);
- else if (action == PLAY_SAMPLE)
- pa_context_play_sample(c, process_argv[2], NULL, 0x100, play_sample_callback, NULL);
- else if (action == REMOVE_SAMPLE)
- pa_context_remove_sample(c, process_argv[2], remove_sample_callback, NULL);
- else if (action == UPLOAD_SAMPLE) {
- if (!(sample_stream = pa_context_upload_sample(c, sample_name, &sample_spec, sample_length, upload_callback, NULL))) {
- fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(c)));
- goto fail;
- }
-
- pa_stream_set_die_callback(sample_stream, stream_die_callback, NULL);
- pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL);
- } else {
- assert(action == EXIT);
- pa_context_exit(c);
- drain();
+ case PA_CONTEXT_FAILED:
+ default:
+ fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c)));
+ quit(1);
}
-
- return;
-
-fail:
- quit(1);
}
static void exit_signal_callback(struct pa_mainloop_api *m, struct pa_signal_event *e, int sig, void *userdata) {
@@ -234,12 +228,15 @@ int main(int argc, char *argv[]) {
sample_name = argv[3];
else {
char *f = strrchr(argv[2], '/');
+ size_t n;
if (f)
f++;
else
f = argv[2];
- strncpy(sample_name = tmp, f, strcspn(f, "."));
+ n = strcspn(f, ".");
+ strncpy(sample_name = tmp, f, n);
+ tmp[n] = 0;
}
memset(&sfinfo, 0, sizeof(sfinfo));
@@ -292,12 +289,8 @@ int main(int argc, char *argv[]) {
goto quit;
}
- if (pa_context_connect(context, NULL, context_complete_callback, NULL) < 0) {
- fprintf(stderr, "pa_context_connext() failed.\n");
- goto quit;
- }
-
- pa_context_set_die_callback(context, context_die_callback, NULL);
+ pa_context_set_state_callback(context, context_state_callback, NULL);
+ pa_context_connect(context, NULL);
if (pa_mainloop_run(m, &ret) < 0) {
fprintf(stderr, "pa_mainloop_run() failed.\n");
@@ -305,8 +298,11 @@ int main(int argc, char *argv[]) {
}
quit:
+ if (sample_stream)
+ pa_stream_unref(sample_stream);
+
if (context)
- pa_context_free(context);
+ pa_context_unref(context);
if (m) {
pa_signal_done();
@@ -315,6 +311,6 @@ quit:
if (sndfile)
sf_close(sndfile);
-
+
return ret;
}
diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c
index 35001d3d..5f849e24 100644
--- a/polyp/polyplib-context.c
+++ b/polyp/polyplib-context.c
@@ -31,7 +31,8 @@
#include <sys/socket.h>
#include <netdb.h>
-#include "polyplib.h"
+#include "polyplib-internal.h"
+#include "polyplib-context.h"
#include "native-common.h"
#include "pdispatch.h"
#include "pstream.h"
@@ -42,128 +43,11 @@
#include "util.h"
#include "xmalloc.h"
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
+ [PA_COMMAND_REQUEST] = { pa_command_request },
+ [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { pa_command_stream_killed },
+ [PA_COMMAND_RECORD_STREAM_KILLED] = { pa_command_stream_killed },
+ [PA_COMMAND_SUBSCRIBE_EVENT] = { pa_command_subscribe_event },
};
struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
@@ -171,65 +55,41 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *
assert(mainloop && name);
c = pa_xmalloc(sizeof(struct pa_context));
+ c->ref = 1;
c->name = pa_xstrdup(name);
c->mainloop = mainloop;
c->client = NULL;
c->pstream = NULL;
c->pdispatch = NULL;
c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
+ assert(c->playback_streams && c->record_streams);
+
+ PA_LLIST_HEAD_INIT(struct pa_stream, c->streams);
+ PA_LLIST_HEAD_INIT(struct pa_operation, c->operations);
+
c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
+ c->state = PA_CONTEXT_UNCONNECTED;
c->ctag = 0;
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
-
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
+ c->state_callback = NULL;
+ c->state_userdata = NULL;
c->subscribe_callback = NULL;
c->subscribe_userdata = NULL;
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
pa_check_for_sigpipe();
return c;
}
-void pa_context_free(struct pa_context *c) {
+static void context_free(struct pa_context *c) {
assert(c);
- while (c->first_stream)
- pa_stream_free(c->first_stream);
+ while (c->operations)
+ pa_operation_cancel(c->operations);
+
+ while (c->streams)
+ pa_stream_set_state(c->streams, PA_STREAM_TERMINATED);
if (c->client)
pa_socket_client_free(c->client);
@@ -237,6 +97,7 @@ void pa_context_free(struct pa_context *c) {
pa_pdispatch_free(c->pdispatch);
if (c->pstream)
pa_pstream_free(c->pstream);
+
if (c->record_streams)
pa_dynarray_free(c->record_streams, NULL, NULL);
if (c->playback_streams)
@@ -246,66 +107,82 @@ void pa_context_free(struct pa_context *c) {
pa_xfree(c);
}
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
+struct pa_context* pa_context_ref(struct pa_context *c) {
+ assert(c && c->ref >= 1);
+ c->ref++;
+ return c;
}
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
+void pa_context_unref(struct pa_context *c) {
+ assert(c && c->ref >= 1);
+
+ if ((--(c->ref)) == 0)
+ context_free(c);
+}
+
+void pa_context_set_state(struct pa_context *c, enum pa_context_state st) {
assert(c);
- if (c->state == CONTEXT_DEAD)
+ if (c->state == st)
return;
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
+ pa_context_ref(c);
+
+ if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED) {
+ struct pa_stream *s;
+
+ s = c->streams ? pa_stream_ref(c->streams) : NULL;
+ while (s) {
+ struct pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL;
+ pa_stream_set_state(s, st == PA_CONTEXT_FAILED ? PA_STREAM_FAILED : PA_STREAM_TERMINATED);
+ pa_stream_unref(s);
+ s = n;
+ }
+
+ if (c->pdispatch)
+ pa_pdispatch_free(c->pdispatch);
+ c->pdispatch = NULL;
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
+ if (c->pstream)
+ pa_pstream_free(c->pstream);
+ c->pstream = NULL;
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
+ if (c->client)
+ pa_socket_client_free(c->client);
+ c->client = NULL;
+ }
+
+ c->state = st;
+ if (c->state_callback)
+ c->state_callback(c, c->state_userdata);
+
+ pa_context_unref(c);
+}
+
+void pa_context_fail(struct pa_context *c, int error) {
+ assert(c);
+ c->error = error;
+ pa_context_set_state(c, PA_CONTEXT_FAILED);
}
static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
struct pa_context *c = userdata;
assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
+ pa_context_fail(c, PA_ERROR_CONNECTIONTERMINATED);
}
static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
struct pa_context *c = userdata;
assert(p && packet && c);
+ pa_context_ref(c);
+
if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
}
+
+ pa_context_unref(c);
}
static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
@@ -313,90 +190,100 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, in
struct pa_stream *s;
assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
+ pa_context_ref(c);
+
+ if ((s = pa_dynarray_get(c->record_streams, channel))) {
+ if (s->read_callback)
+ s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
+ }
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
+ pa_context_unref(c);
}
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
+int pa_context_handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
assert(c && t);
-
+
if (command == PA_COMMAND_ERROR) {
if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
return -1;
+
}
-
- return 0;
+ } else if (command == PA_COMMAND_TIMEOUT)
+ c->error = PA_ERROR_TIMEOUT;
+ else {
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
+ return -1;
}
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
+ return 0;
}
static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
+ assert(pd && c && (c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME));
+ pa_context_ref(c);
+
if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
+ if (pa_context_handle_error(c, command, t) < 0)
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
+ goto finish;
}
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
+ switch(c->state) {
+ case PA_CONTEXT_AUTHORIZING: {
+ struct pa_tagstruct *t;
+ t = pa_tagstruct_new(NULL, 0);
+ assert(t);
+ pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
+ pa_tagstruct_putu32(t, tag = c->ctag++);
+ pa_tagstruct_puts(t, c->name);
+ pa_pstream_send_tagstruct(c->pstream, t);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
+ pa_context_set_state(c, PA_CONTEXT_SETTING_NAME);
+ break;
+ }
+
+ case PA_CONTEXT_SETTING_NAME :
+ pa_context_set_state(c, PA_CONTEXT_READY);
+ break;
+
+ default:
+ assert(0);
}
- return;
+finish:
+ pa_context_unref(c);
}
static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
struct pa_context *c = userdata;
struct pa_tagstruct *t;
uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
+ assert(client && c && c->state == PA_CONTEXT_CONNECTING);
+ pa_context_ref(c);
+
pa_socket_client_free(client);
c->client = NULL;
if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
+ pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED);
+ goto finish;
}
-
+
+ assert(!c->pstream);
c->pstream = pa_pstream_new(c->mainloop, io);
assert(c->pstream);
+
pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
+
+ assert(!c->pdispatch);
c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
assert(c->pdispatch);
@@ -407,7 +294,11 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i
pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
pa_pstream_send_tagstruct(c->pstream, t);
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
+
+ pa_context_set_state(c, PA_CONTEXT_AUTHORIZING);
+
+finish:
+ pa_context_unref(c);
}
static struct sockaddr *resolve_server(const char *server, size_t *len) {
@@ -438,353 +329,89 @@ static struct sockaddr *resolve_server(const char *server, size_t *len) {
return sa;
}
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
+int pa_context_connect(struct pa_context *c, const char *server) {
+ int r = -1;
+ assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED);
+ pa_context_ref(c);
+
if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
+ pa_context_fail(c, PA_ERROR_AUTHKEY);
+ goto finish;
}
if (!server)
- if (!(server = getenv("POLYP_SERVER")))
+ if (!(server = getenv(ENV_DEFAULT_SERVER)))
server = DEFAULT_SERVER;
assert(!c->client);
if (*server == '/') {
if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
+ pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED);
+ goto finish;
}
} else {
struct sockaddr* sa;
size_t sa_len;
if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
+ pa_context_fail(c, PA_ERROR_INVALIDSERVER);
+ goto finish;
}
c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
pa_xfree(sa);
if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
+ pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED);
+ goto finish;
}
}
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
+ pa_context_set_state(c, PA_CONTEXT_CONNECTING);
- return 0;
+ r = 0;
+
+finish:
+ pa_context_unref(c);
+
+ return r;
}
-int pa_context_is_dead(struct pa_context *c) {
+void pa_context_disconnect(struct pa_context *c) {
assert(c);
- return c->state == CONTEXT_DEAD;
+ pa_context_set_state(c, PA_CONTEXT_TERMINATED);
}
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
+enum pa_context_state pa_context_get_state(struct pa_context *c) {
+ assert(c && c->ref >= 1);
+ return c->state;
}
int pa_context_errno(struct pa_context *c) {
- assert(c);
+ assert(c && c->ref >= 1);
return c->error;
}
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
-
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
-
- s->state = STREAM_CREATING;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_puts(t, s->name);
- pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
-
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
-
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
+void pa_context_set_state_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
+ assert(c && c->ref >= 1);
+ c->state_callback = cb;
+ c->state_userdata = userdata;
}
int pa_context_is_pending(struct pa_context *c) {
- assert(c);
+ assert(c && c->ref >= 1);
- if (c->state != CONTEXT_READY)
+ if (c->state != PA_CONTEXT_READY)
return 0;
+ assert(c->pstream && c->pdispatch);
return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
}
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
+static void set_dispatch_callbacks(struct pa_operation *o);
static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
set_dispatch_callbacks(userdata);
@@ -794,757 +421,106 @@ static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
set_dispatch_callbacks(userdata);
}
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s && s->state == STREAM_READY);
-
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
-
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
-}
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
-}
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-
- return s;
-}
-
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
+static void set_dispatch_callbacks(struct pa_operation *o) {
+ int done = 1;
+ assert(o && o->context && o->context->ref >= 1 && o->ref >= 1 && o->context->state == PA_CONTEXT_READY);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
+ pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL);
+ pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL);
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
+ if (pa_pdispatch_is_pending(o->context->pdispatch)) {
+ pa_pdispatch_set_drain_callback(o->context->pdispatch, pdispatch_drain_callback, o);
+ done = 0;
}
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+ if (pa_pstream_is_pending(o->context->pstream)) {
+ pa_pstream_set_drain_callback(o->context->pstream, pstream_drain_callback, o);
+ done = 0;
}
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
-}
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
-
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
-
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
-}
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+ if (!done)
+ pa_operation_ref(o);
+ else {
+ if (o->callback) {
+ void (*cb)(struct pa_context *c, void *userdata);
+ cb = (void*) o->callback;
+ cb(o->context, o->userdata);
}
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
+ pa_operation_done(o);
+ }
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
+ pa_operation_unref(o);
}
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
+struct pa_operation* pa_context_drain(struct pa_context *c, void (*cb) (struct pa_context*c, void *userdata), void *userdata) {
+ struct pa_operation *o;
+ assert(c && c->ref >= 1 && c->state == PA_CONTEXT_READY);
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ if (!pa_context_is_pending(c))
+ return NULL;
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
+ o = pa_operation_new(c, NULL);
+ assert(o);
+ o->callback = cb;
+ o->userdata = userdata;
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
+ set_dispatch_callbacks(pa_operation_ref(o));
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
+ return o;
}
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
+void pa_context_exit_daemon(struct pa_context *c) {
struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
+ assert(c && c->ref >= 1);
t = pa_tagstruct_new(NULL, 0);
assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
+ pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
}
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
+void pa_context_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ int success = 1;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
+ success = 0;
+ } else if (!pa_tagstruct_eof(t)) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
+ if (o->callback) {
+ void (*cb)(struct pa_context *c, int success, void *userdata) = o->callback;
+ cb(o->context, success, o->userdata);
}
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
+struct pa_operation* pa_context_send_simple_command(struct pa_context *c, uint32_t command, void (*internal_callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void (*cb)(), void *userdata) {
struct pa_tagstruct *t;
+ struct pa_operation *o;
uint32_t tag;
- assert(c);
+ assert(c && cb);
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
+ pa_tagstruct_putu32(t, command);
pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_callback, o);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
-}
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
+ return pa_operation_ref(o);
}
diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h
index a0dd9f9c..6a1cc8bd 100644
--- a/polyp/polyplib-context.h
+++ b/polyp/polyplib-context.h
@@ -1,5 +1,5 @@
-#ifndef foopolyplibhfoo
-#define foopolyplibhfoo
+#ifndef foopolyplibcontexthfoo
+#define foopolyplibcontexthfoo
/* $Id$ */
@@ -22,157 +22,71 @@
USA.
***/
-#include <sys/types.h>
-
#include "sample.h"
#include "polyplib-def.h"
#include "mainloop-api.h"
+#include "cdecl.h"
+#include "polyplib-operation.h"
+
+/** \file
+ * Connection contexts */
+
+PA_C_DECL_BEGIN
+
+/** The state of a connection context */
+enum pa_context_state {
+ PA_CONTEXT_UNCONNECTED, /**< The context hasn't been connected yet */
+ PA_CONTEXT_CONNECTING, /**< A connection is being established */
+ PA_CONTEXT_AUTHORIZING, /**< The client is authorizing itself to the daemon */
+ PA_CONTEXT_SETTING_NAME, /**< The client is passing its application name to the daemon */
+ PA_CONTEXT_READY, /**< The connection is established, the context is ready to execute operations */
+ PA_CONTEXT_FAILED, /**< The connection failed or was disconnected */
+ PA_CONTEXT_TERMINATED /**< The connect was terminated cleanly */
+};
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
+/** \struct pa_context
+ * A connection context to a daemon */
struct pa_context;
-struct pa_stream;
+/** Instantiate a new connection context with an abstract mainloop API
+ * and an application name */
struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
+
+/** Decrease the reference counter of the context by one */
void pa_context_unref(struct pa_context *c);
+
+/** Increase the reference counter of the context by one */
struct pa_context* pa_context_ref(struct pa_context *c);
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
+/** Set a callback function that is called whenever the context status changes */
+void pa_context_set_state_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
+/** Return the error number of the last failed operation */
int pa_context_errno(struct pa_context *c);
+/** Return non-zero if some data is pending to be written to the connection */
int pa_context_is_pending(struct pa_context *c);
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
+/** Return the current context status */
+enum pa_context_state pa_context_get_state(struct pa_context *c);
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
+/** Connect the context to the specified server. If server is NULL,
+connect to the default server. This routine may but will not always
+return synchronously on error. Use pa_context_set_state_callback() to
+be notified when the connection is established */
+int pa_context_connect(struct pa_context *c, const char *server);
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
+/** Terminate the context connection immediately */
+void pa_context_disconnect(struct pa_context *c);
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
+/** Drain the context. If there is nothing to drain, the function returns NULL */
+struct pa_operation* pa_context_drain(struct pa_context *c, void (*cb) (struct pa_context*c, void *userdata), void *userdata);
-struct pa_context* pa_stream_get_context(struct pa_stream *p);
+/** Tell the daemon to exit. No operation object is returned as the
+ * connection is terminated when the daemon quits, thus this operation
+ * would never complete. */
+void pa_context_exit_daemon(struct pa_context *c);
-uint32_t pa_stream_get_index(struct pa_stream *s);
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-struct pa_sink_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t volume;
- uint32_t monitor_source;
- const char *monitor_source_name;
- uint32_t latency;
-};
-
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t monitor_of_sink;
- const char *monitor_of_sink_name;
-};
-
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_server_info {
- const char *user_name;
- const char *host_name;
- const char *server_version;
- const char *server_name;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
-
-struct pa_module_info {
- uint32_t index;
- const char*name, *argument;
- uint32_t n_used, auto_unload;
-};
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_client_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- const char *protocol_name;
-};
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_sink_input_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t sink;
- struct pa_sample_spec sample_spec;
- uint32_t volume;
- uint32_t latency;
-};
-
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_output_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t source;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
-
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_END
#endif
diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h
index d96c6899..fc19be69 100644
--- a/polyp/polyplib-def.h
+++ b/polyp/polyplib-def.h
@@ -23,14 +23,13 @@
***/
#include <inttypes.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "native-common.h"
+#include "cdecl.h"
+
+PA_C_DECL_BEGIN
enum pa_stream_direction {
+ PA_STREAM_NODIRECTION,
PA_STREAM_PLAYBACK,
PA_STREAM_RECORD,
PA_STREAM_UPLOAD
@@ -43,9 +42,9 @@ struct pa_buffer_attr {
uint32_t minreq;
uint32_t fragsize;
};
-
-#ifdef __cplusplus
-}
-#endif
+
+#define PA_INVALID_INDEX ((uint32_t) -1)
+
+PA_C_DECL_END
#endif
diff --git a/polyp/polyplib-error.h b/polyp/polyplib-error.h
index d76ce6ff..d7519af4 100644
--- a/polyp/polyplib-error.h
+++ b/polyp/polyplib-error.h
@@ -23,15 +23,13 @@
***/
#include <inttypes.h>
+#include "cdecl.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+PA_C_DECL_BEGIN;
+/** Return a human readable error message for the specified numeric error code */
const char* pa_strerror(uint32_t error);
-#ifdef __cplusplus
-}
-#endif
-
+PA_C_DECL_END;
+
#endif
diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h
index 35001d3d..0b6b3887 100644
--- a/polyp/polyplib-internal.h
+++ b/polyp/polyplib-internal.h
@@ -1,3 +1,6 @@
+#ifndef foopolyplibinternalhfoo
+#define foopolyplibinternalhfoo
+
/* $Id$ */
/***
@@ -19,28 +22,16 @@
USA.
***/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
+#include "mainloop-api.h"
+#include "socket-client.h"
#include "pstream.h"
+#include "pdispatch.h"
#include "dynarray.h"
-#include "socket-client.h"
-#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
+
+#include "polyplib-context.h"
+#include "polyplib-stream.h"
+#include "polyplib-operation.h"
+#include "llist.h"
#define DEFAULT_MAXLENGTH 204800
#define DEFAULT_TLENGTH 10240
@@ -52,68 +43,41 @@
#define DEFAULT_SERVER "/tmp/polypaudio/native"
#define DEFAULT_PORT "4713"
+#define ENV_DEFAULT_SINK "POLYP_SINK"
+#define ENV_DEFAULT_SOURCE "POLYP_SOURCE"
+#define ENV_DEFAULT_SERVER "POLYP_SERVER"
+
struct pa_context {
+ int ref;
+
char *name;
struct pa_mainloop_api* mainloop;
+
struct pa_socket_client *client;
struct pa_pstream *pstream;
struct pa_pdispatch *pdispatch;
+
struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
+ PA_LLIST_HEAD(struct pa_stream, streams);
+ PA_LLIST_HEAD(struct pa_operation, operations);
+
uint32_t ctag;
uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
+ enum pa_context_state state;
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
+ uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
+ void (*state_callback)(struct pa_context*c, void *userdata);
+ void *state_userdata;
void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
};
struct pa_stream {
+ int ref;
struct pa_context *context;
- struct pa_stream *next, *previous;
+ PA_LLIST_FIELDS(struct pa_stream);
char *name;
struct pa_buffer_attr buffer_attr;
@@ -122,1429 +86,47 @@ struct pa_stream {
int channel_valid;
uint32_t device_index;
enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
uint32_t requested_bytes;
+ enum pa_stream_state state;
+
+ void (*state_callback)(struct pa_stream*c, void *userdata);
+ void *state_userdata;
void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
void *read_userdata;
void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
};
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+struct pa_operation {
+ int ref;
+ struct pa_context *context;
+ struct pa_stream *stream;
+ PA_LLIST_FIELDS(struct pa_operation);
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
+ enum pa_operation_state state;
+ void *userdata;
+ void (*callback)();
};
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
-
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
-
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
-
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
-
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
-
-void pa_context_free(struct pa_context *c) {
- assert(c);
-
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
-}
-
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
-}
-
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
-
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
-}
-
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
-}
-
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
-
- return 0;
- }
-
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
-}
-
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
-
- if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
- }
-
- return;
-}
-
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
+void pa_command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+void pa_command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+void pa_command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
- pa_socket_client_free(client);
- c->client = NULL;
+struct pa_operation *pa_operation_new(struct pa_context *c, struct pa_stream *s);
+void pa_operation_done(struct pa_operation *o);
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
-}
-
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
-
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
-
- freeaddrinfo(result);
-
- return sa;
-}
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
-
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
- }
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
-
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
-
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- }
-
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
-}
-
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
-}
-
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
-
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
-
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
-
- s->state = STREAM_CREATING;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_puts(t, s->name);
- pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
+void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+void pa_stream_disconnect_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+void pa_context_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+void pa_stream_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
+void pa_context_fail(struct pa_context *c, int error);
+void pa_context_set_state(struct pa_context *c, enum pa_context_state st);
+int pa_context_handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t);
+struct pa_operation* pa_context_send_simple_command(struct pa_context *c, uint32_t command, void (*internal_callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void (*cb)(), void *userdata);
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
+void pa_stream_set_state(struct pa_stream *s, enum pa_stream_state st);
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
-}
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s && s->state == STREAM_READY);
-
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
-
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
-}
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
-}
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-
- return s;
-}
-
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
-}
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
-
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
-
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
-}
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
-}
-
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
-}
-
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
-}
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
+#endif
diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c
index 35001d3d..345a9cd5 100644
--- a/polyp/polyplib-introspect.c
+++ b/polyp/polyplib-introspect.c
@@ -23,1528 +23,421 @@
#include <config.h>
#endif
-#include <stdio.h>
#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
-#include "pstream.h"
-#include "dynarray.h"
-#include "socket-client.h"
-#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
-
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
-};
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
-
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
-
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
-
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
-
-void pa_context_free(struct pa_context *c) {
- assert(c);
-
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
-}
-
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
-}
-
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
-
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
-}
-
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
-}
-
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
+#include "polyplib-introspect.h"
+#include "polyplib-context.h"
+#include "polyplib-internal.h"
+#include "pstream-util.h"
- return 0;
- }
+/*** Statistics ***/
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
-}
-
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
+static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ struct pa_stat_info i, *p = &i;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
+ p = NULL;
+ } else if (pa_tagstruct_getu32(t, &i.memblock_count) < 0 ||
+ pa_tagstruct_getu32(t, &i.memblock_total) < 0 ||
+ !pa_tagstruct_eof(t)) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_stat_info*i, void *userdata) = o->callback;
+ cb(o->context, p, o->userdata);
}
- return;
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
-
- pa_socket_client_free(client);
- c->client = NULL;
-
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
+struct pa_operation* pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_stat_info*i, void *userdata), void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, cb, userdata);
}
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
-
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
+/*** Server Info ***/
- freeaddrinfo(result);
-
- return sa;
-}
+static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ struct pa_server_info i, *p = &i;
+ assert(pd && o && o->context && o->ref >= 1);
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
+ if (command != PA_COMMAND_REPLY) {
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
+ p = NULL;
+ } else if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
+ pa_tagstruct_gets(t, &i.server_version) < 0 ||
+ pa_tagstruct_gets(t, &i.user_name) < 0 ||
+ pa_tagstruct_gets(t, &i.host_name) < 0 ||
+ pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
+ !pa_tagstruct_eof(t)) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
-
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_server_info*i, void *userdata) = o->callback;
+ cb(o->context, p, o->userdata);
}
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
+struct pa_operation* pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, cb, userdata);
}
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
-
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
+/*** Sink Info ***/
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
+static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ int eof = 1;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
-
- s->state = STREAM_CREATING;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_puts(t, s->name);
- pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
+ eof = -1;
+ } else {
+
+ while (!pa_tagstruct_eof(t)) {
+ struct pa_sink_info i;
+
+ if (pa_tagstruct_getu32(t, &i.index) < 0 ||
+ pa_tagstruct_gets(t, &i.name) < 0 ||
+ pa_tagstruct_gets(t, &i.description) < 0 ||
+ pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
+ pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
+ pa_tagstruct_getu32(t, &i.volume) < 0 ||
+ pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
+ pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
+ pa_tagstruct_getu32(t, &i.latency) < 0) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
+ }
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_sink_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, &i, 0, o->userdata);
+ }
+ }
}
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
-
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
-
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
-}
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_sink_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, NULL, eof, o->userdata);
}
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
- set_dispatch_callbacks(c);
-
- return 0;
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
+struct pa_operation* pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, cb, userdata);
}
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
+struct pa_operation* pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
struct pa_tagstruct *t;
+ struct pa_operation *o;
uint32_t tag;
- assert(s && s->state == STREAM_READY);
-
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
+ assert(c && cb);
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
+ pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
+ pa_tagstruct_putu32(t, tag = c->ctag++);
+ pa_tagstruct_putu32(t, index);
+ pa_tagstruct_puts(t, "");
pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, o);
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
+ return pa_operation_ref(o);
}
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
+/*** Source info ***/
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
+static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ int eof = 1;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
+ eof = -1;
+ } else {
+
+ while (!pa_tagstruct_eof(t)) {
+ struct pa_source_info i;
+
+ if (pa_tagstruct_getu32(t, &i.index) < 0 ||
+ pa_tagstruct_gets(t, &i.name) < 0 ||
+ pa_tagstruct_gets(t, &i.description) < 0 ||
+ pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
+ pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
+ pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
+ pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
+ }
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_source_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, &i, 0, o->userdata);
+ }
+ }
}
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_source_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, NULL, eof, o->userdata);
}
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
+struct pa_operation* pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, cb, userdata);
}
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
+struct pa_operation* pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
struct pa_tagstruct *t;
+ struct pa_operation *o;
uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
+ assert(c && cb);
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
+ pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
+ pa_tagstruct_putu32(t, index);
+ pa_tagstruct_puts(t, "");
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, o);
- return s;
+ return pa_operation_ref(o);
}
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
+/*** Client info ***/
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
+static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ int eof = 1;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
+ eof = -1;
+ } else {
+
+ while (!pa_tagstruct_eof(t)) {
+ struct pa_client_info i;
+
+ if (pa_tagstruct_getu32(t, &i.index) < 0 ||
+ pa_tagstruct_gets(t, &i.name) < 0 ||
+ pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
+ pa_tagstruct_getu32(t, &i.owner_module) < 0) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
+ }
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_client_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, &i, 0, o->userdata);
+ }
+ }
}
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_client_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, NULL, eof, o->userdata);
}
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+struct pa_operation* pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
struct pa_tagstruct *t;
+ struct pa_operation *o;
uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
+ assert(c && cb);
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
+ pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
+ pa_tagstruct_putu32(t, index);
+ pa_tagstruct_puts(t, "");
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, o);
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
+ return pa_operation_ref(o);
}
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
+struct pa_operation* pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, cb, userdata);
}
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
+/*** Module info ***/
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
+static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ int eof = 1;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
+ eof = -1;
+ } else {
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+ while (!pa_tagstruct_eof(t)) {
+ struct pa_module_info i;
+
+ if (pa_tagstruct_getu32(t, &i.index) < 0 ||
+ pa_tagstruct_gets(t, &i.name) < 0 ||
+ pa_tagstruct_gets(t, &i.argument) < 0 ||
+ pa_tagstruct_getu32(t, &i.n_used) < 0 ||
+ pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
+ }
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_module_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, &i, 0, o->userdata);
+ }
}
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
}
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_module_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, NULL, eof, o->userdata);
}
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
+struct pa_operation* pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
struct pa_tagstruct *t;
+ struct pa_operation *o;
uint32_t tag;
- assert(c);
+ assert(c && cb);
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
+ pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
pa_tagstruct_putu32(t, tag = c->ctag++);
+ pa_tagstruct_putu32(t, index);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, o);
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
+ return pa_operation_ref(o);
}
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
+struct pa_operation* pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, cb, userdata);
}
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
+/*** Volume manipulation ***/
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
+struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
- assert(c);
+ assert(c && index != PA_INVALID_INDEX);
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
+ pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME);
pa_tagstruct_putu32(t, tag = c->ctag++);
pa_tagstruct_putu32(t, index);
pa_tagstruct_puts(t, "");
+ pa_tagstruct_putu32(t, volume);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
+ return pa_operation_ref(o);
}
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
+struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, const char *name, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
+ assert(c && name);
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
+ pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME);
pa_tagstruct_putu32(t, tag = c->ctag++);
+ pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+ pa_tagstruct_puts(t, name);
+ pa_tagstruct_putu32(t, volume);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
+ return pa_operation_ref(o);
}
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
+struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
- assert(c);
+ assert(c && index != PA_INVALID_INDEX);
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
+ pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME);
pa_tagstruct_putu32(t, tag = c->ctag++);
pa_tagstruct_putu32(t, index);
+ pa_tagstruct_putu32(t, volume);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
+ return pa_operation_ref(o);
}
diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h
index a0dd9f9c..bca752e2 100644
--- a/polyp/polyplib-introspect.h
+++ b/polyp/polyplib-introspect.h
@@ -1,5 +1,5 @@
-#ifndef foopolyplibhfoo
-#define foopolyplibhfoo
+#ifndef foopolyplibintrospecthfoo
+#define foopolyplibintrospecthfoo
/* $Id$ */
@@ -22,61 +22,13 @@
USA.
***/
-#include <sys/types.h>
+#include <inttypes.h>
-#include "sample.h"
-#include "polyplib-def.h"
-#include "mainloop-api.h"
+#include "polyplib-operation.h"
+#include "polyplib-context.h"
+#include "cdecl.h"
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
-struct pa_context;
-struct pa_stream;
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
-void pa_context_unref(struct pa_context *c);
-struct pa_context* pa_context_ref(struct pa_context *c);
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
-
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
-int pa_context_errno(struct pa_context *c);
-
-int pa_context_is_pending(struct pa_context *c);
-
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
-
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p);
-
-uint32_t pa_stream_get_index(struct pa_stream *s);
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+PA_C_DECL_BEGIN
struct pa_sink_info {
const char *name;
@@ -90,9 +42,9 @@ struct pa_sink_info {
uint32_t latency;
};
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
struct pa_source_info {
const char *name;
@@ -104,9 +56,9 @@ struct pa_source_info {
const char *monitor_of_sink_name;
};
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
struct pa_server_info {
const char *user_name;
@@ -116,7 +68,7 @@ struct pa_server_info {
struct pa_sample_spec sample_spec;
};
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
struct pa_module_info {
uint32_t index;
@@ -124,8 +76,8 @@ struct pa_module_info {
uint32_t n_used, auto_unload;
};
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
struct pa_client_info {
uint32_t index;
@@ -134,8 +86,8 @@ struct pa_client_info {
const char *protocol_name;
};
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
struct pa_sink_input_info {
uint32_t index;
@@ -148,8 +100,8 @@ struct pa_sink_input_info {
uint32_t latency;
};
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
struct pa_source_output_info {
uint32_t index;
@@ -160,19 +112,20 @@ struct pa_source_output_info {
struct pa_sample_spec sample_spec;
};
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, const char *name, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
+struct pa_stat_info {
+ uint32_t memblock_count;
+ uint32_t memblock_total;
+};
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
+struct pa_operation* pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_stat_info *i, void *userdata), void *userdata);
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_END
#endif
diff --git a/polyp/polyplib-operation.c b/polyp/polyplib-operation.c
new file mode 100644
index 00000000..994ac016
--- /dev/null
+++ b/polyp/polyplib-operation.c
@@ -0,0 +1,78 @@
+#include <assert.h>
+
+#include "xmalloc.h"
+#include "polyplib-internal.h"
+#include "polyplib-operation.h"
+
+struct pa_operation *pa_operation_new(struct pa_context *c, struct pa_stream *s) {
+ struct pa_operation *o;
+ assert(c);
+
+ o = pa_xmalloc(sizeof(struct pa_operation));
+ o->ref = 1;
+ o->context = pa_context_ref(c);
+ o->stream = s ? pa_stream_ref(s) : NULL;
+
+ o->state = PA_OPERATION_RUNNING;
+ o->userdata = NULL;
+ o->callback = NULL;
+
+ PA_LLIST_PREPEND(struct pa_operation, o->context->operations, o);
+ return pa_operation_ref(o);
+}
+
+struct pa_operation *pa_operation_ref(struct pa_operation *o) {
+ assert(o && o->ref >= 1);
+ o->ref++;
+ return o;
+}
+
+void pa_operation_unref(struct pa_operation *o) {
+ assert(o && o->ref >= 1);
+
+ if ((--(o->ref)) == 0) {
+ assert(!o->context);
+ assert(!o->stream);
+ free(o);
+ }
+}
+
+static void operation_set_state(struct pa_operation *o, enum pa_operation_state st) {
+ assert(o && o->ref >= 1);
+
+ if (st == o->state)
+ return;
+
+ if (!o->context)
+ return;
+
+ o->state = st;
+
+ if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) {
+ PA_LLIST_REMOVE(struct pa_operation, o->context->operations, o);
+ pa_context_unref(o->context);
+ if (o->stream)
+ pa_stream_unref(o->stream);
+ o->context = NULL;
+ o->stream = NULL;
+ o->callback = NULL;
+ o->userdata = NULL;
+
+ pa_operation_unref(o);
+ }
+}
+
+void pa_operation_cancel(struct pa_operation *o) {
+ assert(o && o->ref >= 1);
+ operation_set_state(o, PA_OPERATION_CANCELED);
+}
+
+void pa_operation_done(struct pa_operation *o) {
+ assert(o && o->ref >= 1);
+ operation_set_state(o, PA_OPERATION_DONE);
+}
+
+enum pa_operation_state pa_operation_get_state(struct pa_operation *o) {
+ assert(o && o->ref >= 1);
+ return o->state;
+}
diff --git a/polyp/polyplib-operation.h b/polyp/polyplib-operation.h
new file mode 100644
index 00000000..7d0adc26
--- /dev/null
+++ b/polyp/polyplib-operation.h
@@ -0,0 +1,56 @@
+#ifndef foopolypliboperationhfoo
+#define foopolypliboperationhfoo
+
+/* $Id$ */
+
+/***
+ This file is part of polypaudio.
+
+ polypaudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2 of the License,
+ or (at your option) any later version.
+
+ polypaudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with polypaudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include "cdecl.h"
+
+/** \file
+ * Asynchronous operations */
+
+PA_C_DECL_BEGIN
+
+enum pa_operation_state {
+ PA_OPERATION_RUNNING, /**< The operation is still running */
+ PA_OPERATION_DONE, /**< The operation has been completed */
+ PA_OPERATION_CANCELED, /**< The operation has been canceled */
+};
+
+/** \struct pa_operation
+ * An asynchronous operation object */
+struct pa_operation;
+
+/** Increase the reference count by one */
+struct pa_operation *pa_operation_ref(struct pa_operation *o);
+
+/** Decrease the reference count by one */
+void pa_operation_unref(struct pa_operation *o);
+
+/** Cancel the operation. Beware! This will not necessarily cancel the execution of the operation on the server side. */
+void pa_operation_cancel(struct pa_operation *o);
+
+/** Return the current status of the operation */
+enum pa_operation_state pa_operation_get_state(struct pa_operation *o);
+
+PA_C_DECL_END
+
+#endif
diff --git a/polyp/polyplib-sample.c b/polyp/polyplib-sample.c
deleted file mode 100644
index 35001d3d..00000000
--- a/polyp/polyplib-sample.c
+++ /dev/null
@@ -1,1550 +0,0 @@
-/* $Id$ */
-
-/***
- This file is part of polypaudio.
-
- polypaudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2 of the License,
- or (at your option) any later version.
-
- polypaudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with polypaudio; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- USA.
-***/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
-#include "pstream.h"
-#include "dynarray.h"
-#include "socket-client.h"
-#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
-
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
-};
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
-
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
-
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
-
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
-
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
-
-void pa_context_free(struct pa_context *c) {
- assert(c);
-
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
-}
-
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
-}
-
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
-
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
-}
-
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
-}
-
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
-
- return 0;
- }
-
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
-}
-
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
-
- if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
- }
-
- return;
-}
-
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
-
- pa_socket_client_free(client);
- c->client = NULL;
-
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
-}
-
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
-
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
-
- freeaddrinfo(result);
-
- return sa;
-}
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
-
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
- }
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
-
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
-
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- }
-
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
-}
-
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
-}
-
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
-
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
-
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
-
- s->state = STREAM_CREATING;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_puts(t, s->name);
- pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
-
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
-
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
-}
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s && s->state == STREAM_READY);
-
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
-
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
-}
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
-}
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-
- return s;
-}
-
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
-}
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
-
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
-
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
-}
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
-}
-
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
-}
-
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
-}
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
diff --git a/polyp/polyplib-sample.h b/polyp/polyplib-sample.h
deleted file mode 100644
index a0dd9f9c..00000000
--- a/polyp/polyplib-sample.h
+++ /dev/null
@@ -1,178 +0,0 @@
-#ifndef foopolyplibhfoo
-#define foopolyplibhfoo
-
-/* $Id$ */
-
-/***
- This file is part of polypaudio.
-
- polypaudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2 of the License,
- or (at your option) any later version.
-
- polypaudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with polypaudio; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- USA.
-***/
-
-#include <sys/types.h>
-
-#include "sample.h"
-#include "polyplib-def.h"
-#include "mainloop-api.h"
-
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
-struct pa_context;
-struct pa_stream;
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
-void pa_context_unref(struct pa_context *c);
-struct pa_context* pa_context_ref(struct pa_context *c);
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
-
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
-int pa_context_errno(struct pa_context *c);
-
-int pa_context_is_pending(struct pa_context *c);
-
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
-
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p);
-
-uint32_t pa_stream_get_index(struct pa_stream *s);
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-struct pa_sink_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t volume;
- uint32_t monitor_source;
- const char *monitor_source_name;
- uint32_t latency;
-};
-
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t monitor_of_sink;
- const char *monitor_of_sink_name;
-};
-
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_server_info {
- const char *user_name;
- const char *host_name;
- const char *server_version;
- const char *server_name;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
-
-struct pa_module_info {
- uint32_t index;
- const char*name, *argument;
- uint32_t n_used, auto_unload;
-};
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_client_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- const char *protocol_name;
-};
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_sink_input_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t sink;
- struct pa_sample_spec sample_spec;
- uint32_t volume;
- uint32_t latency;
-};
-
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_output_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t source;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/polyp/polyplib-scache.c b/polyp/polyplib-scache.c
index 35001d3d..8215eaec 100644
--- a/polyp/polyplib-scache.c
+++ b/polyp/polyplib-scache.c
@@ -23,1083 +23,73 @@
#include <config.h>
#endif
-#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
-#include "pstream.h"
-#include "dynarray.h"
-#include "socket-client.h"
+#include "polyplib-scache.h"
+#include "polyplib-internal.h"
#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
-
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
-};
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
-
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
-
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
-
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
-
-void pa_context_free(struct pa_context *c) {
- assert(c);
-
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
-}
-
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
-}
-
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
-
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
-}
-
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
-}
-
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
-
- return 0;
- }
-
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
-}
-
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
-
- if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
- }
-
- return;
-}
-
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
+void pa_stream_connect_upload(struct pa_stream *s, size_t length) {
struct pa_tagstruct *t;
uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
-
- pa_socket_client_free(client);
- c->client = NULL;
-
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
+ assert(s && length);
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
-}
-
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
-
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
-
- freeaddrinfo(result);
-
- return sa;
-}
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
-
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
- }
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
+ pa_stream_ref(s);
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
-
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- }
-
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
-}
-
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
-}
-
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
-
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
-
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
+ s->state = PA_STREAM_CREATING;
+ s->direction = PA_STREAM_UPLOAD;
- s->state = STREAM_CREATING;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
+ pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
pa_tagstruct_putu32(t, tag = s->context->ctag++);
pa_tagstruct_puts(t, s->name);
pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
+ pa_tagstruct_putu32(t, length);
pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
+ pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s);
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
-
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
-
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
+ pa_stream_unref(s);
}
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
+void pa_stream_finish_upload(struct pa_stream *s) {
struct pa_tagstruct *t;
uint32_t tag;
- assert(s && s->state == STREAM_READY);
+ assert(s);
- if (!complete) {
- s->drain_complete_callback = NULL;
+ if (!s->channel_valid || !s->context->state == PA_CONTEXT_READY)
return;
- }
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
+ pa_stream_ref(s);
t = pa_tagstruct_new(NULL, 0);
assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
+ pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
pa_tagstruct_putu32(t, tag = s->context->ctag++);
pa_tagstruct_putu32(t, s->channel);
pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
-}
+ pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s);
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
+ pa_stream_unref(s);
}
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-
- return s;
-}
-
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
-}
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+struct pa_operation * pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
assert(c && name && *name && (!dev || *dev));
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
+ if (!dev)
+ dev = getenv(ENV_DEFAULT_SINK);
+
t = pa_tagstruct_new(NULL, 0);
assert(t);
pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
@@ -1109,44 +99,20 @@ void pa_context_play_sample(struct pa_context *c, const char *name, const char *
pa_tagstruct_putu32(t, volume);
pa_tagstruct_puts(t, name);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
+ return pa_operation_ref(o);
}
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+struct pa_operation* pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
assert(c && name);
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
t = pa_tagstruct_new(NULL, 0);
assert(t);
@@ -1154,397 +120,8 @@ void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)
pa_tagstruct_putu32(t, tag = c->ctag++);
pa_tagstruct_puts(t, name);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
+ return pa_operation_ref(o);
}
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
-}
-
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
-}
-
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
-}
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
diff --git a/polyp/polyplib-scache.h b/polyp/polyplib-scache.h
index a0dd9f9c..ce74bef0 100644
--- a/polyp/polyplib-scache.h
+++ b/polyp/polyplib-scache.h
@@ -1,5 +1,5 @@
-#ifndef foopolyplibhfoo
-#define foopolyplibhfoo
+#ifndef foopolyplibscachehfoo
+#define foopolyplibscachehfoo
/* $Id$ */
@@ -24,155 +24,27 @@
#include <sys/types.h>
-#include "sample.h"
-#include "polyplib-def.h"
-#include "mainloop-api.h"
+#include "polyplib-context.h"
+#include "polyplib-stream.h"
+#include "cdecl.h"
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
-struct pa_context;
-struct pa_stream;
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
-void pa_context_unref(struct pa_context *c);
-struct pa_context* pa_context_ref(struct pa_context *c);
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
-
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
-int pa_context_errno(struct pa_context *c);
-
-int pa_context_is_pending(struct pa_context *c);
-
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
-
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p);
-
-uint32_t pa_stream_get_index(struct pa_stream *s);
+/** \file
+ * All sample cache related routines */
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
+PA_C_DECL_BEGIN
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+/** Make this stream a sample upload stream */
+void pa_stream_connect_upload(struct pa_stream *s, size_t length);
-struct pa_sink_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t volume;
- uint32_t monitor_source;
- const char *monitor_source_name;
- uint32_t latency;
-};
+/** Finish the sample upload, the stream name will become the sample name. You cancel a sample upload by issuing pa_stream_disconnect() */
+void pa_stream_finish_upload(struct pa_stream *s);
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
+/** Play a sample from the sample cache to the specified device. If the latter is NULL use the default sink. Returns an operation object */
+struct pa_operation* pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-struct pa_source_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t monitor_of_sink;
- const char *monitor_of_sink_name;
-};
+/** Remove a sample from the sample cache. Returns an operation object which may be used to cancel the operation while it is running */
+struct pa_operation* pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_server_info {
- const char *user_name;
- const char *host_name;
- const char *server_version;
- const char *server_name;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
-
-struct pa_module_info {
- uint32_t index;
- const char*name, *argument;
- uint32_t n_used, auto_unload;
-};
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_client_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- const char *protocol_name;
-};
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_sink_input_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t sink;
- struct pa_sample_spec sample_spec;
- uint32_t volume;
- uint32_t latency;
-};
-
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_output_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t source;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
-
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_END
#endif
diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c
index 1f5ea553..66ee5995 100644
--- a/polyp/polyplib-simple.c
+++ b/polyp/polyplib-simple.c
@@ -49,15 +49,28 @@ struct pa_simple {
static void read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata);
static int check_error(struct pa_simple *p, int *perror) {
+ enum pa_context_state cst;
+ enum pa_stream_state sst;
assert(p);
- if (pa_context_is_dead(p->context) || (p->stream && pa_stream_is_dead(p->stream))) {
- if (perror)
- *perror = pa_context_errno(p->context);
- return -1;
- }
+ if ((cst = pa_context_get_state(p->context)) == PA_CONTEXT_FAILED)
+ goto fail;
+ assert(cst != PA_CONTEXT_TERMINATED);
+
+ if (p->stream) {
+ if ((sst = pa_stream_get_state(p->stream)) == PA_STREAM_FAILED)
+ goto fail;
+
+ assert(sst != PA_STREAM_TERMINATED);
+ }
+
return 0;
+
+fail:
+ if (perror)
+ *perror = pa_context_errno(p->context);
+ return -1;
}
static int iterate(struct pa_simple *p, int block, int *perror) {
@@ -96,7 +109,7 @@ struct pa_simple* pa_simple_new(
struct pa_simple *p;
int error = PA_ERROR_INTERNAL;
- assert(ss);
+ assert(ss && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
p = pa_xmalloc(sizeof(struct pa_simple));
p->context = NULL;
@@ -110,23 +123,25 @@ struct pa_simple* pa_simple_new(
if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name)))
goto fail;
-
- if (pa_context_connect(p->context, server, NULL, NULL) < 0) {
- error = pa_context_errno(p->context);
- goto fail;
- }
+
+ pa_context_connect(p->context, server);
/* Wait until the context is ready */
- while (!pa_context_is_ready(p->context)) {
+ while (pa_context_get_state(p->context) != PA_CONTEXT_READY) {
if (iterate(p, 1, &error) < 0)
goto fail;
}
- if (!(p->stream = pa_stream_new(p->context, dir, dev, stream_name, ss, attr, NULL, NULL)))
+ if (!(p->stream = pa_stream_new(p->context, stream_name, ss)))
goto fail;
+ if (dir == PA_STREAM_PLAYBACK)
+ pa_stream_connect_playback(p->stream, dev, attr);
+ else
+ pa_stream_connect_record(p->stream, dev, attr);
+
/* Wait until the stream is ready */
- while (!pa_stream_is_ready(p->stream)) {
+ while (pa_stream_get_state(p->stream) != PA_STREAM_READY) {
if (iterate(p, 1, &error) < 0)
goto fail;
}
@@ -148,10 +163,10 @@ void pa_simple_free(struct pa_simple *s) {
pa_xfree(s->read_data);
if (s->stream)
- pa_stream_free(s->stream);
+ pa_stream_unref(s->stream);
if (s->context)
- pa_context_free(s->context);
+ pa_context_unref(s->context);
if (s->mainloop)
pa_mainloop_free(s->mainloop);
@@ -172,7 +187,7 @@ int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *pe
if (l > length)
l = length;
- pa_stream_write(p->stream, data, l);
+ pa_stream_write(p->stream, data, l, NULL);
data += l;
length -= l;
}
@@ -193,8 +208,7 @@ static void read_callback(struct pa_stream *s, const void*data, size_t length, v
pa_xfree(p->read_data);
}
- p->read_data = pa_xmalloc(p->read_length = length);
- memcpy(p->read_data, data, length);
+ p->read_data = pa_xmemdup(data, p->read_length = length);
p->read_index = 0;
}
@@ -235,23 +249,31 @@ int pa_simple_read(struct pa_simple *p, void*data, size_t length, int *perror) {
return 0;
}
-static void drain_complete(struct pa_stream *s, void *userdata) {
+static void drain_complete(struct pa_stream *s, int success, void *userdata) {
struct pa_simple *p = userdata;
assert(s && p);
- p->drained = 1;
+ p->drained = success ? 1 : -1;
}
int pa_simple_drain(struct pa_simple *p, int *perror) {
+ struct pa_operation *o;
+
assert(p && p->direction == PA_STREAM_PLAYBACK);
p->drained = 0;
- pa_stream_drain(p->stream, drain_complete, p);
+ o = pa_stream_drain(p->stream, drain_complete, p);
while (!p->drained) {
if (iterate(p, 1, perror) < 0) {
- pa_stream_drain(p->stream, NULL, NULL);
+ pa_operation_cancel(o);
+ pa_operation_unref(o);
return -1;
}
}
+ pa_operation_unref(o);
+
+ if (p->drained < 0 && perror)
+ *perror = pa_context_errno(p->context);
+
return 0;
}
diff --git a/polyp/polyplib-simple.h b/polyp/polyplib-simple.h
index 0544410c..ee2e27e3 100644
--- a/polyp/polyplib-simple.h
+++ b/polyp/polyplib-simple.h
@@ -26,24 +26,41 @@
#include "sample.h"
#include "polyplib-def.h"
+#include "cdecl.h"
+/** \file
+ * A simple but limited synchronous playback and recording API. */
+
+PA_C_DECL_BEGIN
+
+/** \struct pa_simple
+ * A simple connection object */
struct pa_simple;
+/** Create a new connection to the server */
struct pa_simple* pa_simple_new(
- const char *server,
- const char *name,
- enum pa_stream_direction dir,
- const char *dev,
- const char *stream_name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- int *error);
+ const char *server, /**< Server name, or NULL for default */
+ const char *name, /**< A descriptive name for this client (application name, ...) */
+ enum pa_stream_direction dir, /**< Open this stream for recording or playback? */
+ const char *dev, /**< Sink (resp. source) name, or NULL for default */
+ const char *stream_name, /**< A descriptive name for this client (application name, song title, ...) */
+ const struct pa_sample_spec *ss, /**< The sample type to use */
+ const struct pa_buffer_attr *attr, /**< Buffering attributes, or NULL for default */
+ int *error /**< A pointer where the error code is stored when the routine returns NULL. It is OK to pass NULL here. */
+ );
+/** Close and free the connection to the server. The connection objects becomes invalid when this is called. */
void pa_simple_free(struct pa_simple *s);
+/** Write some data to the server */
int pa_simple_write(struct pa_simple *s, const void*data, size_t length, int *error);
+
+/** Wait until all data already written is played by the daemon */
int pa_simple_drain(struct pa_simple *s, int *error);
+/** Read some data from the server */
int pa_simple_read(struct pa_simple *s, void*data, size_t length, int *error);
+PA_C_DECL_END
+
#endif
diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c
index 35001d3d..362dbad1 100644
--- a/polyp/polyplib-stream.c
+++ b/polyp/polyplib-stream.c
@@ -23,576 +23,217 @@
#include <config.h>
#endif
-#include <stdio.h>
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
-#include "pstream.h"
-#include "dynarray.h"
-#include "socket-client.h"
-#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
-
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
-};
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
-
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
+#include <stdio.h>
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
+#include "polyplib-internal.h"
+#include "xmalloc.h"
+#include "pstream-util.h"
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
+struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const struct pa_sample_spec *ss) {
+ assert(c && ss);
+ struct pa_stream *s;
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
+ s = pa_xmalloc(sizeof(struct pa_stream));
+ s->ref = 1;
+ s->context = c;
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
+ s->read_callback = NULL;
+ s->read_userdata = NULL;
+ s->write_callback = NULL;
+ s->write_userdata = NULL;
+ s->state_callback = NULL;
+ s->state_userdata = NULL;
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
+ s->state = PA_STREAM_NODIRECTION;
+ s->name = pa_xstrdup(name);
+ s->sample_spec = *ss;
+ s->channel = 0;
+ s->channel_valid = 0;
+ s->device_index = PA_INVALID_INDEX;
+ s->requested_bytes = 0;
+ s->state = PA_STREAM_DISCONNECTED;
+ memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-void pa_context_free(struct pa_context *c) {
- assert(c);
+ PA_LLIST_PREPEND(struct pa_stream, c->streams, s);
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
+ return pa_stream_ref(s);
}
-static void stream_dead(struct pa_stream *s) {
+static void stream_free(struct pa_stream *s) {
assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
+ pa_xfree(s->name);
+ pa_xfree(s);
}
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
+void pa_stream_unref(struct pa_stream *s) {
+ assert(s && s->ref >= 1);
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
+ if (--(s->ref) == 0)
+ stream_free(s);
}
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
+struct pa_stream* pa_stream_ref(struct pa_stream *s) {
+ assert(s && s->ref >= 1);
+ s->ref++;
+ return s;
}
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
-
- return 0;
- }
-
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
+enum pa_stream_state pa_stream_get_state(struct pa_stream *s) {
+ assert(s && s->ref >= 1);
+ return s->state;
}
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
-
- if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
- }
-
- return;
+struct pa_context* pa_stream_get_context(struct pa_stream *s) {
+ assert(s && s->ref >= 1);
+ return s->context;
}
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
-
- pa_socket_client_free(client);
- c->client = NULL;
-
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
+uint32_t pa_stream_get_index(struct pa_stream *s) {
+ assert(s && s->ref >= 1);
+ return s->device_index;
}
-
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
+void pa_stream_set_state(struct pa_stream *s, enum pa_stream_state st) {
+ assert(s && s->ref >= 1);
- freeaddrinfo(result);
+ if (s->state == st)
+ return;
- return sa;
-}
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
+ pa_stream_ref(s);
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
- }
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
+ s->state = st;
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
+ if ((st == PA_STREAM_FAILED || st == PA_STREAM_TERMINATED) && s->context) {
+ if (s->channel_valid)
+ pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
+ PA_LLIST_REMOVE(struct pa_stream, s->context->streams, s);
+ pa_stream_unref(s);
}
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
-}
-
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
-}
-
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
+ if (s->state_callback)
+ s->state_callback(s, s->state_userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
+ pa_stream_unref(s);
}
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+void pa_command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct pa_context *c = userdata;
struct pa_stream *s;
uint32_t channel;
assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
+ pa_context_ref(c);
+
if (pa_tagstruct_getu32(t, &channel) < 0 ||
!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
+ goto finish;
}
if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
+ goto finish;
c->error = PA_ERROR_KILLED;
- stream_dead(s);
+ pa_stream_set_state(s, PA_STREAM_FAILED);
+
+finish:
+ pa_context_unref(c);
}
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+void pa_command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct pa_stream *s;
struct pa_context *c = userdata;
uint32_t bytes, channel;
assert(pd && command == PA_COMMAND_REQUEST && t && c);
+ pa_context_ref(c);
+
if (pa_tagstruct_getu32(t, &channel) < 0 ||
pa_tagstruct_getu32(t, &bytes) < 0 ||
!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
+ goto finish;
}
if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
+ goto finish;
- if (s->state != STREAM_READY)
- return;
+ if (s->state != PA_STREAM_READY)
+ goto finish;
+
+ pa_stream_ref(s);
s->requested_bytes += bytes;
if (s->requested_bytes && s->write_callback)
s->write_callback(s, s->requested_bytes, s->write_userdata);
+
+ pa_stream_unref(s);
+
+finish:
+ pa_context_unref(c);
}
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
+ assert(pd && s && s->state == PA_STREAM_CREATING);
+ pa_stream_ref(s);
+
if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
+ if (pa_context_handle_error(s->context, command, t) < 0)
+ goto finish;
+
+ pa_stream_set_state(s, PA_STREAM_FAILED);
+ goto finish;
}
if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
+ pa_context_fail(s->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
s->channel_valid = 1;
pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
+ pa_stream_set_state(s, PA_STREAM_READY);
+
+finish:
+ pa_stream_unref(s);
}
-static void create_stream(struct pa_stream *s, const char *dev) {
+static void create_stream(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr) {
struct pa_tagstruct *t;
uint32_t tag;
- assert(s);
+ assert(s && s->ref >= 1 && s->state == PA_STREAM_DISCONNECTED);
+
+ pa_stream_ref(s);
+
+ if (attr)
+ s->buffer_attr = *attr;
+ else {
+ s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
+ s->buffer_attr.tlength = DEFAULT_TLENGTH;
+ s->buffer_attr.prebuf = DEFAULT_PREBUF;
+ s->buffer_attr.minreq = DEFAULT_MINREQ;
+ s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
+ }
- s->state = STREAM_CREATING;
+ pa_stream_set_state(s, PA_STREAM_CREATING);
t = pa_tagstruct_new(NULL, 0);
assert(t);
+
+ if (!dev) {
+ if (s->direction == PA_STREAM_PLAYBACK)
+ dev = getenv(ENV_DEFAULT_SINK);
+ else
+ dev = getenv(ENV_DEFAULT_SOURCE);
+ }
pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
pa_tagstruct_putu32(t, tag = s->context->ctag++);
@@ -609,135 +250,40 @@ static void create_stream(struct pa_stream *s, const char *dev) {
pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
+ pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s);
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
+ pa_stream_unref(s);
}
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
+void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr) {
+ assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1);
+ s->direction = PA_STREAM_PLAYBACK;
+ create_stream(s, dev, attr);
}
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
+void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr) {
+ assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1);
+ s->direction = PA_STREAM_RECORD;
+ create_stream(s, dev, attr);
}
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
+void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void (*free_cb)(void *p)) {
struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
+ assert(s && s->context && data && length && s->state == PA_STREAM_READY && s->ref >= 1);
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
+ if (free_cb) {
+ chunk.memblock = pa_memblock_new_user((void*) data, length, free_cb);
+ assert(chunk.memblock && chunk.memblock->data);
+ } else {
+ chunk.memblock = pa_memblock_new(length);
+ assert(chunk.memblock && chunk.memblock->data);
+ memcpy(chunk.memblock->data, data, length);
+ }
chunk.index = 0;
chunk.length = length;
pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
if (length < s->requested_bytes)
s->requested_bytes -= length;
@@ -746,805 +292,163 @@ void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
}
size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
+ assert(s && s->state == PA_STREAM_READY && s->ref >= 1);
return s->requested_bytes;
}
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
-}
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
+struct pa_operation * pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
- assert(s && s->state == STREAM_READY);
+ assert(s && s->ref >= 1 && s->state == PA_STREAM_READY);
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
-
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
+ o = pa_operation_new(s->context, s);
+ assert(o);
+ o->callback = cb;
+ o->userdata = userdata;
t = pa_tagstruct_new(NULL, 0);
assert(t);
-
pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
pa_tagstruct_putu32(t, tag = s->context->ctag++);
pa_tagstruct_putu32(t, s->channel);
pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
+ pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o);
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
+ return pa_operation_ref(o);
}
static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
+ struct pa_operation *o = userdata;
uint32_t latency;
- assert(pd && s);
+ assert(pd && o && o->stream && o->context);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
+ latency = (uint32_t) -1;
+ } else if (pa_tagstruct_getu32(t, &latency) < 0 || !pa_tagstruct_eof(t)) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
+ if (o->callback) {
+ void (*cb)(struct pa_stream *s, uint32_t latency, void *userdata) = o->callback;
+ cb(o->stream, latency, o->userdata);
}
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
+struct pa_operation* pa_stream_get_latency(struct pa_stream *s, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
uint32_t tag;
+ struct pa_operation *o;
struct pa_tagstruct *t;
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
+ o = pa_operation_new(s->context, s);
+ assert(o);
+ o->callback = cb;
+ o->userdata = userdata;
- if (cb == NULL)
- return;
-
t = pa_tagstruct_new(NULL, 0);
assert(t);
pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
-}
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
+ pa_tagstruct_putu32(t, tag = s->context->ctag++);
+ pa_tagstruct_putu32(t, s->channel);
+ pa_pstream_send_tagstruct(s->context->pstream, t);
+ pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, o);
- return s;
+ return pa_operation_ref(o);
}
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+void pa_stream_disconnect_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
+ assert(pd && s && s->ref >= 1);
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
+ pa_stream_ref(s);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ if (pa_context_handle_error(s->context, command, t) < 0)
+ goto finish;
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
+ pa_stream_set_state(s, PA_STREAM_FAILED);
+ goto finish;
+ } else if (!pa_tagstruct_eof(t)) {
+ pa_context_fail(s->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
+ pa_stream_set_state(s, PA_STREAM_TERMINATED);
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
+finish:
+ pa_stream_unref(s);
}
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+void pa_stream_disconnect(struct pa_stream *s) {
struct pa_tagstruct *t;
uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
-
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
-
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
+ assert(s && s->ref >= 1);
- if (!cb)
+ if (!s->channel_valid || !s->context->state == PA_CONTEXT_READY)
return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ pa_stream_ref(s);
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
-}
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
-}
-
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
+ pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
+ (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
+ pa_tagstruct_putu32(t, tag = s->context->ctag++);
+ pa_tagstruct_putu32(t, s->channel);
+ pa_pstream_send_tagstruct(s->context->pstream, t);
+ pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s);
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
+ pa_stream_unref(s);
}
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
+void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
+ assert(s && s->ref >= 1);
+ s->read_callback = cb;
+ s->read_userdata = userdata;
}
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
+void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
+ assert(s && s->ref >= 1);
+ s->write_callback = cb;
+ s->write_userdata = userdata;
}
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
+void pa_stream_set_state_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
+ assert(s && s->ref >= 1);
+ s->state_callback = cb;
+ s->state_userdata = userdata;
}
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
+void pa_stream_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ int success = 1;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
+ success = 0;
+ } else if (!pa_tagstruct_eof(t)) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
+ if (o->callback) {
+ void (*cb)(struct pa_stream *s, int success, void *userdata) = o->callback;
+ cb(o->stream, success, o->userdata);
}
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
-}
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h
index a0dd9f9c..41801c6c 100644
--- a/polyp/polyplib-stream.h
+++ b/polyp/polyplib-stream.h
@@ -1,5 +1,5 @@
-#ifndef foopolyplibhfoo
-#define foopolyplibhfoo
+#ifndef foopolyplibstreamhfoo
+#define foopolyplibstreamhfoo
/* $Id$ */
@@ -26,153 +26,79 @@
#include "sample.h"
#include "polyplib-def.h"
-#include "mainloop-api.h"
+#include "cdecl.h"
+#include "polyplib-operation.h"
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
-struct pa_context;
-struct pa_stream;
+/** \file
+ * Audio streams for input, output and sample upload */
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
-void pa_context_unref(struct pa_context *c);
-struct pa_context* pa_context_ref(struct pa_context *c);
+PA_C_DECL_BEGIN
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
+/** The state of a stream */
+enum pa_stream_state {
+ PA_STREAM_DISCONNECTED, /**< The stream is not yet connected to any sink or source */
+ PA_STREAM_CREATING, /**< The stream is being created */
+ PA_STREAM_READY, /**< The stream is established, you may pass audio data to it now */
+ PA_STREAM_FAILED, /**< An error occured that made the stream invalid */
+ PA_STREAM_TERMINATED, /**< The stream has been terminated cleanly */
+};
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
-int pa_context_errno(struct pa_context *c);
+/** \struct pa_stream
+ * A stream for playback or recording */
+struct pa_stream;
-int pa_context_is_pending(struct pa_context *c);
+/** Create a new, unconnected stream with the specified name and sample type */
+struct pa_stream* pa_stream_new(struct pa_context *c, const char *name, const struct pa_sample_spec *ss);
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
+/** Decrease the reference counter by one */
void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
-
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
+/** Increase the reference counter by one */
+struct pa_stream *pa_stream_ref(struct pa_stream *s);
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
+/** Return the current state of the stream */
+enum pa_stream_state pa_stream_get_state(struct pa_stream *p);
+/** Return the context this stream is attached to */
struct pa_context* pa_stream_get_context(struct pa_stream *p);
+/** Return the device (sink input or source output) index this stream is connected to */
uint32_t pa_stream_get_index(struct pa_stream *s);
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-struct pa_sink_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t volume;
- uint32_t monitor_source;
- const char *monitor_source_name;
- uint32_t latency;
-};
-
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t monitor_of_sink;
- const char *monitor_of_sink_name;
-};
-
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_server_info {
- const char *user_name;
- const char *host_name;
- const char *server_version;
- const char *server_name;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
+/** Connect the stream to a sink */
+void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr);
-struct pa_module_info {
- uint32_t index;
- const char*name, *argument;
- uint32_t n_used, auto_unload;
-};
+/** Connect the stream to a source */
+void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr);
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
+/** Disconnect a stream from a source/sink */
+void pa_stream_disconnect(struct pa_stream *s);
-struct pa_client_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- const char *protocol_name;
-};
+/** Write some data to the server (for playback sinks), if free_cb is
+ * non-NULL this routine is called when all data has been written out
+ * and an internal reference to the specified data is kept, the data
+ * is not copied. If NULL, the data is copied into an internal
+ * buffer. */
+void pa_stream_write(struct pa_stream *p, const void *data, size_t length, void (*free_cb)(void *p));
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_sink_input_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t sink;
- struct pa_sample_spec sample_spec;
- uint32_t volume;
- uint32_t latency;
-};
-
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
+/** Return the amount of bytes that may be written using pa_stream_write() */
+size_t pa_stream_writable_size(struct pa_stream *p);
-struct pa_source_output_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t source;
- struct pa_sample_spec sample_spec;
-};
+/** Drain a playback stream */
+struct pa_operation* pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
+/** Get the playback latency of a stream */
+struct pa_operation* pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+/** Set the callback function that is called whenever the state of the stream changes */
+void pa_stream_set_state_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
+/** Set the callback function that is called when new data may be written to the stream */
+void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
+/** Set the callback function that is called when new data is available from the stream */
+void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_END
#endif
diff --git a/polyp/polyplib-subscribe.c b/polyp/polyplib-subscribe.c
index 35001d3d..a14d0b06 100644
--- a/polyp/polyplib-subscribe.c
+++ b/polyp/polyplib-subscribe.c
@@ -23,1528 +23,52 @@
#include <config.h>
#endif
-#include <stdio.h>
#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
-#include "pstream.h"
-#include "dynarray.h"
-#include "socket-client.h"
+#include "polyplib-subscribe.h"
+#include "polyplib-internal.h"
#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
-};
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
-
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
-
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
-
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
-
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
-
-void pa_context_free(struct pa_context *c) {
- assert(c);
-
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
-}
-
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
-}
-
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
-
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
-}
-
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
-}
-
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
-
- return 0;
- }
-
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
-}
-
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
-
- if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
- }
-
- return;
-}
-
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
-
- pa_socket_client_free(client);
- c->client = NULL;
-
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
-}
-
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
-
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
-
- freeaddrinfo(result);
-
- return sa;
-}
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
-
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
- }
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
-
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
-
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- }
-
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
-}
-
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
-}
-
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
-
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
-
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
-
- s->state = STREAM_CREATING;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_puts(t, s->name);
- pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
-
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
-
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
-}
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s && s->state == STREAM_READY);
-
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
-
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
-}
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
-}
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-
- return s;
-}
-
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
-}
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
-
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
-
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
-}
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
-}
-
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+void pa_command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct pa_context *c = userdata;
enum pa_subscription_event_type e;
uint32_t index;
assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
+ pa_context_ref(c);
+
if (pa_tagstruct_getu32(t, &e) < 0 ||
pa_tagstruct_getu32(t, &index) < 0 ||
!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
+ goto finish;
}
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
+ if (c->subscribe_callback)
c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
+finish:
+ pa_context_unref(c);
}
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
+struct pa_operation* pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
assert(c);
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
+ pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
pa_tagstruct_putu32(t, tag = c->ctag++);
+ pa_tagstruct_putu32(t, cb ? m : 0);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
+ return pa_operation_ref(o);
}
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
diff --git a/polyp/polyplib-subscribe.h b/polyp/polyplib-subscribe.h
index a0dd9f9c..56384915 100644
--- a/polyp/polyplib-subscribe.h
+++ b/polyp/polyplib-subscribe.h
@@ -1,5 +1,5 @@
-#ifndef foopolyplibhfoo
-#define foopolyplibhfoo
+#ifndef foopolyplibsubscribehfoo
+#define foopolyplibsubscribehfoo
/* $Id$ */
@@ -22,157 +22,17 @@
USA.
***/
-#include <sys/types.h>
+#include <inttypes.h>
-#include "sample.h"
#include "polyplib-def.h"
-#include "mainloop-api.h"
+#include "polyplib-context.h"
+#include "cdecl.h"
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
-struct pa_context;
-struct pa_stream;
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
-void pa_context_unref(struct pa_context *c);
-struct pa_context* pa_context_ref(struct pa_context *c);
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
-
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
-int pa_context_errno(struct pa_context *c);
-
-int pa_context_is_pending(struct pa_context *c);
-
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
-
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p);
-
-uint32_t pa_stream_get_index(struct pa_stream *s);
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+PA_C_DECL_BEGIN
-struct pa_sink_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t volume;
- uint32_t monitor_source;
- const char *monitor_source_name;
- uint32_t latency;
-};
+struct pa_operation* pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+void pa_context_set_subscribe_callback(struct pa_context *c, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t monitor_of_sink;
- const char *monitor_of_sink_name;
-};
-
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_server_info {
- const char *user_name;
- const char *host_name;
- const char *server_version;
- const char *server_name;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
-
-struct pa_module_info {
- uint32_t index;
- const char*name, *argument;
- uint32_t n_used, auto_unload;
-};
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_client_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- const char *protocol_name;
-};
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_sink_input_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t sink;
- struct pa_sample_spec sample_spec;
- uint32_t volume;
- uint32_t latency;
-};
-
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_output_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t source;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
-
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_END
#endif
diff --git a/polyp/polyplib.c b/polyp/polyplib.c
deleted file mode 100644
index 35001d3d..00000000
--- a/polyp/polyplib.c
+++ /dev/null
@@ -1,1550 +0,0 @@
-/* $Id$ */
-
-/***
- This file is part of polypaudio.
-
- polypaudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2 of the License,
- or (at your option) any later version.
-
- polypaudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with polypaudio; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- USA.
-***/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
-#include "pstream.h"
-#include "dynarray.h"
-#include "socket-client.h"
-#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
-
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
-};
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
-
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
-
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
-
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
-
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
-
-void pa_context_free(struct pa_context *c) {
- assert(c);
-
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
-}
-
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
-}
-
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
-
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
-}
-
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
-}
-
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
-
- return 0;
- }
-
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
-}
-
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
-
- if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
- }
-
- return;
-}
-
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
-
- pa_socket_client_free(client);
- c->client = NULL;
-
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
-}
-
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
-
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
-
- freeaddrinfo(result);
-
- return sa;
-}
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
-
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
- }
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
-
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
-
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- }
-
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
-}
-
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
-}
-
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
-
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
-
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
-
- s->state = STREAM_CREATING;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_puts(t, s->name);
- pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
-
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
-
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
-}
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s && s->state == STREAM_READY);
-
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
-
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
-}
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
-}
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-
- return s;
-}
-
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
-}
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
-
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
-
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
-}
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
-}
-
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
-}
-
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
-}
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
diff --git a/polyp/polyplib.h b/polyp/polyplib.h
index a0dd9f9c..b9e5637c 100644
--- a/polyp/polyplib.h
+++ b/polyp/polyplib.h
@@ -22,157 +22,13 @@
USA.
***/
-#include <sys/types.h>
-
+#include "mainloop-api.h"
#include "sample.h"
#include "polyplib-def.h"
-#include "mainloop-api.h"
-
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
-struct pa_context;
-struct pa_stream;
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
-void pa_context_unref(struct pa_context *c);
-struct pa_context* pa_context_ref(struct pa_context *c);
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
-
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
-int pa_context_errno(struct pa_context *c);
-
-int pa_context_is_pending(struct pa_context *c);
-
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
-
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p);
-
-uint32_t pa_stream_get_index(struct pa_stream *s);
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-struct pa_sink_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t volume;
- uint32_t monitor_source;
- const char *monitor_source_name;
- uint32_t latency;
-};
-
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t monitor_of_sink;
- const char *monitor_of_sink_name;
-};
-
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_server_info {
- const char *user_name;
- const char *host_name;
- const char *server_version;
- const char *server_name;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
-
-struct pa_module_info {
- uint32_t index;
- const char*name, *argument;
- uint32_t n_used, auto_unload;
-};
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_client_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- const char *protocol_name;
-};
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_sink_input_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t sink;
- struct pa_sample_spec sample_spec;
- uint32_t volume;
- uint32_t latency;
-};
-
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_output_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t source;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
-
-#ifdef __cplusplus
-}
-#endif
+#include "polyplib-context.h"
+#include "polyplib-stream.h"
+#include "polyplib-introspect.h"
+#include "polyplib-subscribe.h"
+#include "polyplib-scache.h"
#endif
diff --git a/polyp/sample-util.c b/polyp/sample-util.c
index 5b1cd626..8f5558a4 100644
--- a/polyp/sample-util.c
+++ b/polyp/sample-util.c
@@ -135,10 +135,3 @@ void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec,
}
}
-uint32_t pa_volume_multiply(uint32_t a, uint32_t b) {
- uint64_t p = a;
- p *= b;
- p /= PA_VOLUME_NORM;
-
- return (uint32_t) p;
-}
diff --git a/polyp/sample-util.h b/polyp/sample-util.h
index 73101ab4..66f40a16 100644
--- a/polyp/sample-util.h
+++ b/polyp/sample-util.h
@@ -26,8 +26,6 @@
#include "memblock.h"
#include "memchunk.h"
-#define PA_VOLUME_NORM (0x100)
-#define PA_VOLUME_MUTE (0)
struct pa_memblock *pa_silence_memblock(struct pa_memblock* b, const struct pa_sample_spec *spec);
void pa_silence_memchunk(struct pa_memchunk *c, const struct pa_sample_spec *spec);
@@ -43,6 +41,4 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz
void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, uint32_t volume);
-uint32_t pa_volume_multiply(uint32_t a, uint32_t b);
-
#endif
diff --git a/polyp/sample.c b/polyp/sample.c
index e4c4bd52..4f93f2b7 100644
--- a/polyp/sample.c
+++ b/polyp/sample.c
@@ -96,3 +96,11 @@ void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec) {
assert(pa_sample_spec_valid(spec));
snprintf(s, l, "%s %uch %uHz", table[spec->format], spec->channels, spec->rate);
}
+
+uint32_t pa_volume_multiply(uint32_t a, uint32_t b) {
+ uint64_t p = a;
+ p *= b;
+ p /= PA_VOLUME_NORM;
+
+ return (uint32_t) p;
+}
diff --git a/polyp/sample.h b/polyp/sample.h
index 25027879..a7cde093 100644
--- a/polyp/sample.h
+++ b/polyp/sample.h
@@ -25,9 +25,9 @@
#include <inttypes.h>
#include <sys/types.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include "cdecl.h"
+
+PA_C_DECL_BEGIN
enum pa_sample_format {
PA_SAMPLE_U8,
@@ -49,10 +49,11 @@ enum pa_sample_format {
#endif
#define PA_SAMPLE_FLOAT32 PA_SAMPLE_FLOAT32NE
+/** A sample format and attribute specification */
struct pa_sample_spec {
- enum pa_sample_format format;
- uint32_t rate;
- uint8_t channels;
+ enum pa_sample_format format; /**< The sample format */
+ uint32_t rate; /**< The sample rate. (e.g. 44100) */
+ uint8_t channels; /**< Audio channels. (1 for mono, 2 for stereo, ...) */
};
size_t pa_bytes_per_second(const struct pa_sample_spec *spec);
@@ -64,8 +65,10 @@ int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_s
#define PA_SAMPLE_SNPRINT_MAX_LENGTH 32
void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec);
-#ifdef __cplusplus
-}
-#endif
+#define PA_VOLUME_NORM (0x100)
+#define PA_VOLUME_MUTE (0)
+uint32_t pa_volume_multiply(uint32_t a, uint32_t b);
+
+PA_C_DECL_END
#endif
diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index e8cb2f92..dffbfe7d 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -120,7 +120,7 @@ static int do_connect(struct pa_socket_client *c, const struct sockaddr *sa, soc
if ((r = connect(c->fd, sa, len)) < 0) {
if (errno != EINPROGRESS) {
- fprintf(stderr, "connect(): %s\n", strerror(errno));
+ /*fprintf(stderr, "connect(): %s\n", strerror(errno));*/
return -1;
}
diff --git a/polyp/socket-client.h b/polyp/socket-client.h
index 2a89210e..7b9e2a72 100644
--- a/polyp/socket-client.h
+++ b/polyp/socket-client.h
@@ -23,6 +23,8 @@
***/
#include <inttypes.h>
+#include <sys/socket.h>
+
#include "mainloop-api.h"
#include "iochannel.h"
diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h
index aefd03c4..bcd7f456 100644
--- a/polyp/tagstruct.h
+++ b/polyp/tagstruct.h
@@ -48,6 +48,4 @@ int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t le
int pa_tagstruct_eof(struct pa_tagstruct*t);
const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l);
-
-
#endif
diff --git a/polyp/xmalloc.c b/polyp/xmalloc.c
index 8ff3054d..7d8b4821 100644
--- a/polyp/xmalloc.c
+++ b/polyp/xmalloc.c
@@ -52,25 +52,36 @@ void *pa_xrealloc(void *ptr, size_t size) {
return p;
}
-char *pa_xstrdup(const char *s) {
- if (!s)
+void* pa_xmemdup(const void *p, size_t l) {
+ if (!p)
return NULL;
else {
- char *r = strdup(s);
- if (!r)
- oom();
-
+ char *r = pa_xmalloc(l);
+ memcpy(r, p, l);
return r;
}
}
+char *pa_xstrdup(const char *s) {
+ if (!s)
+ return NULL;
+
+ return pa_xmemdup(s, strlen(s)+1);
+}
+
char *pa_xstrndup(const char *s, size_t l) {
if (!s)
return NULL;
else {
- char *r = strndup(s, l);
- if (!r)
- oom();
+ char *r;
+ size_t t = strlen(s);
+
+ if (t > l)
+ t = l;
+
+ r = pa_xmemdup(s, t+1);
+ r[t] = 0;
return r;
}
}
+
diff --git a/polyp/xmalloc.h b/polyp/xmalloc.h
index 45209b05..eaf8f708 100644
--- a/polyp/xmalloc.h
+++ b/polyp/xmalloc.h
@@ -12,4 +12,6 @@ void *pa_xrealloc(void *ptr, size_t size);
char *pa_xstrdup(const char *s);
char *pa_xstrndup(const char *s, size_t l);
+void* pa_xmemdup(const void *p, size_t l);
+
#endif