Add new edbus library, aka e_dbus v2

SVN revision: 76775
This commit is contained in:
Lucas De Marchi 2012-09-17 20:41:05 +00:00
parent aeadf86ba6
commit 5934eb6788
51 changed files with 9090 additions and 0 deletions

43
legacy/edbus/.gitignore vendored Normal file
View File

@ -0,0 +1,43 @@
*.o
*.lo
*~
.libs
.deps
.dirstamp
aclocal.m4
autom4te.cache/
compile
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
depcomp
install-sh
libtool
ltmain.sh
m4/libtool.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
Makefile
Makefile.in
missing
stamp-h1
edbus-*.tar.*
edbus.pc
libedbus.la
src/examples/connman-list-services
src/examples/ofono-dial
src/examples/banshee
src/examples/complex_types
src/examples/complex_types_server
src/examples/server
src/examples/client
doc/Doxyfile
doc/html/
doc/latex/
doc/man/

4
legacy/edbus/AUTHORS Normal file
View File

@ -0,0 +1,4 @@
Gustavo Sverzut Barbieri <barbieri@profusion.mobi>
José Roberto de Souza <zehortigoza@profusion.mobi>
Leandro Pereira <leandro@profusion.mobi>
Lucas De Marchi <lucas.demarchi@profusion.mobi>

120
legacy/edbus/Makefile.am Normal file
View File

@ -0,0 +1,120 @@
ACLOCAL_AMFLAGS = -I m4
CLEANFILES =
MAINTAINERCLEANFILES =
EXTRA_DIST =
SUBDIRS = doc
AM_MAKEFLAGS = --no-print-directory
AM_CFLAGS = \
-include $(top_builddir)/config.h \
-I$(top_srcdir)/src/lib \
@ECORE_CFLAGS@ \
@DBUS_CFLAGS@
AM_CPPFLAGS = -DEFL_EDBUS_BUILD=1
includedir = @includedir@/edbus-@VMAJ@/
SED_PROCESS = \
$(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(SED) \
-e 's,@VERSION\@,$(VERSION),g' \
-e 's,@prefix\@,$(prefix),g' \
-e 's,@exec_prefix\@,$(exec_prefix),g' \
-e 's,@libdir\@,$(libdir),g' \
-e 's,@includedir\@,$(includedir),g' \
< $< > $@ || rm $@
%.pc: %.pc.in Makefile
$(SED_PROCESS)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = edbus.pc
CLEANFILES += edbus.pc
EXTRA_DIST += edbus.pc.in
EXTRA_DIST += \
m4/efl_doxygen.m4 \
m4/efl_compiler_flag.m4
MAINTAINERCLEANFILES += \
aclocal.m4 \
compile \
config.guess \
config.h.in \
config.sub \
configure \
depcomp \
install-sh \
ltmain.sh \
Makefile.in \
missing \
mkinstalldirs
lib_LTLIBRARIES = libedbus.la
include_HEADERS = \
src/lib/EDBus.h \
src/lib/edbus_connection.h \
src/lib/edbus_freedesktop.h \
src/lib/edbus_message.h \
src/lib/edbus_object.h \
src/lib/edbus_pending.h \
src/lib/edbus_proxy.h \
src/lib/edbus_service.h \
src/lib/edbus_signal_handler.h
libedbus_la_LIBADD = @ECORE_LIBS@ @DBUS_LIBS@
libedbus_la_SOURCES = \
src/lib/edbus_private.h \
src/lib/edbus_private_types.h \
src/lib/edbus_proxy.c \
src/lib/edbus_core.c \
src/lib/edbus_message.c \
src/lib/edbus_object.c \
src/lib/edbus_pending.c \
src/lib/edbus_freedesktop.c \
src/lib/edbus_service.c \
src/lib/edbus_signal_handler.c
noinst_PROGRAMS = \
src/examples/connman-list-services \
src/examples/ofono-dial \
src/examples/banshee \
src/examples/complex_types \
src/examples/complex_types_server \
src/examples/server \
src/examples/client
EXAMPLES_LIBS = libedbus.la @ECORE_LIBS@
src_examples_connman_list_services_SOURCES = \
src/examples/connman-list-services.c
src_examples_connman_list_services_LDADD = $(EXAMPLES_LIBS)
src_examples_ofono_dial_SOURCES = src/examples/ofono-dial.c
src_examples_ofono_dial_LDADD = $(EXAMPLES_LIBS)
src_examples_banshee_SOURCES = src/examples/banshee.c
src_examples_banshee_LDADD = $(EXAMPLES_LIBS)
src_examples_complex_types_SOURCES = src/examples/complex_types.c
src_examples_complex_types_LDADD = $(EXAMPLES_LIBS)
src_examples_complex_types_server_SOURCES = src/examples/complex_types_server.c
src_examples_complex_types_server_LDADD = $(EXAMPLES_LIBS)
src_examples_server_SOURCES = src/examples/server.c
src_examples_server_LDADD = $(EXAMPLES_LIBS)
src_examples_client_SOURCES = src/examples/client.c
src_examples_client_LDADD = $(EXAMPLES_LIBS)
.PHONY: doc
# Documentation
doc:
@echo "entering doc/"
make -C doc doc

7
legacy/edbus/autogen.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
autoreconf -f -i
if [ -z "$NOCONFIGURE" ]; then
./configure "$@"
fi

114
legacy/edbus/configure.ac Normal file
View File

@ -0,0 +1,114 @@
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
m4_define([v_maj], [1])
m4_define([v_min], [7])
m4_define([v_mic], [99])
m4_define([v_rev], m4_esyscmd([(svnversion "${SVN_REPO_PATH:-.}" | grep -v '\(export\|Unversioned directory\)' || echo 0) | awk -F : '{printf("%s\n", $1);}' | tr -d ' :MSP\n']))
m4_if(v_rev, [0], [m4_define([v_rev], m4_esyscmd([git log 2> /dev/null | (grep -m1 git-svn-id || echo 0) | sed -e 's/.*@\([0-9]*\).*/\1/' | tr -d '\n']))])
##-- When released, remove the dnl on the below line
dnl m4_undefine([v_rev])
##-- When doing snapshots - change soname. remove dnl on below line
dnl m4_define([relname], [ver-pre-svn-07])
dnl m4_define([v_rel], [-release relname])
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
m4_ifdef([v_rev], [m4_define([v_ver], [v_maj.v_min.v_mic.v_rev])],
[m4_define([v_ver], [v_maj.v_min.v_mic])])
m4_define([lt_cur], m4_eval(v_maj + v_min))
m4_define([lt_rev], v_mic)
m4_define([lt_age], v_min)
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
AC_INIT([edbus], [v_ver], [enlightenment-devel@lists.sourceforge.net])
AC_PREREQ([2.60])
AM_INIT_AUTOMAKE([foreign subdir-objects])
AM_CONFIG_HEADER([config.h])
AC_CONFIG_MACRO_DIR([m4])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
PKG_PROG_PKG_CONFIG
EFL_COMPILER_FLAG([-Wall])
EFL_COMPILER_FLAG([-Wextra])
EFL_COMPILER_FLAG([-Wshadow])
EFL_COMPILER_FLAG([-Wno-unused-parameter])
EFL_COMPILER_FLAG([-Wvla])
EFL_COMPILER_FLAG([-Wundef])
EFL_COMPILER_FLAG([-Wformat=2])
EFL_COMPILER_FLAG([-Wlogical-op])
EFL_COMPILER_FLAG([-Wsign-compare])
EFL_COMPILER_FLAG([-Wformat-security])
EFL_COMPILER_FLAG([-Wmissing-include-dirs])
EFL_COMPILER_FLAG([-Wformat-nonliteral])
EFL_COMPILER_FLAG([-Wold-style-definition])
EFL_COMPILER_FLAG([-Wpointer-arith])
EFL_COMPILER_FLAG([-Winit-self])
EFL_COMPILER_FLAG([-Wdeclaration-after-statement])
EFL_COMPILER_FLAG([-Wmissing-declarations])
EFL_COMPILER_FLAG([-Wmissing-noreturn])
EFL_COMPILER_FLAG([-Wendif-labels])
EFL_COMPILER_FLAG([-Wstrict-aliasing=2])
EFL_COMPILER_FLAG([-Wwrite-strings])
EFL_COMPILER_FLAG([-Wno-long-long])
EFL_COMPILER_FLAG([-Wno-overlength-strings])
EFL_COMPILER_FLAG([-Wno-missing-field-initializers])
EFL_COMPILER_FLAG([-Wno-nested-externs])
EFL_COMPILER_FLAG([-Wchar-subscripts])
EFL_COMPILER_FLAG([-Wtype-limits])
EFL_COMPILER_FLAG([-Wuninitialized])
AC_LANG_C
AC_PROG_CC
AC_PROG_MKDIR_P
AM_PROG_CC_C_O
AC_C___ATTRIBUTE__
AC_C_VA_LIST_AS_ARRAY
AC_DISABLE_STATIC
define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl
define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
AC_PROG_LIBTOOL
# doxygen program for documentation building
EFL_CHECK_DOXYGEN([build_doc="yes"], [build_doc="no"])
PKG_CHECK_MODULES([EINA], [eina >= 1.7.0])
PKG_CHECK_MODULES([ECORE], [ecore])
PKG_CHECK_MODULES([DBUS], [dbus-1])
with_max_log_level="EINA_LOG_LEVEL_DBG"
AC_ARG_WITH(maximum-log-level,
[AC_HELP_STRING([--with-maximum-log-level=NUMBER],
[limit log level, any call to EINA_LOG() with values greater than this will be compiled out, ignoring runtime settings, but saving function calls.])],
[with_max_log_level="${withval}"], [:])
AC_DEFINE_UNQUOTED(EINA_LOG_LEVEL_MAXIMUM, ${with_max_log_level}, [if set, logging is limited to this amount.])
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
m4_ifdef([v_rev], , [m4_define([v_rev], [0])])
m4_ifdef([v_rel], , [m4_define([v_rel], [])])
AC_DEFINE_UNQUOTED(VMAJ, [v_maj], [Major version])
AC_DEFINE_UNQUOTED(VMIN, [v_min], [Minor version])
AC_DEFINE_UNQUOTED(VMIC, [v_mic], [Micro version])
AC_DEFINE_UNQUOTED(VREV, [v_rev], [Revison])
version_info="lt_cur:lt_rev:lt_age"
release_info="v_rel"
AC_SUBST(version_info)
AC_SUBST(release_info)
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
VMAJ=v_maj
VMIN=v_min
AC_SUBST(VMAJ)
AC_SUBST(VMIN)
AC_CONFIG_FILES([
Makefile
doc/Makefile
doc/Doxyfile
])
AC_OUTPUT

View File

@ -0,0 +1,227 @@
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = EDBus
PROJECT_NUMBER =
OUTPUT_DIRECTORY = .
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 2
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
EXTENSION_MAPPING =
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
TYPEDEF_HIDES_STRUCT = NO
SYMBOL_CACHE_SIZE = 0
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = NO
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = YES
HIDE_FRIEND_COMPOUNDS = YES
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = NO
SHOW_DIRECTORIES = NO
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = YES
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
INPUT = ../src/lib \
./examples.dox
INPUT_ENCODING = UTF-8
FILE_PATTERNS =
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH = ../src/examples/
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = YES
IMAGE_PATH = ../doc/images/
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = NO
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 2
IGNORE_PREFIX = EDBUS_ edbus_
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER = ./head.html
HTML_FOOTER = ./foot.html
HTML_STYLESHEET = ./e.css
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = YES
HTML_ALIGN_MEMBERS = YES
HTML_DYNAMIC_SECTIONS = NO
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = YES
ENUM_VALUES_PER_LINE = 1
GENERATE_TREEVIEW = NO
USE_INLINE_TREES = NO
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
SEARCHENGINE = NO
SERVER_BASED_SEARCH = NO
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = YES
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
GENERATE_MAN = YES
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = YES
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
GENERATE_AUTOGEN_DEF = NO
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = NO
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = EINA_MAGIC_DEBUG \
__UNUSED__= \
EINA_ARG_NONNULL()= \
EINA_MALLOC= \
EINA_WARN_UNUSED_RESULT= \
EAPI= \
EINA_PURE= \
EINA_CONST=
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
CLASS_DIAGRAMS = NO
MSCGEN_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_NUM_THREADS = 0
DOT_FONTNAME = FreeSans.ttf
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = NO
COLLABORATION_GRAPH = NO
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = NO
INCLUDED_BY_GRAPH = NO
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = NO
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES

View File

@ -0,0 +1,32 @@
MAINTAINERCLEANFILES = Makefile.in
.PHONY: doc
PACKAGE_DOCNAME = $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-doc
if EFL_BUILD_DOC
doc-clean:
rm -rf html/ latex/ $(top_builddir)/$(PACKAGE_DOCNAME).tar*
doc: all
$(efl_doxygen)
cp $(srcdir)/images/* html/
rm -rf $(PACKAGE_DOCNAME).tar*
mkdir -p $(PACKAGE_DOCNAME)/doc
cp -R html/ latex/ $(PACKAGE_DOCNAME)/doc
tar cf $(PACKAGE_DOCNAME).tar $(PACKAGE_DOCNAME)/
bzip2 -9 $(PACKAGE_DOCNAME).tar
rm -rf $(PACKAGE_DOCNAME)/
mv $(PACKAGE_DOCNAME).tar.bz2 $(top_builddir)
clean-local: doc-clean
else
doc:
@echo "Documentation not built. Run ./configure --help"
endif
EXTRA_DIST = Doxyfile.in $(wildcard images/*.*) e.css head.html foot.html

218
legacy/edbus/doc/e.css Normal file
View File

@ -0,0 +1,218 @@
/*
Author:
Andres Blanc <andresblanc@gmail.com>
DaveMDS Andreoli <dave@gurumeditation.it>
Supported Browsers:
ie7, opera9, konqueror4 and firefox3
Please use a different file for ie6, ie5, etc. hacks.
*/
/* Necessary to place the footer at the bottom of the page */
html, body {
height: 100%;
margin: 0px;
padding: 0px;
}
#container {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 auto -53px;
}
#footer, #push {
height: 53px;
}
* html #container {
height: 100%;
}
/* Prevent floating elements overflowing containers */
.clear {
clear: both;
width: 0px;
height: 0px;
}
/* Flexible & centered layout from 750 to 960 pixels */
.layout {
max-width: 960px;
min-width: 760px;
margin-left: auto;
margin-right: auto;
}
body {
/*font-family: Lucida Grande, Helvetica, sans-serif;*/
font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif
}
/* Prevent design overflowing the viewport in small resolutions */
#container {
padding-right: 17px;
padding-left: 17px;
background-image: url(head_bg.png);
background-repeat: repeat-x;
}
#header {
width: 100%;
height: 102px;
}
#header h1 {
width: 63px;
height: 63px;
background-image: url(e.png);
background-repeat: no-repeat;
position: absolute;
margin: 0px;
}
#header h1 span {
display: none;
}
#header h2 {
display: none;
}
/* .menu-container is used to set properties common to .menu and .submenu */
#header .menu-container {
}
#header .menu-container ul {
list-style-type: none;
list-style-position: inside;
margin: 0;
}
#header .menu-container li {
display: block;
float: right;
}
#header .menu {
height: 63px;
display: block;
background-image: url(menu_bg.png);
background-repeat: repeat-x;
}
#header .menu ul {
height: 100%;
display: block;
background-image: url(menu_bg_last.png);
background-repeat: no-repeat;
background-position: top right;
padding-right: 17px;
}
#header .menu li {
height: 100%;
text-align: center;
background-image: url(menu_bg_unsel.png);
background-repeat: no-repeat;
}
#header .menu a {
height: 100%;
display: block;
color: #cdcdcd;
text-decoration: none;
font-size: 10pt;
line-height: 59px;
text-align: center;
padding: 0px 15px 0px 15px;
}
#header .menu li:hover {
background-image: url(menu_bg_hover.png);
background-repeat: no-repeat;
}
#header .menu li:hover a {
color: #FFFFFF;
}
#header .menu li.current {
background-image: url(menu_bg_current.png);
background-repeat: no-repeat;
}
#header .menu li.current a {
color: #646464;
}
/* Hide all the submenus but the current */
#header .submenu ul {
display: none;
}
#header .submenu .current {
display: block;
}
#header .submenu {
font: bold 10px verdana,'Bitstream Vera Sans',helvetica,arial,sans-serif;
margin-top: 10px;
}
#header .submenu a {
color: #888888;
text-decoration: none;
font-size: 0.9em;
line-height: 15px;
padding:0px 5px 0px 5px;
}
#header .submenu a:hover {
color: #444444;
}
#header .submenu li {
border-left: 1px solid #DDDDDD;
}
#header .submenu li:last-child {
border-left: 0;
}
#header .doxytitle {
position: absolute;
font-size: 1.8em;
font-weight: bold;
color: #444444;
line-height: 35px;
}
#header small {
font-size: 0.4em;
}
#footer {
background-image: url(foot_bg.png);
width: 100%;
}
#footer table {
width: 100%;
text-align: center;
white-space: nowrap;
padding: 5px 30px 5px 30px;
font-size: 0.8em;
font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif;
color: #888888;
}
#footer td.copyright {
width: 100%;
}

View File

@ -0,0 +1,55 @@
/**
* @page Examples Examples
*
* Here is a page with some EDBus examples:
*
* @li @ref banshee
* @li @ref simple_dbus_client
* @li @ref simple_dbus_server
* @li @ref complex_types
* @li @ref complex_types_server
* @li @ref connman
* @li @ref ofono
*/
/**
* @page banshee Banshee dbus client
*
* @include banshee.c
*/
/**
* @page simple_dbus_client Simple dbus client
*
* @include client.c
*/
/**
* @page simple_dbus_server Simple dbus server
*
* @include server.c
*/
/**
* @page complex_types Handling with dbus complex types
*
* @include complex_types.c
*/
/**
* @page complex_types_server Handling with dbus complex types server side
*
* @include complex_types_server.c
*/
/**
* @page connman Connman
*
* @include connman-list-services.c
*/
/**
* @page ofono Ofono
*
* @include ofono-dial.c
*/

View File

@ -0,0 +1,19 @@
<div id="push"></div>
</div> <!-- #content -->
</div> <!-- .layout -->
</div> <!-- #container -->
<div id="footer">
<table><tr>
<td class="poweredby"><img src="doxygen.png"></td>
<td class="copyright">Copyright &copy;$year Enlightenment</td>
<td class="generated">Docs generated $datetime</td>
</tr></table>
</div>
</body>
</html>

View File

@ -0,0 +1,67 @@
<html>
<head>
<title>$title</title>
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
<meta name="author" content="Andres Blanc" >
<link rel="icon" href="images/favicon.png" type="image/x-icon">
<link rel="shortcut icon" href="images/favicon.png" type="image/x-icon">
<link rel="icon" href="images/favicon.png" type="image/ico">
<link rel="shortcut icon" href="images/favicon.png" type="image/ico">
<link rel="stylesheet" type="text/css" media="screen" href="e.css">
<link rel="stylesheet" type="text/css" media="screen" href="edoxy.css">
</head>
<body>
<div id="container">
<div id="header">
<div class="layout">
<h1><span>Enlightenment</span></h1>
<h2><span>Beauty at your fingertips</span></h2>
<div class="menu-container">
<div class="menu">
<ul>
<li class="current"><a href="http://web.enlightenment.org/p.php?p=docs">Docs</a></li>
<li><a href="http://trac.enlightenment.org/e">Tracker</a></li>
<li><a href="http://www.enlightenment.org/p.php?p=contact">Contact</a></li>
<li><a href="http://www.enlightenment.org/p.php?p=contribute">Contribute</a></li>
<li><a href="http://www.enlightenment.org/p.php?p=support">Support</a></li>
<li><a href="http://www.enlightenment.org/p.php?p=download">Download</a></li>
<li><a href="http://www.enlightenment.org/p.php?p=about">About</a></li>
<li><a href="http://www.enlightenment.org/p.php?p=news">News</a></li>
<li><a href="http://www.enlightenment.org/">Home</a></li>
</ul>
</div>
</div>
<div class="doxytitle">
$projectname Documentation <small>at $date</small>
</div>
<div class="menu-container">
<!--<div class="submenu">
<ul class="current">
<li><a href="group__EUkit__Group.html">EUkit</a></li>
<li><a href="group__EOfono__Group.html">EOfono</a></li>
<li><a href="group__ENotify__Group.html">ENotify</a></li>
<li><a href="group__EHal__Group.html">EHal</a></li>
<li><a href="group__EConnman__Group.html">EConnman</a></li>
<li><a href="group__EBluez__Group.html">EBluez</a></li>
<li><a href="group__EDbus__Group.html">EDbus</a></li>
<li class="current"><a href="index.html">Main Page</a></li>
</ul>
</div>-->
</div>
<div class="clear"></div>
</div>
</div>
<div id="content">
<div class="layout">

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,483 @@
/*
* This file contain a custom doxygen style to match e.org graphics
*/
/* BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
font-family: Geneva, Arial, Helvetica, sans-serif;
}*/
BODY, TD {
font-size: 12px;
}
H1 {
text-align: center;
font-size: 160%;
}
H2 {
font-size: 120%;
}
H3 {
font-size: 100%;
}
CAPTION {
font-weight: bold
}
DIV.qindex {
width: 100%;
background-color: #e8eef2;
border: 1px solid #84b0c7;
text-align: center;
margin: 2px;
padding: 2px;
line-height: 140%;
}
DIV.navpath {
width: 100%;
background-color: #e8eef2;
border: 1px solid #84b0c7;
text-align: center;
margin: 2px;
padding: 2px;
line-height: 140%;
}
DIV.navtab {
background-color: #e8eef2;
border: 1px solid #84b0c7;
text-align: center;
margin: 2px;
margin-right: 15px;
padding: 2px;
}
TD.navtab {
font-size: 70%;
}
A.qindex {
text-decoration: none;
font-weight: bold;
color: #1A419D;
}
A.qindex:visited {
text-decoration: none;
font-weight: bold;
color: #1A419D
}
A.qindex:hover {
text-decoration: none;
background-color: #ddddff;
}
A.qindexHL {
text-decoration: none;
font-weight: bold;
background-color: #6666cc;
color: #ffffff;
border: 1px double #9295C2;
}
A.qindexHL:hover {
text-decoration: none;
background-color: #6666cc;
color: #ffffff;
}
A.qindexHL:visited {
text-decoration: none;
background-color: #6666cc;
color: #ffffff
}
A.el {
text-decoration: none;
font-weight: bold
}
A.elRef {
font-weight: bold
}
A.code:link {
text-decoration: none;
font-weight: normal;
color: #0000FF
}
A.code:visited {
text-decoration: none;
font-weight: normal;
color: #0000FF
}
A.codeRef:link {
font-weight: normal;
color: #0000FF
}
A.codeRef:visited {
font-weight: normal;
color: #0000FF
}
A:hover, A:visited:hover {
text-decoration: none;
/* background-color: #f2f2ff; */
color: #000055;
}
A.anchor {
color: #000;
}
DL.el {
margin-left: -1cm
}
.fragment {
font-family: monospace, fixed;
font-size: 95%;
}
PRE.fragment {
border: 1px solid #CCCCCC;
background-color: #f5f5f5;
margin-top: 4px;
margin-bottom: 4px;
margin-left: 2px;
margin-right: 8px;
padding-left: 6px;
padding-right: 6px;
padding-top: 4px;
padding-bottom: 4px;
}
DIV.ah {
background-color: black;
font-weight: bold;
color: #ffffff;
margin-bottom: 3px;
margin-top: 3px
}
DIV.groupHeader {
margin-left: 16px;
margin-top: 12px;
margin-bottom: 6px;
font-weight: bold;
}
DIV.groupText {
margin-left: 16px;
font-style: italic;
font-size: 90%
}
/*BODY {
background: white;
color: black;
margin-right: 20px;
margin-left: 20px;
}*/
TD.indexkey {
background-color: #e8eef2;
font-weight: bold;
padding-right : 10px;
padding-top : 2px;
padding-left : 10px;
padding-bottom : 2px;
margin-left : 0px;
margin-right : 0px;
margin-top : 2px;
margin-bottom : 2px;
border: 1px solid #CCCCCC;
}
TD.indexvalue {
background-color: #e8eef2;
font-style: italic;
padding-right : 10px;
padding-top : 2px;
padding-left : 10px;
padding-bottom : 2px;
margin-left : 0px;
margin-right : 0px;
margin-top : 2px;
margin-bottom : 2px;
border: 1px solid #CCCCCC;
}
TR.memlist {
background-color: #f0f0f0;
}
P.formulaDsp {
text-align: center;
}
IMG.formulaDsp {
}
IMG.formulaInl {
vertical-align: middle;
}
SPAN.keyword { color: #008000 }
SPAN.keywordtype { color: #604020 }
SPAN.keywordflow { color: #e08000 }
SPAN.comment { color: #800000 }
SPAN.preprocessor { color: #806020 }
SPAN.stringliteral { color: #002080 }
SPAN.charliteral { color: #008080 }
SPAN.vhdldigit { color: #ff00ff }
SPAN.vhdlchar { color: #000000 }
SPAN.vhdlkeyword { color: #700070 }
SPAN.vhdllogic { color: #ff0000 }
.mdescLeft {
padding: 0px 8px 4px 8px;
font-size: 80%;
font-style: italic;
background-color: #FAFAFA;
border-top: 1px none #E0E0E0;
border-right: 1px none #E0E0E0;
border-bottom: 1px none #E0E0E0;
border-left: 1px none #E0E0E0;
margin: 0px;
}
.mdescRight {
padding: 0px 8px 4px 8px;
font-size: 80%;
font-style: italic;
background-color: #FAFAFA;
border-top: 1px none #E0E0E0;
border-right: 1px none #E0E0E0;
border-bottom: 1px none #E0E0E0;
border-left: 1px none #E0E0E0;
margin: 0px;
}
.memItemLeft {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: solid;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memItemRight {
padding: 1px 8px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: solid;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memTemplItemLeft {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: none;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memTemplItemRight {
padding: 1px 8px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: none;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memTemplParams {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: solid;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
color: #606060;
background-color: #FAFAFA;
font-size: 80%;
}
.search {
color: #003399;
font-weight: bold;
}
FORM.search {
margin-bottom: 0px;
margin-top: 0px;
}
INPUT.search {
font-size: 75%;
color: #000080;
font-weight: normal;
background-color: #e8eef2;
}
TD.tiny {
font-size: 75%;
}
a {
color: #1A41A8;
}
a:visited {
color: #2A3798;
}
.dirtab {
padding: 4px;
border-collapse: collapse;
border: 1px solid #84b0c7;
}
TH.dirtab {
background: #e8eef2;
font-weight: bold;
}
HR {
height: 1px;
border: none;
border-top: 1px solid black;
}
/* Style for detailed member documentation */
.memtemplate {
font-size: 80%;
color: #606060;
font-weight: normal;
margin-left: 3px;
}
.memnav {
background-color: #e8eef2;
border: 1px solid #84b0c7;
text-align: center;
margin: 2px;
margin-right: 15px;
padding: 2px;
}
.memitem {
padding: 4px;
background-color: #eef3f5;
border-width: 1px;
border-style: solid;
border-color: #dedeee;
-moz-border-radius: 8px 8px 8px 8px;
}
.memname {
white-space: nowrap;
font-weight: bold;
}
.memdoc{
padding-left: 10px;
}
.memproto {
background-color: #d5e1e8;
width: 100%;
border-width: 1px;
border-style: solid;
border-color: #84b0c7;
font-weight: bold;
-moz-border-radius: 8px 8px 8px 8px;
}
.paramkey {
text-align: right;
}
.paramtype {
white-space: nowrap;
}
.paramname {
color: #602020;
font-style: italic;
white-space: nowrap;
}
/* End Styling for detailed member documentation */
/* for the tree view */
.ftvtree {
font-family: sans-serif;
margin:0.5em;
}
/* these are for tree view when used as main index */
.directory {
font-size: 9pt;
font-weight: bold;
}
.directory h3 {
margin: 0px;
margin-top: 1em;
font-size: 11pt;
}
/* The following two styles can be used to replace the root node title */
/* with an image of your choice. Simply uncomment the next two styles, */
/* specify the name of your image and be sure to set 'height' to the */
/* proper pixel height of your image. */
/* .directory h3.swap { */
/* height: 61px; */
/* background-repeat: no-repeat; */
/* background-image: url("yourimage.gif"); */
/* } */
/* .directory h3.swap span { */
/* display: none; */
/* } */
.directory > h3 {
margin-top: 0;
}
.directory p {
margin: 0px;
white-space: nowrap;
}
.directory div {
display: none;
margin: 0px;
}
.directory img {
vertical-align: -30%;
}
/* these are for tree view when not used as main index */
.directory-alt {
font-size: 100%;
font-weight: bold;
}
.directory-alt h3 {
margin: 0px;
margin-top: 1em;
font-size: 11pt;
}
.directory-alt > h3 {
margin-top: 0;
}
.directory-alt p {
margin: 0px;
white-space: nowrap;
}
.directory-alt div {
display: none;
margin: 0px;
}
.directory-alt img {
vertical-align: -30%;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

11
legacy/edbus/edbus.pc.in Normal file
View File

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: edbus
Description: D-Bus access from Ecore
Requires.private: ecore dbus-1
Version: @VERSION@
Libs: -L${libdir} -ledbus
Cflags: -I${includedir}

View File

@ -0,0 +1,47 @@
dnl Copyright (C) 2004-2008 Kim Woelders
dnl Copyright (C) 2008 Vincent Torri <vtorri at univ-evry dot fr>
dnl That code is public domain and can be freely used or copied.
dnl Originally snatched from somewhere...
dnl Macro for checking if the compiler supports __attribute__
dnl Usage: AC_C___ATTRIBUTE__
dnl call AC_DEFINE for HAVE___ATTRIBUTE__ and __UNUSED__
dnl if the compiler supports __attribute__, HAVE___ATTRIBUTE__ is
dnl defined to 1 and __UNUSED__ is defined to __attribute__((unused))
dnl otherwise, HAVE___ATTRIBUTE__ is not defined and __UNUSED__ is
dnl defined to nothing.
AC_DEFUN([AC_C___ATTRIBUTE__],
[
AC_MSG_CHECKING([for __attribute__])
AC_CACHE_VAL([ac_cv___attribute__],
[AC_TRY_COMPILE(
[
#include <stdlib.h>
int func(int x);
int foo(int x __attribute__ ((unused)))
{
exit(1);
}
],
[],
[ac_cv___attribute__="yes"],
[ac_cv___attribute__="no"]
)])
AC_MSG_RESULT($ac_cv___attribute__)
if test "x${ac_cv___attribute__}" = "xyes" ; then
AC_DEFINE([HAVE___ATTRIBUTE__], [1], [Define to 1 if your compiler has __attribute__])
AC_DEFINE([__UNUSED__], [__attribute__((unused))], [Macro declaring a function argument to be unused])
else
AC_DEFINE([__UNUSED__], [], [Macro declaring a function argument to be unused])
fi
])
dnl End of ac_attribute.m4

View File

@ -0,0 +1,48 @@
dnl That code is public domain and can be freely used or copied.
dnl Originally snatched from somewhere...
dnl Macro for checking if va_list is an array
dnl Usage: AC_C_VA_LIST_AS_ARRAY
dnl call AC_DEFINE for HAVE_VA_LIST_AS_ARRAY
dnl if for this architecture va_list is defined as an array
AC_DEFUN([AC_C_VA_LIST_AS_ARRAY],
[
AC_MSG_CHECKING([whether va_list is defined as an array])
AC_CACHE_VAL([ac_cv_valistasarray],
[AC_TRY_RUN(
[
#include <stdlib.h>
#include <stdarg.h>
void foo(int i, ...)
{
va_list ap1, ap2;
va_start(ap1, i);
ap2 = ap1;
if (va_arg(ap2, int) != 123 || va_arg(ap1, int) != 123)
exit(1);
va_end(ap1);
}
int main(void)
{
foo(0, 123);
return(0);
}
],
[ac_cv_valistasarray="no"],
[ac_cv_valistasarray="yes"],
[ac_cv_valistasarray="no"]
)])
AC_MSG_RESULT($ac_cv_valistasarray)
if test "x${ac_cv_valistasarray}" = "xyes" ; then
AC_DEFINE([HAVE_VA_LIST_AS_ARRAY], [1], [Define to 1 if va_list is an array])
fi
])
dnl End of ac_valist.m4

View File

@ -0,0 +1,24 @@
dnl Checks if a given compiler switch is supported.
dnl If so, this macro adds the flag to the CFLAGS
AC_DEFUN([EFL_COMPILER_FLAG],
[
CFLAGS_save="${CFLAGS}"
CFLAGS="${CFLAGS} $1"
AC_LANG_PUSH([C])
AC_MSG_CHECKING([whether the compiler supports $1])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[]])],
[have_flag="yes"],
[have_flag="no"])
AC_MSG_RESULT([${have_flag}])
if test "x${have_flag}" = "xno" ; then
CFLAGS="${CFLAGS_save}"
fi
AC_LANG_POP([C])
])

View File

@ -0,0 +1,94 @@
dnl Copyright (C) 2008 Vincent Torri <vtorri at univ-evry dot fr>
dnl That code is public domain and can be freely used or copied.
dnl Macro that check if doxygen is available or not.
dnl EFL_CHECK_DOXYGEN([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
dnl Test for the doxygen program
dnl Defines efl_doxygen
dnl Defines the automake conditionnal EFL_BUILD_DOC
dnl
AC_DEFUN([EFL_CHECK_DOXYGEN],
[
dnl
dnl Disable the build of the documentation
dnl
AC_ARG_ENABLE([doc],
[AC_HELP_STRING(
[--disable-doc],
[Disable documentation build @<:@default=enabled@:>@])],
[
if test "x${enableval}" = "xyes" ; then
efl_enable_doc="yes"
else
efl_enable_doc="no"
fi
],
[efl_enable_doc="yes"])
AC_MSG_CHECKING([whether to build documentation])
AC_MSG_RESULT([${efl_enable_doc}])
if test "x${efl_enable_doc}" = "xyes" ; then
dnl Specify the file name, without path
efl_doxygen="doxygen"
AC_ARG_WITH([doxygen],
[AC_HELP_STRING(
[--with-doxygen=FILE],
[doxygen program to use @<:@default=doxygen@:>@])],
dnl Check the given doxygen program.
[efl_doxygen=${withval}
AC_CHECK_PROG([efl_have_doxygen],
[${efl_doxygen}],
[yes],
[no])
if test "x${efl_have_doxygen}" = "xno" ; then
echo "WARNING:"
echo "The doxygen program you specified:"
echo "${efl_doxygen}"
echo "was not found. Please check the path and make sure "
echo "the program exists and is executable."
AC_MSG_WARN([no doxygen detected. Documentation will not be built])
fi
],
[AC_CHECK_PROG([efl_have_doxygen],
[${efl_doxygen}],
[yes],
[no])
if test "x${efl_have_doxygen}" = "xno" ; then
echo "WARNING:"
echo "The doxygen program was not found in your execute path."
echo "You may have doxygen installed somewhere not covered by your path."
echo ""
echo "If this is the case make sure you have the packages installed, AND"
echo "that the doxygen program is in your execute path (see your"
echo "shell manual page on setting the \$PATH environment variable), OR"
echo "alternatively, specify the program to use with --with-doxygen."
AC_MSG_WARN([no doxygen detected. Documentation will not be built])
fi
])
else
efl_have_doxygen="no"
fi
dnl
dnl Substitution
dnl
AC_SUBST([efl_doxygen])
if ! test "x${efl_have_doxygen}" = "xyes" ; then
efl_enable_doc="no"
fi
AM_CONDITIONAL(EFL_BUILD_DOC, test "x${efl_have_doxygen}" = "xyes")
AS_IF([test "x$efl_have_doxygen" = "xyes"], [$1], [$2])
])
dnl End of efl_doxygen.m4

View File

@ -0,0 +1,293 @@
#include "EDBus.h"
#include <Ecore.h>
static Eina_Bool
_timer1_cb(void *data)
{
printf("\n## ecore_main_loop_quit()\n");
ecore_main_loop_quit();
return EINA_TRUE;
}
EDBus_Connection *conn;
EDBus_Signal_Handler *sh, *sh2, *sh3, *sh4;
static void
on_get_playlists(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname, *errmsg;
EDBus_Message_Iter *array, *struct_entry;
char *path, *name, *image;
int i = 0;
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
return;
}
if (!edbus_message_arguments_get(msg, "a(oss)", &array))
{
fprintf(stderr, "Error: could not get entry contents\n");
return;
}
printf("on_get_playlists() \n\n");
while (edbus_message_iter_get_and_next(array, 'r', &struct_entry))
{
if (! edbus_message_iter_arguments_get(struct_entry, "oss", &path, &name, &image))
{
printf("error on edbus_massage_iterator_arguments_get()");
return;
}
i++;
printf("%d - %s | %s | %s\n", i, path, name, image);
}
printf("end of on_get_playlists()\n\n");
}
static void
on_introspect(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname, *errmsg, *string;
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
return;
}
if (!edbus_message_arguments_get(msg, "s", &string))
{
fprintf(stderr, "Error: could not get entry contents\n");
return;
}
printf("on_introspect() data=\n%s\n\n", string);
}
static void
on_next(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname, *errmsg;
printf("on_next()\n");
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
}
}
static void
on_pause(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname, *errmsg;
printf("on_pause()\n");
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
}
}
static void
on_state_changed(void *data, const EDBus_Message *msg)
{
char *status;
if (edbus_message_error_get(msg, NULL, NULL))
{
fprintf(stderr, "on_state_changed error\n");
return;
}
if (!edbus_message_arguments_get(msg, "s", &status))
{
fprintf(stderr, "Error: could not get entry contents\n");
return;
}
printf("on_state_changed = %s\n", status);
}
static void
on_state_changed2(void *data, const EDBus_Message *msg)
{
char *status;
if (edbus_message_error_get(msg, NULL, NULL))
{
fprintf(stderr, "on_state_changed error\n");
return;
}
if (!edbus_message_arguments_get(msg, "s", &status))
{
fprintf(stderr, "Error: could not get entry contents\n");
return;
}
printf("on_state_changed2 = %s\n", status);
edbus_signal_handler_unref(sh2);
sh2 = NULL;
}
static void
on_name_owner_changed_by_id(void *data, const EDBus_Message *msg)
{
char *bus, *older_id, *new_id;
if (edbus_message_error_get(msg, NULL, NULL))
return;
if (!edbus_message_arguments_get(msg, "sss", &bus, &older_id, &new_id))
printf("Error getting arguments from NameOwnerChanged");
printf("on_name_owner_changed_by_id bus = %s older=%s new=%s\n\n",
bus, older_id, new_id);
if (!new_id[0])
edbus_signal_handler_unref(sh3);
}
static void
on_name_owner_changed(void *data, const EDBus_Message *msg)
{
char *bus, *older_id, *new_id;
const char *name, *text;
if (edbus_message_error_get(msg, &name, &text))
printf("NameOwnerChanged name=%s text=%s", name, text);
if (!edbus_message_arguments_get(msg, "sss", &bus, &older_id, &new_id))
printf("Error getting arguments from NameOwnerChanged");
printf("bus = %s older=%s new=%s\n\n", bus, older_id, new_id);
if (new_id[0])
{
sh4 = edbus_signal_handler_add(conn,
EDBUS_FDO_BUS,
EDBUS_FDO_PATH,
EDBUS_FDO_INTERFACE,
"NameOwnerChanged",
on_name_owner_changed_by_id,
NULL);
edbus_signal_handler_match_extra_set(sh4, "arg1", new_id, NULL);
}
}
int
main(void)
{
EDBus_Object *player_engine_obj, *playback_controller_obj, *mediaplayer2_obj;
EDBus_Proxy *player_engine, *playback_controler, *introspectable, *playlists;
EDBus_Pending *pending;
unsigned int bool2 = 1;
unsigned int playlist_index = 0;
unsigned int playlist_max_count = 30;
unsigned int playlist_reverse_order = 0;
const char *playlist_order = "asc";
ecore_init();
edbus_init();
conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
player_engine_obj = edbus_object_get(conn, "org.bansheeproject.Banshee",
"/org/bansheeproject/Banshee/PlayerEngine");
if (!player_engine_obj)
{
fprintf(stderr, "Error: could not get object\n");
return EXIT_FAILURE;
}
playback_controller_obj = edbus_object_get(conn, "org.bansheeproject.Banshee",
"/org/bansheeproject/Banshee/PlaybackController");
mediaplayer2_obj = edbus_object_get(conn, "org.bansheeproject.Banshee",
"/org/mpris/MediaPlayer2");
player_engine = edbus_proxy_get(player_engine_obj,
"org.bansheeproject.Banshee.PlayerEngine");
if (!player_engine)
{
fprintf(stderr, "Error: could not get binding\n");
return EXIT_FAILURE;
}
introspectable = edbus_proxy_get(player_engine_obj,
"org.freedesktop.DBus.Introspectable");
if (!introspectable)
{
fprintf(stderr, "Error: could not get binding\n");
return EXIT_FAILURE;
}
playback_controler = edbus_proxy_get(playback_controller_obj,
"org.bansheeproject.Banshee.PlaybackController");
if (!playback_controler)
{
fprintf(stderr, "Error: could not get binding\n");
return EXIT_FAILURE;
}
edbus_proxy_signal_handler_add(player_engine, "StateChanged", on_state_changed, NULL);
playlists = edbus_proxy_get(mediaplayer2_obj, "org.mpris.MediaPlayer2.Playlists");
pending = edbus_proxy_call(introspectable, "Introspect", on_introspect, NULL, -1, "");
if (!pending)
{
fprintf(stderr, "Error: could not call\n");
return EXIT_FAILURE;
}
pending = edbus_proxy_call(player_engine, "Pause", on_pause, NULL, -1, "");
if (!pending)
{
fprintf(stderr, "Error: could not call\n");
return EXIT_FAILURE;
}
pending = edbus_proxy_call(playback_controler, "Next", on_next, NULL, -1, "b", bool2);
if (!pending)
{
fprintf(stderr, "Error: could not call\n");
return EXIT_FAILURE;
}
edbus_proxy_call(playlists, "GetPlaylists", on_get_playlists, NULL, -1,
"uusb", playlist_index, playlist_max_count,
playlist_order, playlist_reverse_order);
sh = edbus_signal_handler_add(conn, "org.bansheeproject.Banshee",
"/org/bansheeproject/Banshee/PlayerEngine",
"org.bansheeproject.Banshee.PlayerEngine",
"StateChanged", on_state_changed, NULL);
sh2 = edbus_signal_handler_add(conn, "org.bansheeproject.Banshee",
"/org/bansheeproject/Banshee/PlayerEngine",
"org.bansheeproject.Banshee.PlayerEngine",
"StateChanged", on_state_changed2, NULL);
sh3 = edbus_signal_handler_add(conn,
EDBUS_FDO_BUS,
EDBUS_FDO_PATH,
EDBUS_FDO_INTERFACE,
"NameOwnerChanged",
on_name_owner_changed,
NULL);
edbus_signal_handler_match_extra_set(sh3, "arg0", "org.bansheeproject.Banshee", NULL);
ecore_timer_add(50, _timer1_cb, NULL);
ecore_main_loop_begin();
edbus_signal_handler_unref(sh);
edbus_proxy_unref(playback_controler);
edbus_proxy_unref(introspectable);
edbus_object_unref(player_engine_obj);
edbus_connection_unref(conn);
edbus_shutdown();
ecore_shutdown();
return 0;
}

View File

@ -0,0 +1,255 @@
#include "EDBus.h"
#include <Ecore.h>
#define BUS "org.Enlightenment"
#define PATH "/org/enlightenment"
#define INTERFACE "org.enlightenment.Test"
#define NTESTS 7
static int i = 0;
static EDBus_Signal_Handler *sh;
static void
_on_alive(void *context, const EDBus_Message *msg)
{
printf("Alive\n\n");
}
static void
_on_alive2(void *context, const EDBus_Message *msg)
{
printf("Alive2\n\n");
i++;
if (i == 2)
edbus_signal_handler_unref(sh);
}
static void
_on_hello(void *context, const EDBus_Message *msg)
{
char *txt;
if (edbus_message_arguments_get(msg, "s", &txt))
printf("%s\n", txt);
}
#define bool_value EINA_TRUE
#define byte_value 0xAA
#define uint32_value 0xFFFFFFFF
#define int32_value 0xFFFFFFFF
#define int16_value 0x0000FFFF
#define double_value 3.1415926
#define string_value "test"
static void
test(void)
{
static int n = 0;
n++;
if (n == NTESTS)
printf("Passed in all tests\n");
}
static void
_on_send_bool(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname, *errmsg;
Eina_Bool bool;
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
return;
}
if (!edbus_message_arguments_get(msg, "b", &bool))
{
fprintf(stderr, "Error: could not get entry contents\n");
return;
}
if (bool != bool_value) printf("Error on bool\n");
else test();
}
static void
_on_send_byte(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname, *errmsg;
unsigned char byte;
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
return;
}
if (!edbus_message_arguments_get(msg, "y", &byte))
{
fprintf(stderr, "Error: could not get entry contents\n");
return;
}
if (byte != byte_value) printf("Error on byte\n");
else test();
}
static void
_on_send_uint32(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname, *errmsg;
unsigned int uint32;
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
return;
}
if (!edbus_message_arguments_get(msg, "u", &uint32))
{
fprintf(stderr, "Error: could not get entry contents\n");
return;
}
if (uint32 != uint32_value) printf("Error on uint32\n");
else test();
}
static void
_on_send_int32(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname, *errmsg;
int int32;
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
return;
}
if (!edbus_message_arguments_get(msg, "i", &int32))
{
fprintf(stderr, "Error: could not get entry contents\n");
return;
}
if (int32 != (int)int32_value) printf("Error on int32\n");
else test();
}
static void
_on_send_int16(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname, *errmsg;
short int int16;
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
return;
}
if (!edbus_message_arguments_get(msg, "n", &int16))
{
fprintf(stderr, "Error: could not get entry contents\n");
return;
}
if (int16 != (short int)int16_value) printf("Error on int16\n");
else test();
}
static void
_on_send_double(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname, *errmsg;
double d;
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
return;
}
if (!edbus_message_arguments_get(msg, "d", &d))
{
fprintf(stderr, "Error: could not get entry contents\n");
return;
}
if (d != double_value) printf("Error on double\n");
else test();
}
static void
_on_send_string(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname, *errmsg;
char *str;
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
return;
}
if (!edbus_message_arguments_get(msg, "s", &str))
{
fprintf(stderr, "Error: could not get entry contents\n");
return;
}
if (strcmp(str, string_value)) printf("Error on string\n");
else test();
}
static void
_on_async_test(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname, *errmsg;
char *str;
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
return;
}
if (!edbus_message_arguments_get(msg, "s", &str))
{
fprintf(stderr, "Error: could not get entry contents\n");
return;
}
printf("%s\n", str);
}
int
main(void)
{
EDBus_Connection *conn;
EDBus_Object *obj;
EDBus_Proxy *proxy;
ecore_init();
edbus_init();
conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
obj = edbus_object_get(conn, BUS, PATH);
proxy = edbus_proxy_get(obj, INTERFACE);
edbus_proxy_signal_handler_add(proxy, "Alive", _on_alive, NULL);
sh = edbus_proxy_signal_handler_add(proxy, "Alive", _on_alive2, NULL);
edbus_proxy_signal_handler_add(proxy, "Hello", _on_hello, NULL);
edbus_proxy_call(proxy, "SendBool", _on_send_bool, NULL, -1, "b", bool_value);
edbus_proxy_call(proxy, "SendByte", _on_send_byte, NULL, -1, "y", byte_value);
edbus_proxy_call(proxy, "SendUint32", _on_send_uint32, NULL, -1, "u", uint32_value);
edbus_proxy_call(proxy, "SendInt32", _on_send_int32, NULL, -1, "i", int32_value);
edbus_proxy_call(proxy, "SendInt16", _on_send_int16, NULL, -1, "n", int16_value);
edbus_proxy_call(proxy, "SendDouble", _on_send_double, NULL, -1, "d", double_value);
edbus_proxy_call(proxy, "SendString", _on_send_string, NULL, -1, "s", string_value);
edbus_proxy_call(proxy, "AsyncTest", _on_async_test, NULL, -1, "");
ecore_main_loop_begin();
edbus_connection_unref(conn);
edbus_shutdown();
ecore_shutdown();
return 0;
}

View File

@ -0,0 +1,257 @@
#include "EDBus.h"
#include <Ecore.h>
#define BUS "com.profusion"
#define PATH "/com/profusion/Test"
#define IFACE "com.profusion.Test"
EDBus_Connection *conn;
static Eina_Bool
_timer1_cb(void *data)
{
printf("\n## ecore_main_loop_quit()\n");
ecore_main_loop_quit();
return EINA_TRUE;
}
static void
on_plus_one(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
int num2 = 0;
if (edbus_message_error_get(msg, NULL, NULL))
{
printf("Message error\n\n");
return;
}
if (!edbus_message_arguments_get(msg, "i", &num2))
{
printf("Error getting arguments.");
return;
}
printf("on_plus_one() %d\n", num2);
}
static void
set_property_resp2(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname;
const char *errmsg;
printf("set_property_resp2()\n");
if (edbus_message_error_get(msg, &errname, &errmsg))
{
printf("Message error %s - %s\n\n", errname, errmsg);
return;
}
}
static void
get_property_resp2(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
EDBus_Proxy *proxy = data;
EDBus_Message_Iter *variant = NULL;
char *type;
char *resp2;
const char *errname;
const char *errmsg;
printf("get_property_resp2()\n");
if (edbus_message_error_get(msg, &errname, &errmsg))
{
printf("Message error %s - %s\n\n", errname, errmsg);
return;
}
if (!edbus_message_arguments_get(msg, "v", &variant))
{
printf("Error getting arguments.");
return;
}
type = edbus_message_iter_signature_get(variant);
if (type[1])
{
printf("It is a complex type, not handle yet.\n\n");
return;
}
if (type[0] != 's')
{
printf("Expected type is string.\n\n");
return;
}
if (!edbus_message_iter_arguments_get(variant, "s", &resp2))
{
printf("error in edbus_message_iter_arguments_get()\n\n");
return;
}
printf("resp2=%s\n", resp2);
free(type);
edbus_proxy_property_set(proxy, "Resp2", 's', "lalala", set_property_resp2, NULL);
}
static void
on_send_array_int(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
EDBus_Message_Iter *array = NULL;
int num;
printf("on_send_array_int()\n");
if (edbus_message_error_get(msg, NULL, NULL))
{
printf("Message error\n\n");
return;
}
if (!edbus_message_arguments_get(msg, "ai", &array))
{
printf("Error getting arguments.");
return;
}
while (edbus_message_iter_get_and_next(array, 'i', &num))
{
printf("%d\n", num);
}
}
static void
on_send_array(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
EDBus_Message_Iter *array = NULL;
char *txt = NULL;
char *string[10];
int i = 0;
int z;
printf("on_send_array()\n");
if (edbus_message_error_get(msg, NULL, NULL))
{
printf("Message error\n\n");
return;
}
if (!edbus_message_arguments_get(msg, "as", &array))
{
printf("Error getting arguments.");
return;
}
while (edbus_message_iter_get_and_next(array, 's', &txt))
{
string[i] = txt;
i++;
}
for (z = 0; z < i; z++)
printf("string = %s\n", string[z]);
}
static void
on_receive_array_with_size(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname;
const char *errmsg;
printf("on_receive_array_with_size()\n");
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
}
}
static void
on_send_variant(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
printf("on_send_variant()\n\n");
}
static void
on_receive_array(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname;
const char *errmsg;
printf("on_receive_array()\n");
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
}
}
int
main(void)
{
EDBus_Object *test2_obj;
EDBus_Proxy *test2_proxy;
EDBus_Pending *pending;
EDBus_Message_Iter *iter, *array_of_string, *variant;
EDBus_Message *msg;
int size_of_array = 5;
const char *array[5] = { "aaaa", "bbbb", "cccc", "dddd", "eeee" };
int i;
int plus_one = 24;
ecore_init();
edbus_init();
conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
test2_obj = edbus_object_get(conn, BUS, PATH);
test2_proxy = edbus_proxy_get(test2_obj, IFACE);
msg = edbus_proxy_method_call_new(test2_proxy, "ReceiveArray");
iter = edbus_message_iter_get(msg);
array_of_string = edbus_message_iter_container_new(iter, 'a',"s");
if (!array_of_string) printf("array_of_string == NULL\n\n");
for (i = 0; i < 5; i++)
edbus_message_iter_append_basic(array_of_string, 's', array[i]);
edbus_message_iter_container_close(iter, array_of_string);
pending = edbus_proxy_send(test2_proxy, msg, on_receive_array, NULL, -1);
if (!pending) printf("Error in edbus_proxy_send()\n\n");
edbus_message_unref(msg);
msg = edbus_proxy_method_call_new(test2_proxy, "ReceiveArrayOfStringIntWithSize");
iter = edbus_message_iter_get(msg);
if (!edbus_message_iter_arguments_set(iter, "ia(si)", size_of_array, &array_of_string))
printf("error on edbus_massage_iterator_arguments_set()\n\n");
for (i = 0; i < size_of_array; i++)
{
EDBus_Message_Iter *struct_of_si;
edbus_message_iter_arguments_set(array_of_string, "(si)", &struct_of_si);
edbus_message_iter_arguments_set(struct_of_si, "si", array[i], i);
edbus_message_iter_container_close(array_of_string, struct_of_si);
}
edbus_message_iter_container_close(iter, array_of_string);
pending = edbus_proxy_send(test2_proxy, msg, on_receive_array_with_size, NULL, -1);
edbus_message_unref(msg);
msg = edbus_proxy_method_call_new(test2_proxy, "SendVariantData");
iter = edbus_message_iter_get(msg);
variant = edbus_message_iter_container_new(iter, 'v', "s");
edbus_message_iter_append_basic(variant, 's', "test");
edbus_message_iter_container_close(iter, variant);
pending = edbus_proxy_send(test2_proxy, msg, on_send_variant, NULL, -1);
edbus_message_unref(msg);
pending = edbus_proxy_call(test2_proxy, "SendArrayInt", on_send_array_int, NULL,
-1 , "");
pending = edbus_proxy_call(test2_proxy, "SendArray", on_send_array, NULL,
-1 , "");
pending = edbus_proxy_call(test2_proxy, "PlusOne", on_plus_one, NULL,
-1 , "i", plus_one);
pending = edbus_proxy_property_get(test2_proxy, "Resp2", get_property_resp2, test2_proxy);
ecore_timer_add(5, _timer1_cb, NULL);
ecore_main_loop_begin();
edbus_connection_unref(conn);
edbus_shutdown();
ecore_shutdown();
return 0;
}

View File

@ -0,0 +1,351 @@
#include "EDBus.h"
#include <Ecore.h>
#define BUS "com.profusion"
#define PATH "/com/profusion/Test"
#define IFACE "com.profusion.Test"
char *resp2;
static EDBus_Message *
_receive_array(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
EDBus_Message_Iter *array;
char *txt;
printf("receiveArray\n");
if (!edbus_message_arguments_get(msg, "as", &array))
{
printf("Error on edbus_message_arguments_get()\n");
return reply;
}
while (edbus_message_iter_get_and_next(array, 's', &txt))
printf("%s\n", txt);
printf("\n");
return reply;
}
static EDBus_Message *
_receive_array_of_string_int_with_size(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
EDBus_Message_Iter *array;
EDBus_Message_Iter *struct_si;
int size, i = 0;
printf("receiveArrayOfStringIntWithSize\n");
if (!edbus_message_arguments_get(msg, "ia(si)", &size, &array))
{
printf("Error on edbus_message_arguments_get()\n");
return reply;
}
while (edbus_message_iter_get_and_next(array, 'r', &struct_si))
{
char *txt;
char num;
if (!edbus_message_iter_arguments_get(struct_si, "si", &txt, &num))
{
printf("Error on edbus_message_arguments_get()\n");
return reply;
}
printf("%s | %d\n", txt, num);
i++;
}
printf("size in msg %d | size read %d\n", size, i);
printf("\n");
return reply;
}
static EDBus_Message *
_send_variant(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
EDBus_Message_Iter *variant;
char *type;
printf("sendVariantData\n");
if (!edbus_message_arguments_get(msg, "v", &variant))
{
printf("Error on edbus_message_arguments_get()\n");
return reply;
}
type = edbus_message_iter_signature_get(variant);
if (type[1] || type[0] == 'v')
{
printf("It is a complex type, not handle yet.\n");
free(type);
return reply;
}
switch (type[0])
{
case 's':
case 'o':
{
char *txt;
edbus_message_iter_arguments_get(variant, type, &txt);
printf("type = %c value = %s\n", type[0], txt);
break;
}
case 'i':
{
int num;
edbus_message_iter_arguments_get(variant, type, &num);
printf("type = %c value = %d\n", type[0], num);
break;
}
default:
{
printf("Unhandled type\n");
}
}
printf("\n");
free(type);
return reply;
}
static EDBus_Message *
_send_array_int(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
EDBus_Message_Iter *iter, *array;
int i;
printf("sendArrayInt\n\n");
iter = edbus_message_iter_get(reply);
array = edbus_message_iter_container_new(iter, 'a', "i");
for (i = 0; i < 5; i++)
edbus_message_iter_arguments_set(array, "i", i);
edbus_message_iter_container_close(iter, array);
return reply;
}
static EDBus_Message *
_send_array(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
EDBus_Message_Iter *iter, *array;
const char *array_string[5] = {"qqqq", "wwwww", "eeeeee", "rrrrr", "ttttt"};
int i;
printf("sendArray\n\n");
iter = edbus_message_iter_get(reply);
array = edbus_message_iter_container_new(iter, 'a', "s");
for (i = 0; i < 5; i++)
edbus_message_iter_arguments_set(array, "s", array_string[i]);
edbus_message_iter_container_close(iter, array);
return reply;
}
static EDBus_Message *
_plus_one(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
int num;
printf("plusOne\n\n");
if (!edbus_message_arguments_get(msg, "i", &num))
{
printf("Error on edbus_message_arguments_get()\n");
return reply;
}
num++;
edbus_message_arguments_set(reply, "i", num);
return reply;
}
static EDBus_Message *
_properties_get(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply;
char *interface, *property;
EDBus_Message_Iter *variant, *iter;
if (!edbus_message_arguments_get(msg, "ss", &interface, &property))
{
printf("Error on edbus_message_arguments_get()\n");
return NULL;
}
if (strcmp(interface, IFACE))
{
reply = edbus_message_error_new(msg,
"org.freedesktop.DBus.Error.UnknownInterface",
"Interface not found.");
return reply;
}
if (strcmp(property, "Resp2"))
{
reply = edbus_message_error_new(msg,
"org.freedesktop.DBus.Error.UnknownProperty",
"Property not found.");
return reply;
}
reply = edbus_message_method_return_new(msg);
iter = edbus_message_iter_get(reply);
variant = edbus_message_iter_container_new(iter, 'v', "s");
edbus_message_iter_append_basic(variant, 's', resp2);
printf("get %s\n", resp2);
edbus_message_iter_container_close(iter, variant);
return reply;
}
static EDBus_Message *
_properties_set(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply;
char *interface, *property, *type, *txt;
EDBus_Message_Iter *variant;
if (!edbus_message_arguments_get(msg, "ssv", &interface, &property, &variant))
{
printf("Error on edbus_message_arguments_get()\n");
return NULL;
}
if (strcmp(interface, IFACE))
{
reply = edbus_message_error_new(msg,
"org.freedesktop.DBus.Error.UnknownInterface",
"Interface not found.");
return reply;
}
if (strcmp(property, "Resp2"))
{
reply = edbus_message_error_new(msg,
"org.freedesktop.DBus.Error.UnknownProperty",
"Property not found.");
return reply;
}
type = edbus_message_iter_signature_get(variant);
if (type[0] != 's')
{
reply = edbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidSignature",
"Invalid type.");
free(type);
return reply;
}
reply = edbus_message_method_return_new(msg);
edbus_message_iter_arguments_get(variant, "s", &txt);
free(type);
free(resp2);
resp2 = strdup(txt);
return reply;
}
static const EDBus_Method methods[] = {
{
"ReceiveArray", EDBUS_ARGS({"as", "array_of_strings"}),
EDBUS_ARGS({"", ""}), _receive_array, 0
},
{
"ReceiveArrayOfStringIntWithSize",
EDBUS_ARGS({"i", "size_of_array"}, {"a(si)", "array"}),
EDBUS_ARGS({"", ""}), _receive_array_of_string_int_with_size, 0
},
{
"SendVariantData", EDBUS_ARGS({"v", "variant_data"}),
EDBUS_ARGS({"", ""}), _send_variant, 0
},
{
"SendArrayInt", EDBUS_ARGS({"", ""}),
EDBUS_ARGS({"ai", "array_of_int"}), _send_array_int, 0
},
{
"SendArray", EDBUS_ARGS({"", ""}), EDBUS_ARGS({"as", "array_string"}),
_send_array, 0
},
{
"PlusOne", EDBUS_ARGS({"i", "integer"}),
EDBUS_ARGS({"i", "integer_plus_one"}), _plus_one, 0
},
{ }
};
static const EDBus_Method properties_methods[] = {
{
"Get", EDBUS_ARGS({"s", "interface"}, {"s", "property"}),
EDBUS_ARGS({"v", "value"}), _properties_get, 0
},
{
"Set", EDBUS_ARGS({"s", "interface"}, {"s", "property"}, {"v", "value"}),
EDBUS_ARGS({"", ""}), _properties_set, 0
},
{ }
};
static void
on_name_request(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
EDBus_Connection *conn = data;
unsigned int flag;
resp2 = malloc(sizeof(char) * 5);
strcpy(resp2, "test");
if (edbus_message_error_get(msg, NULL, NULL))
{
printf("error on on_name_request\n");
return;
}
if (!edbus_message_arguments_get(msg, "u", &flag))
{
printf("error geting arguments on on_name_request\n");
return;
}
if (!(flag & EDBUS_NAME_REQUEST_REPLY_PRIMARY_OWNER))
{
printf("error name already in use\n");
return;
}
edbus_service_interface_register(conn, PATH, IFACE, methods, NULL);
edbus_service_interface_register(conn, PATH, EDBUS_FDO_INTERFACE_PROPERTIES, properties_methods, NULL);
}
int
main(void)
{
EDBus_Connection *conn;
ecore_init();
edbus_init();
conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
edbus_name_request(conn, BUS, EDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE, on_name_request, conn);
ecore_main_loop_begin();
free(resp2);
edbus_connection_unref(conn);
edbus_shutdown();
ecore_shutdown();
return 0;
}

View File

@ -0,0 +1,107 @@
#include "EDBus.h"
#include <Ecore.h>
static void
on_services_get(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
EDBus_Message_Iter *array, *entry;
const char *errname, *errmsg;
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
return;
}
if (!edbus_message_arguments_get(msg, "a(oa{sv})", &array))
{
fprintf(stderr, "Error: could not get array\n");
return;
}
while (edbus_message_iter_get_and_next(array, 'r', &entry))
{
EDBus_Message_Iter *properties, *dict_entry;
const char *path;
if (!edbus_message_iter_arguments_get(entry, "oa{sv}", &path, &properties))
{
fprintf(stderr, "Error: could not get entry contents\n");
return;
}
printf("service: %s\n", path);
while (edbus_message_iter_get_and_next(properties, 'e', &dict_entry))
{
EDBus_Message_Iter *variant;
const char *key;
if (!edbus_message_iter_arguments_get(dict_entry, "sv", &key,
&variant))
{
fprintf(stderr,
"Error: could not get property contents\n");
return;
}
printf("\t%s: type %s\n", key,
edbus_message_iter_signature_get(variant));
/* TODO: get the value from variant */
}
}
}
int
main(void)
{
EDBus_Connection *conn;
EDBus_Object *obj;
EDBus_Proxy *manager;
EDBus_Pending *pending;
ecore_init();
edbus_init();
conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SYSTEM);
if (!conn)
{
fprintf(stderr, "Error: could not get system bus\n");
return EXIT_FAILURE;
}
obj = edbus_object_get(conn, "net.connman", "/");
if (!obj)
{
fprintf(stderr, "Error: could not get object\n");
return EXIT_FAILURE;
}
manager = edbus_proxy_get(obj, "net.connman.Manager");
if (!manager)
{
fprintf(stderr, "Error: could not get proxy\n");
return EXIT_FAILURE;
}
pending = edbus_proxy_call(manager, "GetServices", on_services_get, NULL,
-1, "");
if (!pending)
{
fprintf(stderr, "Error: could not call\n");
return EXIT_FAILURE;
}
ecore_main_loop_begin();
edbus_proxy_unref(manager);
edbus_object_unref(obj);
edbus_connection_unref(conn);
edbus_shutdown();
ecore_shutdown();
return 0;
}

View File

@ -0,0 +1,85 @@
#include "EDBus.h"
#include <Ecore.h>
static void
on_dial(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
const char *errname, *errmsg;
const char *call_path;
if (edbus_message_error_get(msg, &errname, &errmsg))
{
fprintf(stderr, "Error: %s %s\n", errname, errmsg);
return;
}
if (!edbus_message_arguments_get(msg, "o", &call_path))
{
fprintf(stderr, "Error: could not get call path\n");
return;
}
printf("dialed! call path: %s\n", call_path);
}
int
main(int argc, char *argv[])
{
EDBus_Connection *conn;
EDBus_Object *obj;
EDBus_Proxy *manager;
EDBus_Pending *pending;
const char *number, *hide_callerid;
if (argc < 2)
{
fprintf(stderr, "Usage:\n\t%s <number> [hide_callerid]\n", argv[0]);
return EXIT_FAILURE;
}
number = argv[1];
hide_callerid = (argc > 2) ? argv[2] : "";
ecore_init();
edbus_init();
conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SYSTEM);
if (!conn)
{
fprintf(stderr, "Error: could not get system bus\n");
return EXIT_FAILURE;
}
obj = edbus_object_get(conn, "org.ofono", "/");
if (!obj)
{
fprintf(stderr, "Error: could not get object\n");
return EXIT_FAILURE;
}
manager = edbus_proxy_get(obj, "org.ofono.Manager");
if (!manager)
{
fprintf(stderr, "Error: could not get proxy\n");
return EXIT_FAILURE;
}
pending = edbus_proxy_call(manager, "Dial", on_dial, NULL,
-1, "ss", number, hide_callerid);
if (!pending)
{
fprintf(stderr, "Error: could not call\n");
return EXIT_FAILURE;
}
ecore_main_loop_begin();
edbus_proxy_unref(manager);
edbus_object_unref(obj);
edbus_connection_unref(conn);
edbus_shutdown();
ecore_shutdown();
return 0;
}

View File

@ -0,0 +1,236 @@
#include "EDBus.h"
#include <Ecore.h>
#define BUS "org.Enlightenment"
#define PATH "/org/enlightenment"
#define INTERFACE "org.enlightenment.Test"
EDBus_Connection *conn;
static EDBus_Message *
_hello(const EDBus_Service_Interface *iface, const EDBus_Message *message)
{
EDBus_Message *reply = edbus_message_method_return_new(message);
edbus_message_arguments_set(reply, "s", "Hello World");
printf("Hello\n");
return reply;
}
static EDBus_Message *
_quit(const EDBus_Service_Interface *iface, const EDBus_Message *message)
{
printf("Quit\n");
ecore_main_loop_quit();
return edbus_message_method_return_new(message);
}
enum
{
TEST_SIGNAL_ALIVE = 0,
TEST_SIGNAL_HELLO
};
static Eina_Bool
send_signal_alive(void *data)
{
EDBus_Service_Interface *iface = data;
edbus_service_signal_emit(iface, TEST_SIGNAL_ALIVE);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
send_signal_hello(void *data)
{
EDBus_Service_Interface *iface = data;
edbus_service_signal_emit(iface, TEST_SIGNAL_HELLO, "Hello World");
return ECORE_CALLBACK_RENEW;
}
static EDBus_Message *
_send_bool(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
Eina_Bool bool;
if (!edbus_message_arguments_get(msg, "b", &bool))
printf("edbus_message_arguments_get() error\n");
edbus_message_arguments_set(reply, "b", bool);
return reply;
}
static EDBus_Message *
_send_byte(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
unsigned char byte;
if (!edbus_message_arguments_get(msg, "y", &byte))
printf("edbus_message_arguments_get() error\n");
edbus_message_arguments_set(reply, "y", byte);
return reply;
}
static EDBus_Message *
_send_uint32(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
unsigned int uint32;
if (!edbus_message_arguments_get(msg, "u", &uint32))
printf("edbus_message_arguments_get() error\n");
edbus_message_arguments_set(reply, "u", uint32);
return reply;
}
static EDBus_Message *
_send_int32(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
int int32;
if (!edbus_message_arguments_get(msg, "i", &int32))
printf("edbus_message_arguments_get() error\n");
edbus_message_arguments_set(reply, "i", int32);
return reply;
}
static EDBus_Message *
_send_int16(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
short int int16;
if (!edbus_message_arguments_get(msg, "n", &int16))
printf("edbus_message_arguments_get() error\n");
edbus_message_arguments_set(reply, "n", int16);
return reply;
}
static EDBus_Message *
_send_double(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
double d;
if (!edbus_message_arguments_get(msg, "d", &d))
printf("edbus_message_arguments_get() error\n");
edbus_message_arguments_set(reply, "d", d);
return reply;
}
static EDBus_Message *
_send_string(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
char *txt;
if (!edbus_message_arguments_get(msg, "s", &txt))
printf("edbus_message_arguments_get() error\n");
edbus_message_arguments_set(reply, "s", txt);
return reply;
}
static Eina_Bool
_resp_async(void *data)
{
EDBus_Message *msg = data;
edbus_message_arguments_set(msg, "s", "Async test ok");
edbus_connection_send(conn, msg, NULL, NULL, -1);
edbus_message_unref(msg);
return ECORE_CALLBACK_CANCEL;
}
static EDBus_Message *
_async_test(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply = edbus_message_method_return_new(msg);
printf("Received a call to AsyncTest.\n");
printf("Response will be send in 5 seconds.\n");
ecore_timer_add (5, _resp_async, reply);
return NULL;
}
static const EDBus_Signal signals[] = {
[TEST_SIGNAL_ALIVE] = {"Alive", EDBUS_ARGS({ NULL, NULL }), 0},
[TEST_SIGNAL_HELLO] = {"Hello", EDBUS_ARGS({ "s", "message" }), 0},
{ }
};
static const EDBus_Method methods[] = {
{
"Hello", EDBUS_ARGS({"", ""}), EDBUS_ARGS({"s", "message"}),
_hello, 0
},
{
"Quit", EDBUS_ARGS({"", ""}), EDBUS_ARGS({"", ""}),
_quit, EDBUS_METHOD_FLAG_DEPRECATED
},
{ "SendBool", EDBUS_ARGS({"b", "bool"}), EDBUS_ARGS({"b", "bool"}),
_send_bool, 0
},
{ "SendByte", EDBUS_ARGS({"y", "byte"}), EDBUS_ARGS({"y", "byte"}),
_send_byte, 0
},
{ "SendUint32", EDBUS_ARGS({"u", "uint32"}), EDBUS_ARGS({"u", "uint32"}),
_send_uint32, 0
},
{ "SendInt32", EDBUS_ARGS({"i", "int32"}), EDBUS_ARGS({"i", "int32"}),
_send_int32, 0
},
{ "SendInt16", EDBUS_ARGS({"n", "int16"}), EDBUS_ARGS({"n", "int16"}),
_send_int16, 0
},
{ "SendDouble", EDBUS_ARGS({"d", "double"}), EDBUS_ARGS({"d", "double"}),
_send_double, 0
},
{ "SendString", EDBUS_ARGS({"s", "string"}), EDBUS_ARGS({"s", "string"}),
_send_string, 0
},
{ "AsyncTest", EDBUS_ARGS({"", ""}), EDBUS_ARGS({"s", "text"}),
_async_test, 0
},
{ }
};
static void
on_name_request(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
{
EDBus_Service_Interface *iface;
unsigned int flag;
if (edbus_message_error_get(msg, NULL, NULL))
{
printf("error on on_name_request\n");
return;
}
if (!edbus_message_arguments_get(msg, "u", &flag))
{
printf("error geting arguments on on_name_request\n");
return;
}
if (!(flag & EDBUS_NAME_REQUEST_REPLY_PRIMARY_OWNER))
{
printf("error name already in use\n");
return;
}
iface = edbus_service_interface_register(conn, PATH, INTERFACE, methods,
signals);
ecore_timer_add(5, send_signal_alive, iface);
ecore_timer_add(6, send_signal_hello, iface);
}
int
main(void)
{
ecore_init();
edbus_init();
conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
edbus_name_request(conn, BUS, EDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE,
on_name_request, NULL);
ecore_main_loop_begin();
edbus_connection_unref(conn);
edbus_shutdown();
ecore_shutdown();
return 0;
}

View File

@ -0,0 +1,141 @@
#ifndef EDBUS_H
#define EDBUS_H
#include <Eina.h>
#include <stdarg.h>
#ifdef EAPI
# undef EAPI
#endif
#ifdef _WIN32
# ifdef EFL_EDBUS_BUILD
# ifdef DLL_EXPORT
# define EAPI __declspec(dllexport)
# else
# define EAPI
# endif /* ! DLL_EXPORT */
# else
# define EAPI __declspec(dllimport)
# endif /* ! EFL_EDBUS_BUILD */
#else
# ifdef __GNUC__
# if __GNUC__ >= 4
# define EAPI __attribute__ ((visibility("default")))
# else
# define EAPI
# endif
# else
# define EAPI
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup EDBus_Core Core
*
* @{
*/
#define EDBUS_VERSION_MAJOR 1
#define EDBUS_VERSION_MINOR 6
#define EDBUS_FDO_BUS "org.freedesktop.DBus"
#define EDBUS_FDO_PATH "/org/freedesktop/DBus"
#define EDBUS_FDO_INTERFACE EDBUS_FDO_BUS
#define EDBUS_FDO_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties"
typedef struct _EDBus_Version
{
int major;
int minor;
int micro;
int revision;
} EDBus_Version;
EAPI extern const EDBus_Version * edbus_version;
/**
* @brief Initialize edbus.
*
* @return 1 or greater on success, 0 otherwise
*/
EAPI int edbus_init(void);
/**
* @brief Shutdown edbus.
*
* @return 0 if e_dbus shuts down, greater than 0 otherwise.
*/
EAPI int edbus_shutdown(void);
typedef void (*EDBus_Free_Cb)(void *data, const void *deadptr);
/**
* @typedef EDBus_Connection
*
* Represents a connection of one the type of connection with the DBus daemon.
*/
typedef struct _EDBus_Connection EDBus_Connection;
/**
* @typedef EDBus_Object
*
* Represents a object path already attach with bus name or unique id.
*/
typedef struct _EDBus_Object EDBus_Object;
/**
* @typedef EDBus_Proxy
*
* Represents a interface of a object path.
*/
typedef struct _EDBus_Proxy EDBus_Proxy;
/**
* @typedef EDBus_Message
*
* Represents the way of how the data is send and received in DBus.
*/
typedef struct _EDBus_Message EDBus_Message;
/**
* @typedef EDBus_Message_Iter
*
* Represents an iterator over a complex message type (array, dict, struct,
* or variant). Its life is bound to the message that contains
* it. The same applies to the returned data.
*/
typedef struct _EDBus_Message_Iter EDBus_Message_Iter;
/**
* @typedef EDBus_Pending
*
* Represents a message that was been sent but has not yet reached its
* destination.
*/
typedef struct _EDBus_Pending EDBus_Pending;
/**
* @typedef EDBus_Signal_Handler
*
* Represents a listener that will listen for signals emitted by other
* applications.
*/
typedef struct _EDBus_Signal_Handler EDBus_Signal_Handler;
typedef void (*EDBus_Message_Cb)(void *data, const EDBus_Message *msg, EDBus_Pending *pending);
typedef void (*EDBus_Signal_Cb)(void *data, const EDBus_Message *msg);
/**
* @}
*/
#include "edbus_connection.h"
#include "edbus_message.h"
#include "edbus_signal_handler.h"
#include "edbus_pending.h"
#include "edbus_object.h"
#include "edbus_proxy.h"
#include "edbus_freedesktop.h"
#include "edbus_service.h"
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,144 @@
#ifndef EDBUS_CONNECTION_H
#define EDBUS_CONNECTION_H 1
/**
* @defgroup EDBus_Conneciton Connection
*
* @{
*/
typedef enum
{
EDBUS_CONNECTION_TYPE_UNKNOWN = 0, /**< sentinel, not a real type */
EDBUS_CONNECTION_TYPE_SESSION,
EDBUS_CONNECTION_TYPE_SYSTEM,
EDBUS_CONNECTION_TYPE_STARTER,
EDBUS_CONNECTION_TYPE_LAST /**< sentinel, not a real type */
} EDBus_Connection_Type;
#define EDBUS_TIMEOUT_INFINITE ((int) 0x7fffffff)
/**
* @brief Establish a connection to bus and integrate it with the ecore main
* loop.
*
* @param type type of connection e.g EDBUS_CONNECTION_TYPE_SESSION,
* EDBUS_CONNECTION_TYPE_SYSTEM or EDBUS_CONNECTION_TYPE_STARTER
*
* @return connection with bus
*/
EAPI EDBus_Connection *edbus_connection_get(EDBus_Connection_Type type);
/**
* @brief Increment connection reference count.
*
* @param conn The given EDBus_Connection object to reference
*/
EAPI EDBus_Connection *edbus_connection_ref(EDBus_Connection *conn) EINA_ARG_NONNULL(1);
/**
* @brief Decrement object reference count.
*
* If reference count reaches 0, the connection to bus will be dropped and all
* its children will be invalidated.
*/
EAPI void edbus_connection_unref(EDBus_Connection *conn) EINA_ARG_NONNULL(1);
/**
* @brief Add a callback function to be called when connection is freed
*
* @param conn The connection object to add the callback to.
* @param cb callback to be called
* @param data passed to callback
*/
EAPI void edbus_connection_cb_free_add(EDBus_Connection *conn, EDBus_Free_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
/**
* @brief Remove callback registered in edbus_connection_cb_free_add().
*/
EAPI void edbus_connection_cb_free_del(EDBus_Connection *conn, EDBus_Free_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
/**
* @brief Set an attached data pointer to an object with a given string key.
*
* @param conn The connection object to store data to
* @param key to identify data
* @param data data that will be stored
*/
EAPI void edbus_connection_data_set(EDBus_Connection *conn, const char *key, const void *data) EINA_ARG_NONNULL(1, 2, 3);
/**
* @brief Get data stored in connection.
*
* @param conn connection where data are stored
* @param key that identify data
*
* @return pointer to data if found otherwise NULL
*/
EAPI void *edbus_connection_data_get(const EDBus_Connection *conn, const char *key) EINA_ARG_NONNULL(1, 2);
/**
* @brief Del data stored in connection.
*
* @param conn connection where data are stored
* @param key that identify data
*
* @return pointer to data if found otherwise NULL
*/
EAPI void *edbus_connection_data_del(EDBus_Connection *conn, const char *key) EINA_ARG_NONNULL(1, 2);
typedef enum
{
EDBUS_CONNECTION_EVENT_OBJECT_ADDED = 0,
EDBUS_CONNECTION_EVENT_OBJECT_REMOVED,
//EDBUS_CONNECTION_EVENT_NAME_OWNER_CHANGED,
EDBUS_CONNECTION_EVENT_DEL,
EDBUS_CONNECTION_EVENT_LAST /**< sentinel, not a real event type */
} EDBus_Connection_Event_Type;
typedef struct _EDBus_Connection_Event_Object_Added
{
const char *path;
EDBus_Object *object;
} EDBus_Connection_Event_Object_Added;
typedef struct _EDBus_Connection_Event_Object_Removed
{
const char *path;
} EDBus_Connection_Event_Object_Removed;
typedef struct _EDBus_Connection_Event_Name_Owner_Changed
{
const char *name;
const char *old_id;
const char *new_id;
} EDBus_Connection_Event_Name_Owner_Changed;
typedef void (*EDBus_Connection_Event_Cb)(void *data, EDBus_Connection *conn, void *event_info);
/**
* @brief Add a callback function to be called when occurs a event of the
* type passed.
*/
EAPI void edbus_connection_event_callback_add(EDBus_Connection *conn, EDBus_Connection_Event_Type type, EDBus_Connection_Event_Cb cb, const void *cb_data) EINA_ARG_NONNULL(1, 3);
/**
* @brief Remove callback registered in edbus_connection_event_callback_add().
*/
EAPI void edbus_connection_event_callback_del(EDBus_Connection *conn, EDBus_Connection_Event_Type type, EDBus_Connection_Event_Cb cb, const void *cb_data) EINA_ARG_NONNULL(1, 3);
/**
* @brief Send a message.
*
* @param conn the connection where the message will be send
* @param msg message that will be send
* @param cb if msg is a method call a callback should be passed
* to be execute when response arrive
* @param cb_data data passed to callback
* @param timeout timeout in milliseconds, -1 to default internal value or
* EDBUS_TIMEOUT_INFINITE for no timeout
*/
EAPI EDBus_Pending *edbus_connection_send(EDBus_Connection *conn, EDBus_Message *msg, EDBus_Message_Cb cb, const void *cb_data, double timeout) EINA_ARG_NONNULL(1, 2);
/**
* @}
*/
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,80 @@
#include "edbus_private.h"
#include "edbus_private_types.h"
#include <dbus/dbus.h>
static EDBus_Proxy *
get_freedesktop_proxy(EDBus_Connection *conn)
{
EDBus_Object *freedesktop_obj;
freedesktop_obj = edbus_object_get(conn, EDBUS_FDO_BUS, EDBUS_FDO_PATH);
return edbus_proxy_get(freedesktop_obj, EDBUS_FDO_INTERFACE);
}
EAPI EDBus_Pending *
edbus_name_request(EDBus_Connection *conn, const char *name, unsigned int flags, EDBus_Message_Cb cb, const void *cb_data)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
return edbus_proxy_call(get_freedesktop_proxy(conn), "RequestName", cb,
cb_data, -1, "su", name, flags);
}
EAPI EDBus_Pending *
edbus_name_release(EDBus_Connection *conn, const char *name, EDBus_Message_Cb cb, const void *cb_data)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
return edbus_proxy_call(get_freedesktop_proxy(conn), "ReleaseName", cb,
cb_data, -1, "s", name);
}
EAPI EDBus_Pending *
edbus_name_owner_get(EDBus_Connection *conn, const char *name, EDBus_Message_Cb cb, const void *cb_data)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
return edbus_proxy_call(get_freedesktop_proxy(conn), "GetNameOwner", cb,
cb_data, -1, "s", name);
}
EAPI EDBus_Pending *
edbus_name_owner_has(EDBus_Connection *conn, const char *name, EDBus_Message_Cb cb, const void *cb_data)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
return edbus_proxy_call(get_freedesktop_proxy(conn), "NameHasOwner", cb,
cb_data, -1, "s", name);
}
EAPI EDBus_Pending *
edbus_names_list(EDBus_Connection *conn, EDBus_Message_Cb cb, const void *cb_data)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
return edbus_proxy_call(get_freedesktop_proxy(conn), "ListNames", cb,
cb_data, -1, "");
}
EAPI EDBus_Pending *
edbus_names_activatable_list(EDBus_Connection *conn, EDBus_Message_Cb cb, const void *cb_data)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
return edbus_proxy_call(get_freedesktop_proxy(conn), "ListActivatableNames", cb,
cb_data, -1, "");
}
EAPI EDBus_Pending *
edbus_name_start(EDBus_Connection *conn, const char *name, unsigned int flags, EDBus_Message_Cb cb, const void *cb_data)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
return edbus_proxy_call(get_freedesktop_proxy(conn), "StartServiceByName", cb,
cb_data, -1, "su", name, flags);
}

View File

@ -0,0 +1,126 @@
#ifndef EDBUS_FREEDESKTOP_H
#define EDBUS_FREEDESKTOP_H 1
/**
* @defgroup EDBus_Basic Basic Methods
*
* @{
*/
#define EDBUS_NAME_REQUEST_FLAG_ALLOW_REPLACEMENT 0x1 /**< Allow another service to become the primary owner if requested */
#define EDBUS_NAME_REQUEST_FLAG_REPLACE_EXISTING 0x2 /**< Request to replace the current primary owner */
#define EDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE 0x4 /**< If we can not become the primary owner do not place us in the queue */
/* Replies to request for a name */
#define EDBUS_NAME_REQUEST_REPLY_PRIMARY_OWNER 1 /**< Service has become the primary owner of the requested name */
#define EDBUS_NAME_REQUEST_REPLY_IN_QUEUE 2 /**< Service could not become the primary owner and has been placed in the queue */
#define EDBUS_NAME_REQUEST_REPLY_EXISTS 3 /**< Service is already in the queue */
#define EDBUS_NAME_REQUEST_REPLY_ALREADY_OWNER 4 /**< Service is already the primary owner */
EAPI EDBus_Pending *edbus_name_request(EDBus_Connection *conn, const char *bus, unsigned int flags, EDBus_Message_Cb cb, const void *cb_data);
/* Replies to releasing a name */
#define EDBUS_NAME_RELEASE_REPLY_RELEASED 1 /**< Service was released from the given name */
#define EDBUS_NAME_RELEASE_REPLY_NON_EXISTENT 2 /**< The given name does not exist on the bus */
#define EDBUS_NAME_RELEASE_REPLY_NOT_OWNER 3 /**< Service is not an owner of the given name */
EAPI EDBus_Pending *edbus_name_release(EDBus_Connection *conn, const char *bus, EDBus_Message_Cb cb, const void *cb_data);
EAPI EDBus_Pending *edbus_name_owner_get(EDBus_Connection *conn, const char *bus, EDBus_Message_Cb cb, const void *cb_data);
EAPI EDBus_Pending *edbus_name_owner_has(EDBus_Connection *conn, const char *bus, EDBus_Message_Cb cb, const void *cb_data);
EAPI EDBus_Pending *edbus_names_list(EDBus_Connection *conn, EDBus_Message_Cb cb, const void *cb_data);
EAPI EDBus_Pending *edbus_names_activatable_list(EDBus_Connection *conn, EDBus_Message_Cb cb, const void *cb_data);
/* Replies to service starts */
#define EDBUS_NAME_START_REPLY_SUCCESS 1 /**< Service was auto started */
#define EDBUS_NAME_START_REPLY_ALREADY_RUNNING 2 /**< Service was already running */
EAPI EDBus_Pending *edbus_name_start(EDBus_Connection *conn, const char *bus, unsigned int flags, EDBus_Message_Cb cb, const void *cb_data);
typedef void (*EDBus_Name_Owner_Changed_Cb)(void *data, const char *bus, const char *old_id, const char *new_id);
EAPI void edbus_name_owner_changed_callback_add(EDBus_Connection *conn, const char *bus, EDBus_Name_Owner_Changed_Cb cb, const void *cb_data);
EAPI void edbus_name_owner_changed_callback_del(EDBus_Connection *conn, const char *bus, EDBus_Name_Owner_Changed_Cb cb, const void *cb_data);
/**
* @defgroup EDBus_FDO_Peer org.freedesktop.DBus.Peer
*
* @{
*/
EAPI EDBus_Pending *edbus_object_peer_ping(EDBus_Object *obj, EDBus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1);
EAPI EDBus_Pending *edbus_object_peer_machine_id_get(EDBus_Object *obj, EDBus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
/**
* @}
*/
/**
* @defgroup EDBus_FDO_Introspectable org.freedesktop.DBus.Introspectable
*
* @{
*/
EAPI EDBus_Pending *edbus_object_introspect(EDBus_Object *obj, EDBus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
/**
* @}
*/
/**
* @defgroup EDBus_FDO_Properties org.freedesktop.DBus.Properties
*
* Whenever edbus_proxy_properties_monitor() is called on a
* proxy to an object it will automatically listen for properties
* changed on that interface, emitting events with
* edbus_object_event_type being
* #EDBUS_OBJECT_EVENT_PROPERTY_CHANGED and
* #EDBUS_OBJECT_EVENT_PROPERTY_REMOVED, as well as
* #EDBUS_PROXY_EVENT_PROPERTY_CHANGED and
* #EDBUS_PROXY_EVENT_PROPERTY_REMOVED.
*
* One may manually query the properties
* edbus_proxy_property_get() and edbus_proxy_property_get_all()
* or listen for changes with
* edbus_proxy_properties_changed_callback_add().
*
* To set property call edbus_proxy_property_set().
*
* @{
*/
EAPI void edbus_proxy_properties_monitor(EDBus_Proxy *proxy);
EAPI EDBus_Pending *edbus_proxy_property_get(EDBus_Proxy *proxy, const char *name, EDBus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2, 3);
EAPI EDBus_Pending *edbus_proxy_property_set(EDBus_Proxy *proxy, const char *name, char type, const void *value, EDBus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2, 4);
EAPI EDBus_Pending *edbus_proxy_property_get_all(EDBus_Proxy *proxy, EDBus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
EAPI EDBus_Signal_Handler *edbus_proxy_properties_changed_callback_add(EDBus_Proxy *proxy, EDBus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
/**
* @}
*/
/**
* @defgroup EDBus_FDO_ObjectManager org.freedesktop.DBus.ObjectManager
*
* Whenever edbus_object_managed_objects_monitor() is called on an
* object it will start listening for children being added or
* interfaces changing on the object itself. It will then emit
* events with edbus_object_event_type being
* #EDBUS_OBJECT_EVENT_IFACE_ADDED,
* #EDBUS_OBJECT_EVENT_IFACE_REMOVED,
* #EDBUS_OBJECT_EVENT_PROPERTY_CHANGED and
* #EDBUS_OBJECT_EVENT_PROPERTY_REMOVED.
*
* One may manually query the managed objects with
* edbus_object_managed_objects_get() and listen for changes with
* edbus_object_interfaces_added_callback_add() and
* edbus_object_interfaces_removed_callback_add().
*
* @{
*/
EAPI void edbus_object_properties_monitor(EDBus_Object *obj);
EAPI EDBus_Pending *edbus_object_managed_objects_get(EDBus_Object *obj, EDBus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
EAPI EDBus_Signal_Handler *edbus_object_interfaces_added_callback_add(EDBus_Object *obj, EDBus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
EAPI EDBus_Signal_Handler *edbus_object_interfaces_removed_callback_add(EDBus_Object *obj, EDBus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
/**
* @}
*/
/**
* @}
*/
#endif

View File

@ -0,0 +1,792 @@
#include "edbus_private.h"
#include "edbus_private_types.h"
#include <dbus/dbus.h>
#include <stdint.h>
/* TODO: mempool of EDBus_Message and EDBus_Message_Iter */
#define EDBUS_MESSAGE_CHECK(msg) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN(msg); \
if (!EINA_MAGIC_CHECK(msg, EDBUS_MESSAGE_MAGIC)) \
{ \
EINA_MAGIC_FAIL(msg, EDBUS_MESSAGE_MAGIC); \
return; \
} \
EINA_SAFETY_ON_TRUE_RETURN(msg->refcount <= 0); \
} \
while (0)
#define EDBUS_MESSAGE_CHECK_RETVAL(msg, retval) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN_VAL(msg, retval); \
if (!EINA_MAGIC_CHECK(msg, EDBUS_MESSAGE_MAGIC)) \
{ \
EINA_MAGIC_FAIL(msg, EDBUS_MESSAGE_MAGIC); \
return retval; \
} \
EINA_SAFETY_ON_TRUE_RETURN_VAL(msg->refcount <= 0, retval); \
} \
while (0)
#define EDBUS_MESSAGE_ITERATOR_CHECK(iter) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN(iter); \
if (!EINA_MAGIC_CHECK(iter, EDBUS_MESSAGE_ITERATOR_MAGIC)) \
{ \
EINA_MAGIC_FAIL(iter, EDBUS_MESSAGE_ITERATOR_MAGIC); \
return; \
} \
} \
while (0)
#define EDBUS_MESSAGE_ITERATOR_CHECK_RETVAL(iter, retval) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN_VAL(iter, retval); \
if (!EINA_MAGIC_CHECK(iter, EDBUS_MESSAGE_ITERATOR_MAGIC)) \
{ \
EINA_MAGIC_FAIL(iter, EDBUS_MESSAGE_ITERATOR_MAGIC); \
return retval; \
} \
} \
while (0)
static Eina_Bool append_basic(char type, va_list *vl, DBusMessageIter *iter);
Eina_Bool
edbus_message_init(void)
{
return EINA_TRUE;
}
void
edbus_message_shutdown(void)
{
}
static EDBus_Message_Iter *
_message_iterator_new(Eina_Bool writable)
{
EDBus_Message_Iter *iter;
iter = calloc(1, sizeof(EDBus_Message_Iter));
EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
EINA_MAGIC_SET(iter, EDBUS_MESSAGE_ITERATOR_MAGIC);
iter->writable = writable;
return iter;
}
EDBus_Message *edbus_message_new(Eina_Bool writable)
{
EDBus_Message *msg = calloc(1, sizeof(EDBus_Message));
EINA_SAFETY_ON_NULL_RETURN_VAL(msg, NULL);
EINA_MAGIC_SET(msg, EDBUS_MESSAGE_MAGIC);
msg->refcount = 1;
msg->iterator = _message_iterator_new(writable);
EINA_SAFETY_ON_NULL_GOTO(msg->iterator, fail);
return msg;
fail:
edbus_message_unref(msg);
return NULL;
}
EAPI EDBus_Message *
edbus_message_method_call_new(const char *dest, const char *path, const char *iface, const char *method)
{
EDBus_Message *msg;
EINA_SAFETY_ON_NULL_RETURN_VAL(dest, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(iface, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(method, NULL);
msg = edbus_message_new(EINA_TRUE);
EINA_SAFETY_ON_NULL_GOTO(msg, fail);
msg->dbus_msg = dbus_message_new_method_call(dest, path, iface, method);
dbus_message_iter_init_append(msg->dbus_msg, &msg->iterator->dbus_iterator);
return msg;
fail:
edbus_message_unref(msg);
return NULL;
}
EAPI EDBus_Message *
edbus_message_ref(EDBus_Message *msg)
{
EDBUS_MESSAGE_CHECK_RETVAL(msg, NULL);
DBG("msg=%p, pre-refcount=%d", msg, msg->refcount);
msg->refcount++;
return msg;
}
static void
_message_iterator_free(EDBus_Message_Iter *iter)
{
Eina_Inlist *lst, *next;
EDBus_Message_Iter *sub;
if (!iter) return;
lst = iter->iterators;
while (lst)
{
next = lst->next;
sub = EINA_INLIST_CONTAINER_GET(lst, EDBus_Message_Iter);
_message_iterator_free(sub);
lst = next;
}
free(iter);
}
EAPI void
edbus_message_unref(EDBus_Message *msg)
{
EDBUS_MESSAGE_CHECK(msg);
DBG("msg=%p, pre-refcount=%d", msg, msg->refcount);
msg->refcount--;
if (msg->refcount > 0) return;
DBG("message free %p", msg);
EINA_MAGIC_SET(msg, EINA_MAGIC_NONE);
if (msg->dbus_msg)
dbus_message_unref(msg->dbus_msg);
msg->dbus_msg = NULL;
_message_iterator_free(msg->iterator);
free(msg);
}
EAPI const char *
edbus_message_path_get(const EDBus_Message *msg)
{
EDBUS_MESSAGE_CHECK_RETVAL(msg, NULL);
return dbus_message_get_path(msg->dbus_msg);
}
EAPI const char *
edbus_message_interface_get(const EDBus_Message *msg)
{
EDBUS_MESSAGE_CHECK_RETVAL(msg, NULL);
return dbus_message_get_interface(msg->dbus_msg);
}
EAPI const char *
edbus_message_member_get(const EDBus_Message *msg)
{
EDBUS_MESSAGE_CHECK_RETVAL(msg, NULL);
return dbus_message_get_member(msg->dbus_msg);
}
EAPI const char *
edbus_message_destination_get(const EDBus_Message *msg)
{
EDBUS_MESSAGE_CHECK_RETVAL(msg, NULL);
return dbus_message_get_destination(msg->dbus_msg);
}
EAPI const char *
edbus_message_sender_get(const EDBus_Message *msg)
{
EDBUS_MESSAGE_CHECK_RETVAL(msg, NULL);
return dbus_message_get_sender(msg->dbus_msg);
}
EAPI const char *
edbus_message_signature_get(const EDBus_Message *msg)
{
EDBUS_MESSAGE_CHECK_RETVAL(msg, NULL);
return dbus_message_get_signature(msg->dbus_msg);
}
EAPI Eina_Bool
edbus_message_error_get(const EDBus_Message *msg, const char **name, const char **text)
{
if (name) *name = NULL;
if (text) *text = NULL;
EDBUS_MESSAGE_CHECK_RETVAL(msg, EINA_FALSE);
if (dbus_message_get_type(msg->dbus_msg) != DBUS_MESSAGE_TYPE_ERROR)
return EINA_FALSE;
if (name)
*name = dbus_message_get_error_name(msg->dbus_msg);
if (text)
dbus_message_get_args(msg->dbus_msg, NULL, DBUS_TYPE_STRING, text,
DBUS_TYPE_INVALID);
return EINA_TRUE;
}
static Eina_Bool
_edbus_message_arguments_vget(EDBus_Message *msg, const char *signature, va_list ap)
{
EDBus_Message_Iter *iter;
iter = edbus_message_iter_get(msg);
EDBUS_MESSAGE_ITERATOR_CHECK_RETVAL(iter, EINA_FALSE);
return edbus_message_iter_arguments_vget(iter, signature, ap);
}
EAPI EDBus_Message_Iter *
edbus_message_iter_get(EDBus_Message *msg)
{
EDBUS_MESSAGE_CHECK_RETVAL(msg, NULL);
/* Something went wrong, msg->iterator should not be NULL */
EINA_SAFETY_ON_NULL_RETURN_VAL(msg->iterator, NULL);
return msg->iterator;
}
EAPI Eina_Bool
edbus_message_arguments_get(const EDBus_Message *msg, const char *signature, ...)
{
Eina_Bool ret;
va_list ap;
EDBUS_MESSAGE_CHECK_RETVAL(msg, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(signature, EINA_FALSE);
va_start(ap, signature);
ret = _edbus_message_arguments_vget((EDBus_Message *)msg, signature, ap);
va_end(ap);
return ret;
}
EAPI Eina_Bool
edbus_message_arguments_vget(const EDBus_Message *msg, const char *signature, va_list ap)
{
EDBUS_MESSAGE_CHECK_RETVAL(msg, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(signature, EINA_FALSE);
return _edbus_message_arguments_vget((EDBus_Message *)msg, signature, ap);
}
EAPI Eina_Bool
edbus_message_iter_arguments_vset(EDBus_Message_Iter *iter, const char *signature, va_list ap)
{
DBusSignatureIter signature_iter;
Eina_Bool r = EINA_TRUE;
char *type;
EINA_SAFETY_ON_FALSE_RETURN_VAL(iter->writable, EINA_FALSE);
dbus_signature_iter_init(&signature_iter, signature);
while ((type = dbus_signature_iter_get_signature(&signature_iter)) && r)
{
if (type[0] != DBUS_TYPE_VARIANT && !type[1])
r = append_basic(type[0], MAKE_PTR_FROM_VA_LIST(ap),
&iter->dbus_iterator);
else
{
EDBus_Message_Iter **user_itr;
EDBus_Message_Iter *sub;
user_itr = va_arg(ap, EDBus_Message_Iter **);
sub = _message_iterator_new(EINA_TRUE);
EINA_SAFETY_ON_NULL_GOTO(sub, error);
iter->iterators = eina_inlist_append(iter->iterators,
EINA_INLIST_GET(sub));
if (type[0] == DBUS_TYPE_ARRAY)
r = dbus_message_iter_open_container(&iter->dbus_iterator,
type[0], type+1,
&sub->dbus_iterator);
else if(type[1] == DBUS_TYPE_VARIANT)
{
ERR("variant not supported by \
edbus_message_iter_arguments_set(), \
try edbus_message_iter_container_new()");
goto error;
}
else
{
char real_type;
if (type[0] == DBUS_STRUCT_BEGIN_CHAR)
real_type = DBUS_TYPE_STRUCT;
else real_type = DBUS_TYPE_DICT_ENTRY;
r = dbus_message_iter_open_container(&iter->dbus_iterator,
real_type, NULL,
&sub->dbus_iterator);
}
*user_itr = sub;
}
dbus_free(type);
if (!dbus_signature_iter_next(&signature_iter)) break;
continue;
error:
r = EINA_FALSE;
dbus_free(type);
break;
}
return r;
}
EAPI Eina_Bool
edbus_message_iter_arguments_set(EDBus_Message_Iter *iter, const char *signature, ...)
{
Eina_Bool r;
va_list ap;
EDBUS_MESSAGE_ITERATOR_CHECK_RETVAL(iter, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(signature, EINA_FALSE);
va_start(ap, signature);
r = edbus_message_iter_arguments_vset(iter, signature, ap);
va_end(ap);
return r;
}
static Eina_Bool
append_basic(char type, va_list *vl, DBusMessageIter *iter)
{
switch (type)
{
case DBUS_TYPE_BYTE:
{
uint32_t read_byte = va_arg(*vl, uint32_t);
uint8_t byte = read_byte;
return dbus_message_iter_append_basic(iter, type, &byte);
}
case DBUS_TYPE_INT16:
{
int32_t read_int16 = va_arg(*vl, int32_t);
int16_t int16 = read_int16;
return dbus_message_iter_append_basic(iter, type, &int16);
}
case DBUS_TYPE_UINT16:
{
uint32_t read_uint16 = va_arg(*vl, uint32_t);
uint16_t uint16 = read_uint16;
return dbus_message_iter_append_basic(iter, type, &uint16);
}
case DBUS_TYPE_BOOLEAN:
case DBUS_TYPE_INT32:
case DBUS_TYPE_UNIX_FD:
{
int32_t int32 = va_arg(*vl, int32_t);
return dbus_message_iter_append_basic(iter, type, &int32);
}
case DBUS_TYPE_UINT32:
{
uint32_t uint32 = va_arg(*vl, uint32_t);
return dbus_message_iter_append_basic(iter, type, &uint32);
}
case DBUS_TYPE_INT64:
{
int64_t int64 = va_arg(*vl, int64_t);
return dbus_message_iter_append_basic(iter, type, &int64);
}
case DBUS_TYPE_UINT64:
{
uint64_t uint64 = va_arg(*vl, uint64_t);
return dbus_message_iter_append_basic(iter, type, &uint64);
}
case DBUS_TYPE_DOUBLE:
{
double double_ieee = va_arg(*vl, double);
return dbus_message_iter_append_basic(iter, type, &double_ieee);
}
case DBUS_TYPE_STRING:
case DBUS_TYPE_OBJECT_PATH:
case DBUS_TYPE_SIGNATURE:
{
char *string = va_arg(*vl, char*);
return dbus_message_iter_append_basic(iter, type, &string);
}
default:
ERR("Type not handled %c", type);
return EINA_FALSE;
}
}
static Eina_Bool
_edbus_message_arguments_vset(EDBus_Message *msg, const char *signature, va_list ap)
{
DBusSignatureIter signature_iter;
EDBus_Message_Iter *iter;
char *type;
Eina_Bool r = EINA_TRUE;
if (!signature || !signature[0]) return EINA_TRUE;
EINA_SAFETY_ON_FALSE_RETURN_VAL(dbus_signature_validate(signature, NULL), EINA_FALSE);
iter = edbus_message_iter_get(msg);
EINA_SAFETY_ON_FALSE_RETURN_VAL(iter->writable, EINA_FALSE);
dbus_signature_iter_init(&signature_iter, signature);
while ((type = dbus_signature_iter_get_signature(&signature_iter)) && r)
{
if (dbus_type_is_basic(type[0]))
r = append_basic(type[0], MAKE_PTR_FROM_VA_LIST(ap),
&iter->dbus_iterator);
else
{
ERR("edbus_message_arguments_set() and \
edbus_message_arguments_vset() only support basic types, \
to complex types use edbus_message_iter_* functions");
r = EINA_FALSE;
}
dbus_free(type);
if (!dbus_signature_iter_next(&signature_iter)) break;
}
return r;
}
EAPI Eina_Bool
edbus_message_arguments_set(EDBus_Message *msg, const char *signature, ...)
{
Eina_Bool ret;
va_list ap;
EDBUS_MESSAGE_CHECK_RETVAL(msg, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(signature, EINA_FALSE);
va_start(ap, signature);
ret = _edbus_message_arguments_vset(msg, signature, ap);
va_end(ap);
return ret;
}
EAPI Eina_Bool
edbus_message_arguments_vset(EDBus_Message *msg, const char *signature, va_list ap)
{
EDBUS_MESSAGE_CHECK_RETVAL(msg, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(signature, EINA_FALSE);
return _edbus_message_arguments_vset(msg, signature, ap);
}
EAPI EDBus_Message_Iter *
edbus_message_iter_container_new(EDBus_Message_Iter *iter, int type, const char* contained_signature)
{
EDBus_Message_Iter *sub;
EDBUS_MESSAGE_ITERATOR_CHECK_RETVAL(iter, NULL);
sub = _message_iterator_new(EINA_TRUE);
EINA_SAFETY_ON_NULL_RETURN_VAL(sub, NULL);
if (!dbus_message_iter_open_container(&iter->dbus_iterator, type,
contained_signature,
&sub->dbus_iterator))
goto cleanup;
iter->iterators = eina_inlist_append(iter->iterators, EINA_INLIST_GET(sub));
return sub;
cleanup:
free(sub);
return NULL;
}
EAPI Eina_Bool
edbus_message_iter_container_close(EDBus_Message_Iter *iter, EDBus_Message_Iter *sub)
{
EDBUS_MESSAGE_ITERATOR_CHECK_RETVAL(iter, EINA_FALSE);
EDBUS_MESSAGE_ITERATOR_CHECK_RETVAL(sub, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(iter->writable, EINA_FALSE);
return dbus_message_iter_close_container(&iter->dbus_iterator,
&sub->dbus_iterator);
}
EAPI Eina_Bool
edbus_message_iter_append_basic(EDBus_Message_Iter *iter, int type, ...)
{
Eina_Bool r;
va_list vl;
EDBUS_MESSAGE_ITERATOR_CHECK_RETVAL(iter, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(iter->writable, EINA_FALSE);
va_start(vl, type);
r = append_basic(type, &vl, &iter->dbus_iterator);
va_end(vl);
return r;
}
EAPI void
edbus_message_iter_get_basic(EDBus_Message_Iter *iter, void *value)
{
EDBUS_MESSAGE_ITERATOR_CHECK(iter);
EINA_SAFETY_ON_TRUE_RETURN(iter->writable);
dbus_message_iter_get_basic(&iter->dbus_iterator, value);
}
EAPI char*
edbus_message_iter_signature_get(EDBus_Message_Iter *iter)
{
return dbus_message_iter_get_signature(&iter->dbus_iterator);
}
EAPI Eina_Bool
edbus_message_iter_next(EDBus_Message_Iter *iter)
{
EDBUS_MESSAGE_ITERATOR_CHECK_RETVAL(iter, EINA_FALSE);
EINA_SAFETY_ON_TRUE_RETURN_VAL(iter->writable, EINA_FALSE);
return dbus_message_iter_next(&iter->dbus_iterator);
}
static void
get_basic(char type, DBusMessageIter *iter, va_list *vl)
{
switch (type)
{
case DBUS_TYPE_BYTE:
{
uint8_t *byte = va_arg(*vl, uint8_t *);
dbus_message_iter_get_basic(iter, byte);
break;
}
case DBUS_TYPE_BOOLEAN:
{
Eina_Bool *boolean = va_arg(*vl, Eina_Bool *);
dbus_bool_t val;
dbus_message_iter_get_basic(iter, &val);
*boolean = val;
break;
}
case DBUS_TYPE_INT16:
{
int16_t *int16 = va_arg(*vl, int16_t *);
dbus_message_iter_get_basic(iter, int16);
break;
}
case DBUS_TYPE_UINT16:
{
uint16_t *uint16 = va_arg(*vl, uint16_t *);
dbus_message_iter_get_basic(iter, uint16);
break;
}
case DBUS_TYPE_INT32:
case DBUS_TYPE_UNIX_FD:
{
int32_t *int32 = va_arg(*vl, int32_t *);
dbus_message_iter_get_basic(iter, int32);
break;
}
case DBUS_TYPE_UINT32:
{
uint32_t *uint32 = va_arg(*vl, uint32_t *);
dbus_message_iter_get_basic(iter, uint32);
break;
}
case DBUS_TYPE_INT64:
{
int64_t *int64 = va_arg(*vl, int64_t *);
dbus_message_iter_get_basic(iter, int64);
break;
}
case DBUS_TYPE_UINT64:
{
uint64_t *uint64 = va_arg(*vl, uint64_t *);
dbus_message_iter_get_basic(iter, uint64);
break;
}
case DBUS_TYPE_DOUBLE:
{
double *double_ieee = va_arg(*vl, double *);
dbus_message_iter_get_basic(iter, double_ieee);
break;
}
case DBUS_TYPE_STRING:
case DBUS_TYPE_OBJECT_PATH:
case DBUS_TYPE_SIGNATURE:
{
char **string = va_arg(*vl, char**);
dbus_message_iter_get_basic(iter, string);
break;
}
default:
{
ERR("Type not handled %c", type);
}
}
}
EAPI Eina_Bool
edbus_message_iter_fixed_array_get(EDBus_Message_Iter *iter, int signature, void *value, int *n_elements)
{
EDBUS_MESSAGE_ITERATOR_CHECK_RETVAL(iter, EINA_FALSE);
EINA_SAFETY_ON_TRUE_RETURN_VAL(iter->writable, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(
(dbus_message_iter_get_element_type(&iter->dbus_iterator) == signature),
EINA_FALSE);
dbus_message_iter_get_fixed_array(&iter->dbus_iterator, value, n_elements);
return EINA_TRUE;
}
/**
* Useful when iterating over arrays
*/
EAPI Eina_Bool
edbus_message_iter_get_and_next(EDBus_Message_Iter *iter, char signature, ...)
{
char type;
va_list vl;
EDBUS_MESSAGE_ITERATOR_CHECK_RETVAL(iter, EINA_FALSE);
EINA_SAFETY_ON_TRUE_RETURN_VAL(iter->writable, EINA_FALSE);
va_start(vl, signature);
type = dbus_message_iter_get_arg_type(&iter->dbus_iterator);
if (type == DBUS_TYPE_INVALID) return EINA_FALSE;
EINA_SAFETY_ON_FALSE_RETURN_VAL(type == signature, EINA_FALSE);
if (dbus_type_is_basic(type))
get_basic(type, &iter->dbus_iterator, &vl);
else
{
EDBus_Message_Iter *sub;
EDBus_Message_Iter **iter_var = va_arg(vl, EDBus_Message_Iter**);
sub = _message_iterator_new(EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(sub, EINA_FALSE);
dbus_message_iter_recurse(&iter->dbus_iterator,
&sub->dbus_iterator);
iter->iterators = eina_inlist_append(iter->iterators,
EINA_INLIST_GET(sub));
*iter_var = sub;
}
va_end(vl);
dbus_message_iter_next(&iter->dbus_iterator);
return EINA_TRUE;
}
EAPI Eina_Bool
edbus_message_iter_arguments_get(EDBus_Message_Iter *iter, const char *signature, ...)
{
va_list ap;
Eina_Bool ret;
va_start(ap, signature);
ret = edbus_message_iter_arguments_vget(iter, signature, ap);
va_end(ap);
return ret;
}
EAPI Eina_Bool
edbus_message_iter_arguments_vget(EDBus_Message_Iter *iter, const char *signature, va_list ap)
{
int current_type;
DBusSignatureIter signature_iter;
EDBUS_MESSAGE_ITERATOR_CHECK_RETVAL(iter, EINA_FALSE);
EINA_SAFETY_ON_TRUE_RETURN_VAL(iter->writable, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(signature, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(dbus_signature_validate(signature, NULL), EINA_FALSE);
dbus_signature_iter_init(&signature_iter, signature);
current_type = dbus_message_iter_get_arg_type(&iter->dbus_iterator);
while (current_type != DBUS_TYPE_INVALID)
{
char *iter_sig = dbus_signature_iter_get_signature(&signature_iter);
int c = iter_sig[0];
dbus_free(iter_sig);
dbus_signature_iter_next(&signature_iter);
EINA_SAFETY_ON_FALSE_RETURN_VAL(c == current_type, EINA_FALSE);
if (dbus_type_is_basic(current_type))
get_basic(current_type, &iter->dbus_iterator, MAKE_PTR_FROM_VA_LIST(ap));
else
{
EDBus_Message_Iter **user_itr = va_arg(ap, EDBus_Message_Iter **);
EDBus_Message_Iter *sub_itr;
sub_itr = _message_iterator_new(EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(sub_itr, EINA_FALSE);
dbus_message_iter_recurse(&iter->dbus_iterator,
&sub_itr->dbus_iterator);
iter->iterators = eina_inlist_append(iter->iterators,
EINA_INLIST_GET(sub_itr));
*user_itr = sub_itr;
}
dbus_message_iter_next(&iter->dbus_iterator);
current_type = dbus_message_iter_get_arg_type(&iter->dbus_iterator);
}
return EINA_TRUE;
}
EAPI void
edbus_message_iter_del(EDBus_Message_Iter *iter)
{
EDBUS_MESSAGE_ITERATOR_CHECK(iter);
_message_iterator_free(iter);
}
/* TODO: proper doc
* Return the *reply* to @msg, i.e. @msg is the message we are replying to.
*/
EAPI EDBus_Message *
edbus_message_error_new(const EDBus_Message *msg, const char *error_name, const char *error_msg)
{
EDBus_Message *reply;
EDBUS_MESSAGE_CHECK_RETVAL(msg, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(error_name, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(error_msg, NULL);
reply = edbus_message_new(EINA_FALSE);
reply->dbus_msg = dbus_message_new_error(msg->dbus_msg,
error_name, error_msg);
/*
* Technically user should not append more arguments in an error message but
* we can't leave its iter as NULL.
*/
dbus_message_iter_init_append(reply->dbus_msg,
&reply->iterator->dbus_iterator);
return reply;
}
EAPI EDBus_Message *
edbus_message_method_return_new(const EDBus_Message *msg)
{
EDBus_Message *reply;
EDBUS_MESSAGE_CHECK_RETVAL(msg, NULL);
reply = edbus_message_new(EINA_TRUE);
reply->dbus_msg = dbus_message_new_method_return(msg->dbus_msg);
dbus_message_iter_init_append(reply->dbus_msg,
&reply->iterator->dbus_iterator);
return reply;
}
EAPI EDBus_Message *
edbus_message_signal_new(const char *path, const char *interface, const char *name)
{
EDBus_Message *msg;
EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
EINA_SAFETY_ON_FALSE_RETURN_VAL(name, NULL);
msg = edbus_message_new(EINA_TRUE);
EINA_SAFETY_ON_NULL_RETURN_VAL(msg, NULL);
msg->dbus_msg = dbus_message_new_signal(path, interface, name);
dbus_message_iter_init_append(msg->dbus_msg,
&msg->iterator->dbus_iterator);
return msg;
}

View File

@ -0,0 +1,276 @@
#ifndef EDBUS_MESSAGE_H
#define EDBUS_MESSAGE_H 1
/**
* @defgroup EDBus_Message Message
*
* @{
*/
/**
* @brief Constructs a new message to invoke a method on a remote object.
*
* @param dest bus name or unique id of the remote applications
* @param path object path
* @param iface interface name
* @param method name of method that will be called
*
* @return a new EDBus_Message, free with edbus_message_unref()
*/
EAPI EDBus_Message *edbus_message_method_call_new(const char *dest, const char *path, const char *iface, const char *method) EINA_ARG_NONNULL(1, 2, 3, 4) EINA_WARN_UNUSED_RESULT EINA_MALLOC;
/**
* @brief Increase message reference.
*/
EAPI EDBus_Message *edbus_message_ref(EDBus_Message *msg) EINA_ARG_NONNULL(1);
/**
* @brief Decrease message reference.
* If reference == 0 message will be freed and all your children's.
*/
EAPI void edbus_message_unref(EDBus_Message *msg) EINA_ARG_NONNULL(1);
EAPI const char *edbus_message_path_get(const EDBus_Message *msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_message_interface_get(const EDBus_Message *msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_message_member_get(const EDBus_Message *msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_message_destination_get(const EDBus_Message *msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_message_sender_get(const EDBus_Message *msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_message_signature_get(const EDBus_Message *msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
/**
* @brief Creates a new message that is an error reply to another message.
*
* @param reply the message we're replying to
* @param error_name the error name
* @param error_msg the error message string
*
* @return new EDBus_Message, free with edbus_message_unref()
*/
EAPI EDBus_Message *edbus_message_error_new(const EDBus_Message *reply, const char *error_name, const char *error_msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
/**
* @brief Constructs a message that is a reply to a method call.
*
* @param msg the message we're replying to
*
* @return new EDBus_Message, free with edbus_message_unref()
*/
EAPI EDBus_Message *edbus_message_method_return_new(const EDBus_Message *msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
/**
* @brief Constructs a new message representing a signal emission.
*
* @param path of the object that was emiting the signal
* @param interface
* @param name
*
* @return new EDBus_Message, free with edbus_message_unref()
*/
EAPI EDBus_Message *edbus_message_signal_new(const char *path, const char *interface, const char *name) EINA_ARG_NONNULL(1, 2, 3) EINA_WARN_UNUSED_RESULT;
/**
* @brief If EDBus_Message is a message error return EINA_TRUE and fills
* name and text if their pointers is not null.
*/
EAPI Eina_Bool edbus_message_error_get(const EDBus_Message *msg, const char **name, const char **text) EINA_ARG_NONNULL(1);
/**
* @brief Get data from EDBus_Message, for each complete type must have
* a pointer to store his value, in case of complex type a
* EDBus_Message_Iter will be need.
*/
EAPI Eina_Bool edbus_message_arguments_get(const EDBus_Message *msg, const char *signature, ...) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
/**
* @brief Get data from EDBus_Message, for each complete type must have
* a pointer to store his value, in case of complex type a
* EDBus_Message_Iter will be need.
*/
EAPI Eina_Bool edbus_message_arguments_vget(const EDBus_Message *msg, const char *signature, va_list ap) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
/**
* @brief Set data to EDBus_Message.
*
* This function only support basic type from complex type use
* edbus_message_iter_* functions.
*/
EAPI Eina_Bool edbus_message_arguments_set(EDBus_Message *msg, const char *signature, ...) EINA_ARG_NONNULL(1, 2);
/**
* @brief Set data to EDBus_Message.
*
* This function only support basic type from complex type use
* edbus_message_iter_* functions.
*/
EAPI Eina_Bool edbus_message_arguments_vset(EDBus_Message *msg, const char *signature, va_list ap) EINA_ARG_NONNULL(1, 2);
/**
* @defgroup EDBus_Message_Iter Iterator
* @{
*/
/**
* @brief Create and appends a typed iterator to another iterator.
*
* After append data to returned iterator it must be closed calling
* edbus_message_iter_container_close().
*
* Container types are for example struct, variant, and array.
* For variants, the contained_signature should be the type of the single
* value inside the variant. For structs and dict entries, contained_signature
* should be NULL; it will be set to whatever types you write into the struct.
* For arrays, contained_signature should be the type of the array elements.
*
* @param iter parent of the new iterator
* @param type of iterator (e.g struct, dict, variant or array)
* @param contained_signature signature of what iterator will store
*
* @return the new iterator
*/
EAPI EDBus_Message_Iter *edbus_message_iter_container_new(EDBus_Message_Iter *iter, int type, const char* contained_signature) EINA_ARG_NONNULL(1, 3) EINA_WARN_UNUSED_RESULT;
/**
* @brief Append a basic type to EDBus_Iterator.
*/
EAPI Eina_Bool edbus_message_iter_append_basic(EDBus_Message_Iter *iter, int type, ...) EINA_ARG_NONNULL(1, 3);
/**
* @brief Set data to EDBus_Message_Iter. For each complete in signature
* you need pass the value, in case of complex type a pointer to be allocated a
* EDBus_Message_Iter that you need fill and close.
*
* It's not possible open two iterators at same Iterator. Example:
* "aiai", to set this you need create and put the first array with
* edbus_message_iter_container_new() fill array with data and close then
* you could open the second array with edbus_message_iter_container_new().
*
* @param iter iterator
* @param signature of data
* @param ... values
*
* @note This function don't support variant, use instead
* edbus_message_iter_container_new() to create the variant fill
* data and close it..
*/
EAPI Eina_Bool edbus_message_iter_arguments_set(EDBus_Message_Iter *iter, const char *signature, ...) EINA_ARG_NONNULL(1, 2);
/**
* @brief Set data to EDBus_Message_Iter. For each complete in signature
* you need pass the value, in case of complex type a pointer to be allocated a
* EDBus_Message_Iter that you need fill and close.
*
* It's not possible open two iterators at same Iterator. Example:
* "aiai", to set this you need create and put the first array with
* edbus_message_iter_container_new() fill array with data and close then
* you could open the second array with edbus_message_iter_container_new().
*
* @param iter iterator
* @param signature of data
* @param ap va_list with the values
*
* @note This function don't support variant, use instead
* edbus_message_iter_container_new() to create the variant fill
* data and close it.
*/
EAPI Eina_Bool edbus_message_iter_arguments_vset(EDBus_Message_Iter *iter, const char *signature, va_list ap) EINA_ARG_NONNULL(1, 2, 3);
/**
* @brief Closes a container-typed value appended to the message.
*
* @param iter parent of the sub-iterator
* @param sub the iterator that will be closed
*
* @return EINA_FALSE if iterator was already close or if not enough memory
*/
EAPI Eina_Bool edbus_message_iter_container_close(EDBus_Message_Iter *iter, EDBus_Message_Iter *sub) EINA_ARG_NONNULL(1, 2);
/**
* @brief Get the main EDBus_Message_Iter from the EDBus_Message.
*/
EAPI EDBus_Message_Iter *edbus_message_iter_get(EDBus_Message *msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
/**
* @brief Get a basic type from EDBus_Iterator.
*/
EAPI void edbus_message_iter_get_basic(EDBus_Message_Iter *iter, void *value) EINA_ARG_NONNULL(1, 2);
/**
* @brief Returns the current signature of a message iterator.
*
* @note The returned string must be freed.
*/
EAPI char *edbus_message_iter_signature_get(EDBus_Message_Iter *iter) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
/**
* @brief Moves the iterator to the next field, if any.
* @param iter iterator
*
* @return if iterator was reach to end return EINA_FALSE
*/
EAPI Eina_Bool edbus_message_iter_next(EDBus_Message_Iter *iter) EINA_ARG_NONNULL(1);
/**
* @brief Get a complete type from EDBus_Message_Iter if is not at the end
* of iterator and move to next field.
* Useful to iterate over arrays.
*
* @param iter iterator
* @param type of the next completed type in Iterator
* @param ... pointer of where data will be stored
*
* @param if iterator was reach to end or if type different of the type that
* iterator points return EINA_FALSE
*
*/
EAPI Eina_Bool edbus_message_iter_get_and_next(EDBus_Message_Iter *iter, char type, ...) EINA_ARG_NONNULL(1, 2, 3);
/**
* @brief Reads a block of fixed-length values from the message iterator.
*
* Fixed-length values are those basic types that are not string-like,
* such as integers, bool, double. The returned block will be from the
* current position in the array until the end of the array.
*
* There is one exception here: although EDBUS_TYPE_UNIX_FD is considered a
* 'fixed' type arrays of this type may not be read with this function.
*
* The value argument should be the address of a location to store the returned
* array. So for int32 it should be a "const dbus_int32_t**" The returned value
* is by reference and should not be freed.
*
* Because the array is not copied, this function runs in constant time and is
* fast; it's much preferred over walking the entire array with an iterator.
*/
EAPI Eina_Bool edbus_message_iter_fixed_array_get(EDBus_Message_Iter *iter, int signature, void *value, int *n_elements) EINA_ARG_NONNULL(1, 3, 4);
/**
* @brief Get data from EDBus_Message_Iter, for each complete type must have
* a pointer to store his value, in case of complex type a
* EDBus_Message_Iter will be need.
*
* @param iter iterator
* @param signature of the complete data types on interator
* @param ... pointers of where data will be stored
*
* @return EINA_FALSE if signature different from signature in iterator
*/
EAPI Eina_Bool edbus_message_iter_arguments_get(EDBus_Message_Iter *iter, const char *signature, ...) EINA_ARG_NONNULL(1, 2);
/**
* @brief Get data from EDBus_Message_Iter, for each complete type must have
* a pointer to store his value, in case of complex type a
* EDBus_Message_Iter will be need.
*
* @param iter iterator
* @param signature of the complete data types on interator
* @param ap va_list of the pointers of where data will be stored
*
* @return EINA_FALSE if signature different from signature in iterator
*/
EAPI Eina_Bool edbus_message_iter_arguments_vget(EDBus_Message_Iter *iter, const char *signature, va_list ap) EINA_ARG_NONNULL(1, 2);
/**
* @brief Manually delete the iterator.
*
* Iterators are usually bound to the life of @ref EDBus_Message
* they were created from, being deleted automatically once the
* message is deleted.
*
* However when dealing with huge arrays or dicts it may become a
* major memory impact to leave the unused iterators alive. By
* calling this function one states the iterator is not used anymore
* and can be deleted.
*
* @param iter the iterator to be deleted.
*/
EAPI void edbus_message_iter_del(EDBus_Message_Iter *iter) EINA_ARG_NONNULL(1);
/**
* @}
*/
/**
* @}
*/
#endif

View File

@ -0,0 +1,467 @@
#include "edbus_private.h"
#include "edbus_private_types.h"
#include <dbus/dbus.h>
/* TODO: mempool of EDBus_Object, Edbus_Object_Context_Event_Cb and
* EDBus_Object_Context_Event
*/
#define EDBUS_OBJECT_CHECK(obj) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN(obj); \
if (!EINA_MAGIC_CHECK(obj, EDBUS_OBJECT_MAGIC)) \
{ \
EINA_MAGIC_FAIL(obj, EDBUS_OBJECT_MAGIC); \
return; \
} \
EINA_SAFETY_ON_TRUE_RETURN(obj->refcount <= 0); \
} \
while (0)
#define EDBUS_OBJECT_CHECK_RETVAL(obj, retval) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, retval); \
if (!EINA_MAGIC_CHECK(obj, EDBUS_OBJECT_MAGIC)) \
{ \
EINA_MAGIC_FAIL(obj, EDBUS_OBJECT_MAGIC); \
return retval; \
} \
EINA_SAFETY_ON_TRUE_RETURN_VAL(obj->refcount <= 0, retval); \
} \
while (0)
#define EDBUS_OBJECT_CHECK_GOTO(obj, label) \
do \
{ \
EINA_SAFETY_ON_NULL_GOTO(obj, label); \
if (!EINA_MAGIC_CHECK(obj, EDBUS_OBJECT_MAGIC)) \
{ \
EINA_MAGIC_FAIL(obj, EDBUS_OBJECT_MAGIC); \
goto label; \
} \
EINA_SAFETY_ON_TRUE_GOTO(obj->refcount <= 0, label); \
} \
while (0)
Eina_Bool
edbus_object_init(void)
{
return EINA_TRUE;
}
void
edbus_object_shutdown(void)
{
}
static void _edbus_object_event_callback_call(EDBus_Object *obj, EDBus_Object_Event_Type type, const void *event_info);
static void _edbus_object_context_event_cb_del(EDBus_Object_Context_Event *ce, EDBus_Object_Context_Event_Cb *ctx);
static void _on_connection_free(void *data, const void *dead_pointer);
static void
_edbus_object_call_del(EDBus_Object *obj)
{
EDBus_Object_Context_Event *ce;
_edbus_object_event_callback_call(obj, EDBUS_OBJECT_EVENT_DEL, NULL);
/* clear all del callbacks so we don't call them twice at
* _edbus_object_clear()
*/
ce = obj->event_handlers + EDBUS_OBJECT_EVENT_DEL;
while (ce->list)
{
EDBus_Object_Context_Event_Cb *ctx;
ctx = EINA_INLIST_CONTAINER_GET(ce->list,
EDBus_Object_Context_Event_Cb);
_edbus_object_context_event_cb_del(ce, ctx);
}
}
static void
_edbus_object_clear(EDBus_Object *obj)
{
EDBus_Signal_Handler *h;
EDBus_Pending *p;
Eina_List *iter, *iter_next;
Eina_Inlist *in_l;
DBG("obj=%p, refcount=%d, name=%s, path=%s",
obj, obj->refcount, obj->name, obj->path);
obj->refcount = 1;
_edbus_object_call_del(obj);
edbus_connection_name_object_del(obj->conn, obj);
/* NOTE: obj->proxies is deleted from obj->cbs_free. */
EINA_LIST_FOREACH_SAFE(obj->signal_handlers, iter, iter_next, h)
{
DBG("obj=%p delete owned signal handler %p %s",
obj, h, edbus_signal_handler_match_get(h));
edbus_signal_handler_del(h);
}
EINA_INLIST_FOREACH_SAFE(obj->pendings, in_l, p)
{
DBG("obj=%p delete owned pending call=%p dest=%s path=%s %s.%s()",
obj, p,
edbus_pending_destination_get(p),
edbus_pending_path_get(p),
edbus_pending_interface_get(p),
edbus_pending_method_get(p));
edbus_pending_cancel(p);
}
edbus_cbs_free_dispatch(&(obj->cbs_free), obj);
obj->refcount = 0;
}
static void
_edbus_object_free(EDBus_Object *obj)
{
unsigned int i;
if (obj->proxies)
{
Eina_Iterator *iterator = eina_hash_iterator_data_new(obj->proxies);
EDBus_Proxy *proxy;
EINA_ITERATOR_FOREACH (iterator, proxy)
ERR("obj=%p alive proxy=%p %s", obj, proxy,
edbus_proxy_interface_get(proxy));
eina_iterator_free(iterator);
eina_hash_free(obj->proxies);
}
if (obj->signal_handlers)
{
EDBus_Signal_Handler *h;
CRITICAL("Object %p released with live signal handlers!", obj);
EINA_LIST_FREE (obj->signal_handlers, h)
ERR("obj=%p alive handler=%p %s", obj, h,
edbus_signal_handler_match_get(h));
}
if (obj->pendings)
CRITICAL("Object %p released with live pending calls!", obj);
for (i = 0; i < EDBUS_OBJECT_EVENT_LAST; i++)
{
EDBus_Object_Context_Event *ce = obj->event_handlers + i;
while (ce->list)
{
EDBus_Object_Context_Event_Cb *ctx;
ctx = EINA_INLIST_CONTAINER_GET(ce->list,
EDBus_Object_Context_Event_Cb);
_edbus_object_context_event_cb_del(ce, ctx);
}
eina_list_free(ce->to_delete);
}
eina_stringshare_del(obj->name);
eina_stringshare_del(obj->path);
EINA_MAGIC_SET(obj, EINA_MAGIC_NONE);
free(obj);
}
static void
_on_connection_free(void *data, const void *dead_pointer)
{
EDBus_Object *obj = data;
EDBUS_OBJECT_CHECK(obj);
_edbus_object_clear(obj);
_edbus_object_free(obj);
}
EAPI EDBus_Object *
edbus_object_get(EDBus_Connection *conn, const char *bus, const char *path)
{
EDBus_Object *obj;
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(bus, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
obj = edbus_connection_name_object_get(conn, bus, path);
if (obj) return obj;
obj = calloc(1, sizeof(EDBus_Object));
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
obj->conn = conn;
obj->refcount = 1;
obj->path = eina_stringshare_add(path);
obj->name = eina_stringshare_add(bus);
obj->proxies = eina_hash_string_small_new(NULL);
EINA_SAFETY_ON_NULL_GOTO(obj->proxies, cleanup);
EINA_MAGIC_SET(obj, EDBUS_OBJECT_MAGIC);
edbus_connection_name_object_set(conn, obj);
edbus_connection_cb_free_add(obj->conn, _on_connection_free, obj);
return obj;
cleanup:
eina_stringshare_del(obj->path);
eina_stringshare_del(obj->name);
free(obj);
return NULL;
}
static void _on_signal_handler_free(void *data, const void *dead_pointer);
static void
_edbus_object_unref(EDBus_Object *obj)
{
obj->refcount--;
if (obj->refcount > 0) return;
edbus_connection_cb_free_del(obj->conn, _on_connection_free, obj);
_edbus_object_clear(obj);
_edbus_object_free(obj);
}
EAPI EDBus_Object *
edbus_object_ref(EDBus_Object *obj)
{
EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
DBG("obj=%p, pre-refcount=%d, name=%s, path=%s",
obj, obj->refcount, obj->name, obj->path);
obj->refcount++;
return obj;
}
EAPI void
edbus_object_unref(EDBus_Object *obj)
{
EDBUS_OBJECT_CHECK(obj);
DBG("obj=%p, pre-refcount=%d, name=%s, path=%s",
obj, obj->refcount, obj->name, obj->path);
_edbus_object_unref(obj);
}
EAPI void
edbus_object_cb_free_add(EDBus_Object *obj, EDBus_Free_Cb cb, const void *data)
{
EDBUS_OBJECT_CHECK(obj);
EINA_SAFETY_ON_NULL_RETURN(cb);
obj->cbs_free = edbus_cbs_free_add(obj->cbs_free, cb, data);
}
EAPI void
edbus_object_cb_free_del(EDBus_Object *obj, EDBus_Free_Cb cb, const void *data)
{
EDBUS_OBJECT_CHECK(obj);
EINA_SAFETY_ON_NULL_RETURN(cb);
obj->cbs_free = edbus_cbs_free_del(obj->cbs_free, cb, data);
}
EAPI void
edbus_object_event_callback_add(EDBus_Object *obj, EDBus_Object_Event_Type type, EDBus_Object_Event_Cb cb, const void *cb_data)
{
EDBus_Object_Context_Event *ce;
EDBus_Object_Context_Event_Cb *ctx;
EDBUS_OBJECT_CHECK(obj);
EINA_SAFETY_ON_NULL_RETURN(cb);
EINA_SAFETY_ON_TRUE_RETURN(type >= EDBUS_OBJECT_EVENT_LAST);
ce = obj->event_handlers + type;
ctx = calloc(1, sizeof(EDBus_Object_Context_Event_Cb));
EINA_SAFETY_ON_NULL_RETURN(ctx);
ctx->cb = cb;
ctx->cb_data = cb_data;
ce->list = eina_inlist_append(ce->list, EINA_INLIST_GET(ctx));
}
static void
_edbus_object_context_event_cb_del(EDBus_Object_Context_Event *ce, EDBus_Object_Context_Event_Cb *ctx)
{
ce->list = eina_inlist_remove(ce->list, EINA_INLIST_GET(ctx));
free(ctx);
}
EAPI void
edbus_object_event_callback_del(EDBus_Object *obj, EDBus_Object_Event_Type type, EDBus_Object_Event_Cb cb, const void *cb_data)
{
EDBus_Object_Context_Event *ce;
EDBus_Object_Context_Event_Cb *iter, *found = NULL;
EDBUS_OBJECT_CHECK(obj);
EINA_SAFETY_ON_NULL_RETURN(cb);
EINA_SAFETY_ON_TRUE_RETURN(type >= EDBUS_OBJECT_EVENT_LAST);
ce = obj->event_handlers + type;
EINA_INLIST_FOREACH (ce->list, iter)
{
if (cb != iter->cb) continue;
if ((cb_data) && (cb_data != iter->cb_data)) continue;
found = iter;
break;
}
EINA_SAFETY_ON_NULL_RETURN(found);
EINA_SAFETY_ON_TRUE_RETURN(found->deleted);
if (ce->walking)
{
found->deleted = EINA_TRUE;
ce->to_delete = eina_list_append(ce->to_delete, found);
return;
}
_edbus_object_context_event_cb_del(ce, found);
}
static void
_edbus_object_event_callback_call(EDBus_Object *obj, EDBus_Object_Event_Type type, const void *event_info)
{
EDBus_Object_Context_Event *ce;
EDBus_Object_Context_Event_Cb *iter;
ce = obj->event_handlers + type;
ce->walking++;
EINA_INLIST_FOREACH (ce->list, iter)
{
if (iter->deleted) continue;
iter->cb((void *)iter->cb_data, obj, (void *)event_info);
}
ce->walking--;
if (ce->walking > 0) return;
EINA_LIST_FREE (ce->to_delete, iter)
_edbus_object_context_event_cb_del(ce, iter);
}
EAPI EDBus_Connection *
edbus_object_connection_get(const EDBus_Object *obj)
{
EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
return obj->conn;
}
EAPI const char *
edbus_object_bus_name_get(const EDBus_Object *obj)
{
EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
return obj->name;
}
EAPI const char *
edbus_object_bus_path_get(const EDBus_Object *obj)
{
EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
return obj->path;
}
static void
_on_pending_free(void *data, const void *dead_pointer)
{
EDBus_Object *obj = data;
EDBus_Pending *pending = (EDBus_Pending*) dead_pointer;
EDBUS_OBJECT_CHECK(obj);
obj->pendings = eina_inlist_remove(obj->pendings, EINA_INLIST_GET(pending));
}
EAPI EDBus_Pending *
edbus_object_send(EDBus_Object *obj, EDBus_Message *msg, EDBus_Message_Cb cb, const void *cb_data, double timeout)
{
EDBus_Pending *pending;
EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(msg, NULL);
pending = _edbus_connection_send(obj->conn, msg, cb, cb_data, timeout);
if (!cb) return NULL;
EINA_SAFETY_ON_NULL_RETURN_VAL(pending, NULL);
edbus_pending_cb_free_add(pending, _on_pending_free, obj);
obj->pendings = eina_inlist_append(obj->pendings, EINA_INLIST_GET(pending));
return pending;
}
static void
_on_signal_handler_free(void *data, const void *dead_pointer)
{
EDBus_Object *obj = data;
EDBUS_OBJECT_CHECK(obj);
obj->signal_handlers = eina_list_remove(obj->signal_handlers, dead_pointer);
}
EAPI EDBus_Signal_Handler *
edbus_object_signal_handler_add(EDBus_Object *obj, const char *interface, const char *member, EDBus_Signal_Cb cb, const void *cb_data)
{
EDBus_Signal_Handler *handler;
EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
handler = edbus_signal_handler_add(obj->conn, obj->name, obj->path,
interface, member, cb, cb_data);
EINA_SAFETY_ON_NULL_RETURN_VAL(handler, NULL);
edbus_signal_handler_cb_free_add(handler, _on_signal_handler_free, obj);
obj->signal_handlers = eina_list_append(obj->signal_handlers, handler);
return handler;
}
Eina_Bool
edbus_object_proxy_add(EDBus_Object *obj, EDBus_Proxy *proxy)
{
return eina_hash_add(obj->proxies, edbus_proxy_interface_get(proxy), proxy);
}
EDBus_Proxy *
edbus_object_proxy_get(EDBus_Object *obj, const char *interface)
{
return eina_hash_find(obj->proxies, interface);
}
Eina_Bool
edbus_object_proxy_del(EDBus_Object *obj, EDBus_Proxy *proxy, const char *interface)
{
return eina_hash_del(obj->proxies, interface, proxy);
}
static EDBus_Proxy *
get_peer_proxy(EDBus_Object *obj)
{
return edbus_proxy_get(obj, "org.freedesktop.DBus.Peer");
}
EAPI EDBus_Pending *
edbus_object_peer_ping(EDBus_Object *obj, EDBus_Message_Cb cb, const void *data)
{
EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
return edbus_proxy_call(get_peer_proxy(obj), "Ping", cb,
data, -1, "");
}
EAPI EDBus_Pending *
edbus_object_peer_machine_id_get(EDBus_Object *obj, EDBus_Message_Cb cb, const void *data)
{
EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
return edbus_proxy_call(get_peer_proxy(obj), "GetMachineId", cb,
data, -1, "");
}
EAPI EDBus_Pending *
edbus_object_introspect(EDBus_Object *obj, EDBus_Message_Cb cb, const void *data)
{
EDBus_Proxy *introspectable;
EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
introspectable = edbus_proxy_get(obj, "org.freedesktop.DBus.Introspectable");
return edbus_proxy_call(introspectable, "Introspect", cb, data, -1, "");
}

View File

@ -0,0 +1,117 @@
#ifndef EDBUS_OBJECT_H
#define EDBUS_OBJECT_H 1
/**
* @defgroup EDBus_Object_Mapper Object Mapper
*
* @{
*/
/**
* @brief Get a object of the following bus and path.
*
* @param conn connection where object belongs
* @param bus name of bus or unique-id of who listen for calls of this object
* @param path object path of this object
*/
EAPI EDBus_Object *edbus_object_get(EDBus_Connection *conn, const char *bus, const char *path) EINA_ARG_NONNULL(1, 2, 3) EINA_WARN_UNUSED_RESULT;
/**
* @brief Increase object reference.
*/
EAPI EDBus_Object *edbus_object_ref(EDBus_Object *obj) EINA_ARG_NONNULL(1);
/**
* @brief Decrease object reference.
* If reference == 0 object will be freed and all your children's.
*/
EAPI void edbus_object_unref(EDBus_Object *obj) EINA_ARG_NONNULL(1);
/**
* @brief Add a callback function to be called when object will be freed.
*
* @param obj object that you want to know when it will be free
* @param cb callback that will be execute
* @param data passed to callback
*/
EAPI void edbus_object_cb_free_add(EDBus_Object *obj, EDBus_Free_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
/**
* @brief Remove callback registered in edbus_object_cb_free_add().
*/
EAPI void edbus_object_cb_free_del(EDBus_Object *obj, EDBus_Free_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
typedef enum
{
EDBUS_OBJECT_EVENT_IFACE_ADDED = 0,
EDBUS_OBJECT_EVENT_IFACE_REMOVED,
EDBUS_OBJECT_EVENT_PROPERTY_CHANGED,
EDBUS_OBJECT_EVENT_PROPERTY_REMOVED,
EDBUS_OBJECT_EVENT_DEL,
EDBUS_OBJECT_EVENT_LAST /**< sentinel, not a real event type */
} EDBus_Object_Event_Type;
typedef struct _EDBus_Object_Event_Interface_Added
{
const char *interface;
EDBus_Proxy *proxy;
} EDBus_Object_Event_Interface_Added;
typedef struct _EDBus_Object_Event_Interface_Removed
{
const char *interface;
} EDBus_Object_Event_Interface_Removed;
typedef struct _EDBus_Object_Event_Property_Changed
{
const char *interface;
EDBus_Proxy *proxy;
const char *name;
const Eina_Value *value;
} EDBus_Object_Event_Property_Changed;
typedef struct _EDBus_Object_Event_Property_Removed
{
const char *interface;
EDBus_Proxy *proxy;
const char *name;
} EDBus_Object_Event_Property_Removed;
typedef void (*EDBus_Object_Event_Cb)(void *data, EDBus_Object *obj, void *event_info);
/**
* @brief Add a callback function to be called when occurs a event of the
* type passed.
*/
EAPI void edbus_object_event_callback_add(EDBus_Object *obj, EDBus_Object_Event_Type type, EDBus_Object_Event_Cb cb, const void *cb_data) EINA_ARG_NONNULL(1, 3);
/**
* @brief Remove callback registered in edbus_object_event_callback_add().
*/
EAPI void edbus_object_event_callback_del(EDBus_Object *obj, EDBus_Object_Event_Type type, EDBus_Object_Event_Cb cb, const void *cb_data) EINA_ARG_NONNULL(1, 3);
EAPI EDBus_Connection *edbus_object_connection_get(const EDBus_Object *obj) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_object_bus_name_get(const EDBus_Object *obj) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_object_bus_path_get(const EDBus_Object *obj) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
/**
* @brief Send a message.
*
* @param obj the msg will be send in connection that obj belongs
* @param msg message that will be send
* @param cb if msg is a method call a callback should be passed
* to be execute when response arrive
* @param cb_data data passed to callback
* @param timeout timeout in milliseconds, -1 to default internal value or
* EDBUS_TIMEOUT_INFINITE for no timeout
*/
EAPI EDBus_Pending *edbus_object_send(EDBus_Object *obj, EDBus_Message *msg, EDBus_Message_Cb cb, const void *cb_data, double timeout) EINA_ARG_NONNULL(1, 2);
/**
* @brief Add a signal handler.
*
* @param obj where the signal is emitted
* @param interface of the signal
* @param member name of the signal
* @param cb callback that will be called when this signal is received
* @param cb_data data that will be passed to callback
*/
EAPI EDBus_Signal_Handler *edbus_object_signal_handler_add(EDBus_Object *obj, const char *interface, const char *member, EDBus_Signal_Cb cb, const void *cb_data) EINA_ARG_NONNULL(1, 4);
/**
* @}
*/
#endif

View File

@ -0,0 +1,260 @@
#include "edbus_private.h"
#include "edbus_private_types.h"
#include <dbus/dbus.h>
/* TODO: mempool of EDBus_Pending */
#define EDBUS_PENDING_CHECK(pending) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN(pending); \
if (!EINA_MAGIC_CHECK(pending, EDBUS_PENDING_MAGIC)) \
{ \
EINA_MAGIC_FAIL(pending, EDBUS_PENDING_MAGIC); \
return; \
} \
} \
while (0)
#define EDBUS_PENDING_CHECK_RETVAL(pending, retval) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN_VAL(pending, retval); \
if (!EINA_MAGIC_CHECK(pending, EDBUS_PENDING_MAGIC)) \
{ \
EINA_MAGIC_FAIL(pending, EDBUS_PENDING_MAGIC); \
return retval; \
} \
} \
while (0)
static void edbus_pending_dispatch(EDBus_Pending *pending, EDBus_Message *msg);
Eina_Bool
edbus_pending_init(void)
{
return EINA_TRUE;
}
void
edbus_pending_shutdown(void)
{
}
static void
cb_pending(DBusPendingCall *dbus_pending, void *user_data)
{
EDBus_Message *msg;
EDBus_Pending *pending = user_data;
if (!dbus_pending_call_get_completed(dbus_pending))
{
INF("timeout to pending %p", pending);
dbus_pending_call_cancel(dbus_pending);
msg = edbus_message_error_new(pending->msg_sent,
"org.enlightenment.DBus.Timeout",
"This call was not completed.");
edbus_pending_dispatch(pending, msg);
return;
}
msg = edbus_message_new(EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN(msg);
msg->dbus_msg = dbus_pending_call_steal_reply(dbus_pending);
if (!msg->dbus_msg)
{
EINA_SAFETY_ON_NULL_GOTO(pending->cb, cleanup);
msg->dbus_msg = dbus_message_new_error(NULL,
"org.enlightenment.DBus.NoReply",
"There was no reply to this method call.");
EINA_SAFETY_ON_NULL_GOTO(msg->dbus_msg, cleanup);
}
dbus_message_iter_init(msg->dbus_msg, &msg->iterator->dbus_iterator);
edbus_pending_dispatch(pending, msg);
return;
cleanup:
edbus_message_unref(msg);
}
static void
_on_pending_free(void *data, const void *dead_pointer)
{
EDBus_Connection *conn = data;
edbus_connection_pending_del(conn, (void *)dead_pointer);
}
EAPI EDBus_Pending *
edbus_connection_send(EDBus_Connection *conn, EDBus_Message *msg, EDBus_Message_Cb cb, const void *cb_data, double timeout)
{
EDBus_Pending *pending;
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(msg, NULL);
pending = _edbus_connection_send(conn, msg, cb, cb_data, timeout);
if (!cb) return NULL;
EINA_SAFETY_ON_NULL_RETURN_VAL(pending, NULL);
edbus_connection_pending_add(conn, pending);
edbus_pending_cb_free_add(pending, _on_pending_free, conn);
return pending;
}
EDBus_Pending *
_edbus_connection_send(EDBus_Connection *conn, EDBus_Message *msg, EDBus_Message_Cb cb, const void *cb_data, double timeout)
{
EDBus_Pending *pending;
EDBus_Message *error_msg;
DBG("conn=%p, msg=%p, cb=%p, cb_data=%p, timeout=%f",
conn, msg, cb, cb_data, timeout);
if (!cb)
{
dbus_connection_send(conn->dbus_conn, msg->dbus_msg, NULL);
return NULL;
}
pending = calloc(1, sizeof(EDBus_Pending));
EINA_SAFETY_ON_NULL_RETURN_VAL(pending, NULL);
pending->cb = cb;
pending->cb_data = cb_data;
pending->conn = conn;
pending->dest = eina_stringshare_add(dbus_message_get_member(msg->dbus_msg));
pending->interface = eina_stringshare_add(dbus_message_get_interface(msg->dbus_msg));
pending->method = eina_stringshare_add(dbus_message_get_member(msg->dbus_msg));
pending->path = eina_stringshare_add(dbus_message_get_path(msg->dbus_msg));
pending->msg_sent = edbus_message_ref(msg);
EINA_MAGIC_SET(pending, EDBUS_PENDING_MAGIC);
if (!dbus_connection_send_with_reply(conn->dbus_conn,
msg->dbus_msg,
&pending->dbus_pending, timeout))
{
error_msg = edbus_message_error_new(msg, "org.enlightenment.DBus.NoConnection",
"EDBus_Connection was closed.");
edbus_pending_dispatch(pending, error_msg);
return NULL;
}
if (dbus_pending_call_set_notify(pending->dbus_pending, cb_pending, pending, NULL))
return pending;
dbus_pending_call_cancel(pending->dbus_pending);
error_msg = edbus_message_error_new(pending->msg_sent,
"org.enlightenment.DBus.Error",
"Error when try set callback to message.");
edbus_pending_dispatch(pending, error_msg);
return NULL;
}
EAPI void
edbus_pending_data_set(EDBus_Pending *pending, const char *key, const void *data)
{
EDBUS_PENDING_CHECK(pending);
EINA_SAFETY_ON_NULL_RETURN(key);
EINA_SAFETY_ON_NULL_RETURN(data);
edbus_data_set(&(pending->data), key, data);
}
EAPI void *
edbus_pending_data_get(const EDBus_Pending *pending, const char *key)
{
EDBUS_PENDING_CHECK_RETVAL(pending, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
return edbus_data_get(&(((EDBus_Pending *)pending)->data), key);
}
EAPI void *
edbus_pending_data_del(EDBus_Pending *pending, const char *key)
{
EDBUS_PENDING_CHECK_RETVAL(pending, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
return edbus_data_del(&(((EDBus_Pending *)pending)->data), key);
}
static void
edbus_pending_dispatch(EDBus_Pending *pending, EDBus_Message *msg)
{
DBG("pending=%p msg=%p", pending, msg);
if (pending->cb)
pending->cb((void *)pending->cb_data, msg, pending);
edbus_cbs_free_dispatch(&(pending->cbs_free), pending);
edbus_data_del_all(&(pending->data));
if (msg) edbus_message_unref(msg);
edbus_message_unref(pending->msg_sent);
dbus_pending_call_unref(pending->dbus_pending);
pending->cb = NULL;
pending->dbus_pending = NULL;
eina_stringshare_del(pending->dest);
eina_stringshare_del(pending->path);
eina_stringshare_del(pending->interface);
eina_stringshare_del(pending->method);
EINA_MAGIC_SET(pending, EINA_MAGIC_NONE);
free(pending);
}
EAPI void
edbus_pending_cancel(EDBus_Pending *pending)
{
EDBus_Message *error_message;
EDBUS_PENDING_CHECK(pending);
EINA_SAFETY_ON_NULL_RETURN(pending->dbus_pending);
DBG("pending=%p", pending);
dbus_pending_call_cancel(pending->dbus_pending);
error_message = edbus_message_error_new(pending->msg_sent,
"org.enlightenment.DBus.Canceled",
"Canceled by user.");
edbus_pending_dispatch(pending, error_message);
}
EAPI void
edbus_pending_cb_free_add(EDBus_Pending *pending, EDBus_Free_Cb cb, const void *data)
{
EDBUS_PENDING_CHECK(pending);
EINA_SAFETY_ON_NULL_RETURN(cb);
pending->cbs_free = edbus_cbs_free_add(pending->cbs_free, cb, data);
}
EAPI void
edbus_pending_cb_free_del(EDBus_Pending *pending, EDBus_Free_Cb cb, const void *data)
{
EDBUS_PENDING_CHECK(pending);
EINA_SAFETY_ON_NULL_RETURN(cb);
pending->cbs_free = edbus_cbs_free_del(pending->cbs_free, cb, data);
}
EAPI const char *
edbus_pending_destination_get(const EDBus_Pending *pending)
{
EDBUS_PENDING_CHECK_RETVAL(pending, NULL);
return pending->dest;
}
EAPI const char *
edbus_pending_path_get(const EDBus_Pending *pending)
{
EDBUS_PENDING_CHECK_RETVAL(pending, NULL);
return pending->path;
}
EAPI const char *
edbus_pending_interface_get(const EDBus_Pending *pending)
{
EDBUS_PENDING_CHECK_RETVAL(pending, NULL);
return pending->interface;
}
EAPI const char *
edbus_pending_method_get(const EDBus_Pending *pending)
{
EDBUS_PENDING_CHECK_RETVAL(pending, NULL);
return pending->method;
}

View File

@ -0,0 +1,30 @@
#ifndef EDBUS_PENDING_H
#define EDBUS_PENDING_H 1
/**
* @defgroup EDBus_Pending Pending
*
* @{
*/
EAPI void edbus_pending_data_set(EDBus_Pending *pending, const char *key, const void *data) EINA_ARG_NONNULL(1, 2, 3);
EAPI void *edbus_pending_data_get(const EDBus_Pending *pending, const char *key) EINA_ARG_NONNULL(1, 2);
EAPI void *edbus_pending_data_del(EDBus_Pending *pending, const char *key) EINA_ARG_NONNULL(1, 2);
EAPI void edbus_pending_cancel(EDBus_Pending *pending) EINA_ARG_NONNULL(1);
EAPI const char *edbus_pending_destination_get(const EDBus_Pending *pending) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_pending_path_get(const EDBus_Pending *pending) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_pending_interface_get(const EDBus_Pending *pending) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_pending_method_get(const EDBus_Pending *pending) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
/**
* @brief Add a callback function to be called when pending will be freed.
*/
EAPI void edbus_pending_cb_free_add(EDBus_Pending *pending, EDBus_Free_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
/**
* @brief Remove callback registered in edbus_pending_cb_free_add().
*/
EAPI void edbus_pending_cb_free_del(EDBus_Pending *pending, EDBus_Free_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
/**
* @}
*/
#endif

View File

@ -0,0 +1,81 @@
#ifndef EDBUS_PRIVATE_H
#define EDBUS_PRIVATE_H
#include <Eina.h>
#include "eina_safety_checks.h"
#include "EDBus.h"
#include "edbus_private_types.h"
extern int _edbus_log_dom;
#define DBG(...) EINA_LOG_DOM_DBG(_edbus_log_dom, __VA_ARGS__)
#define INF(...) EINA_LOG_DOM_INFO(_edbus_log_dom, __VA_ARGS__)
#define WRN(...) EINA_LOG_DOM_WARN(_edbus_log_dom, __VA_ARGS__)
#define ERR(...) EINA_LOG_DOM_ERR(_edbus_log_dom, __VA_ARGS__)
#define CRITICAL(...) EINA_LOG_DOM_CRIT(_edbus_log_dom, __VA_ARGS__)
#define EDBUS_CONNECTION_MAGIC (0xdb050001)
#define EDBUS_MESSAGE_MAGIC (0xdb050002)
#define EDBUS_SIGNAL_HANDLER_MAGIC (0xdb050003)
#define EDBUS_PENDING_MAGIC (0xdb050004)
#define EDBUS_OBJECT_MAGIC (0xdb050005)
#define EDBUS_PROXY_MAGIC (0xdb050006)
#define EDBUS_MESSAGE_ITERATOR_MAGIC (0xdb050007)
#define EDBUS_SERVICE_INTERFACE_MAGIC (0xdb050008)
void edbus_cbs_free_dispatch(Eina_Inlist **p_lst, const void *dead_pointer);
Eina_Inlist *edbus_cbs_free_add(Eina_Inlist *lst, EDBus_Free_Cb cb, const void *data);
Eina_Inlist *edbus_cbs_free_del(Eina_Inlist *lst, EDBus_Free_Cb cb, const void *data);
void edbus_data_set(Eina_Inlist **p_lst, const char *key, const void *data) EINA_ARG_NONNULL(1, 2, 3);
void *edbus_data_get(Eina_Inlist **p_lst, const char *key) EINA_ARG_NONNULL(1, 2);
void *edbus_data_del(Eina_Inlist **p_lst, const char *key) EINA_ARG_NONNULL(1, 2);
void edbus_data_del_all(Eina_Inlist **p_list) EINA_ARG_NONNULL(1);
Eina_Bool edbus_message_init(void);
void edbus_message_shutdown(void);
EDBus_Message *edbus_message_new(Eina_Bool writable);
Eina_Bool edbus_signal_handler_init(void);
void edbus_signal_handler_shutdown(void);
Eina_Bool edbus_pending_init(void);
void edbus_pending_shutdown(void);
Eina_Bool edbus_object_init(void);
void edbus_object_shutdown(void);
Eina_Bool edbus_proxy_init(void);
void edbus_proxy_shutdown(void);
Eina_Bool edbus_service_init(void);
void edbus_service_shutdown(void);
void edbus_connection_event_callback_call(EDBus_Connection *conn, EDBus_Connection_Event_Type type, const void *event_info) EINA_ARG_NONNULL(1);
Eina_Bool edbus_object_proxy_del(EDBus_Object *obj, EDBus_Proxy *proxy, const char *interface) EINA_ARG_NONNULL(1, 2);
void edbus_connection_signal_handler_add(EDBus_Connection *conn, EDBus_Signal_Handler *handler) EINA_ARG_NONNULL(1, 2);
void edbus_connection_pending_add(EDBus_Connection *conn, EDBus_Pending *pending) EINA_ARG_NONNULL(1, 2);
void edbus_connection_signal_handler_del(EDBus_Connection *conn, EDBus_Signal_Handler *handler) EINA_ARG_NONNULL(1, 2);
void edbus_connection_signal_handler_del(EDBus_Connection *conn, EDBus_Signal_Handler *handler) EINA_ARG_NONNULL(1, 2);
void edbus_connection_pending_del(EDBus_Connection *conn, EDBus_Pending *pending) EINA_ARG_NONNULL(1, 2);
EDBus_Object *edbus_connection_name_object_get(EDBus_Connection *conn, const char *name, const char *path);
void edbus_connection_name_object_set(EDBus_Connection *conn, EDBus_Object *obj);
Eina_Bool edbus_object_proxy_add(EDBus_Object *obj, EDBus_Proxy *proxy) EINA_ARG_NONNULL(1, 2);
EDBus_Proxy *edbus_object_proxy_get(EDBus_Object *obj, const char *interface);
void edbus_connection_name_object_del(EDBus_Connection *conn, const EDBus_Object *obj);
EDBus_Connection_Name *edbus_connection_name_get(EDBus_Connection *conn, const char *name);
void edbus_connection_name_owner_monitor(EDBus_Connection *conn, EDBus_Connection_Name *cn, Eina_Bool enable);
EDBus_Pending *_edbus_connection_send(EDBus_Connection *conn, EDBus_Message *msg, EDBus_Message_Cb cb, const void *cb_data, double timeout);
#ifdef HAVE_VA_LIST_AS_ARRAY
#define MAKE_PTR_FROM_VA_LIST(arg) ((va_list *)(arg))
#else
#define MAKE_PTR_FROM_VA_LIST(arg) (&(arg))
#endif
#endif

View File

@ -0,0 +1,168 @@
#ifndef EDBUS_PRIVATE_TYPES_H
#define EDBUS_PRIVATE_TYPES_H 1
#include "EDBus.h"
#include <Eina.h>
#include <dbus/dbus.h>
#include <Ecore.h>
typedef struct _EDBus_Connection_Name
{
const char *name;
const char *unique_id;
Eina_Hash *objects;
int refcount;
struct
{
Eina_Inlist *list; //EDBus_Connection_Context_NOC_Cb
int walking;
Eina_List *to_delete;
} event_handlers;
EDBus_Signal_Handler *name_owner_changed;
} EDBus_Connection_Name;
typedef struct _EDBus_Object_Context_Event_Cb
{
EINA_INLIST;
EDBus_Object_Event_Cb cb;
const void *cb_data;
Eina_Bool deleted : 1;
} EDBus_Object_Context_Event_Cb;
typedef struct _EDBus_Object_Context_Event
{
Eina_Inlist *list;
int walking;
Eina_List *to_delete;
} EDBus_Object_Context_Event;
typedef struct _EDBus_Connection_Context_Event
{
Eina_Inlist *list;
int walking;
Eina_List *to_delete;
} EDBus_Connection_Context_Event;
struct _EDBus_Connection
{
EINA_MAGIC;
EINA_INLIST;
int refcount;
EDBus_Connection_Type type;
DBusConnection *dbus_conn;
Eina_Hash *names; //EDBus_Connection_Name
Eina_Inlist *data;
Eina_Inlist *cbs_free;
Eina_Inlist *signal_handlers;
Eina_Inlist *pendings;
Eina_Inlist *fd_handlers;
Eina_Inlist *timeouts;
Ecore_Idler *idler;
Eina_Bool running_signal;
EDBus_Connection_Context_Event event_handlers[EDBUS_CONNECTION_EVENT_LAST];
};
struct _EDBus_Object
{
EINA_MAGIC;
EINA_INLIST;
int refcount;
EDBus_Connection *conn;
const char *name;
const char *path;
Eina_Hash *proxies;
Eina_Inlist *pendings;
Eina_List *signal_handlers;
Eina_Inlist *cbs_free;
EDBus_Object_Context_Event event_handlers[EDBUS_OBJECT_EVENT_LAST];
};
struct _EDBus_Signal_Handler
{
EINA_MAGIC;
EINA_INLIST;
int refcount;
const char *sender;
const char *path;
const char *interface;
const char *member;
Eina_Strbuf *match;
Eina_Inlist *args;
Eina_Inlist_Sorted_State *state_args;
EDBus_Connection *conn;
EDBus_Signal_Cb cb;
EDBus_Connection_Name *bus;
const void *cb_data;
Eina_Inlist *cbs_free;
Eina_Bool dangling;
};
struct _EDBus_Pending
{
EINA_MAGIC;
EINA_INLIST;
EDBus_Message_Cb cb;
const void *cb_data;
DBusPendingCall *dbus_pending;
EDBus_Connection *conn;
const char *dest;
const char *path;
const char *interface;
const char *method;
Eina_Inlist *data;
Eina_Inlist *cbs_free;
EDBus_Message *msg_sent;
};
struct _EDBus_Message_Iter
{
EINA_MAGIC;
EINA_INLIST;
DBusMessageIter dbus_iterator;
Eina_Inlist *iterators;
Eina_Bool writable;
};
struct _EDBus_Message
{
EINA_MAGIC;
int refcount;
DBusMessage *dbus_msg;
EDBus_Message_Iter *iterator;
};
typedef struct _EDBus_Service_Object
{
EDBus_Connection *conn;
const char *path;
Eina_Hash *interfaces;
Eina_Strbuf *introspection_data;
Eina_Bool introspection_dirty;
Eina_Inlist *data;
} EDBus_Service_Object;
struct _EDBus_Service_Interface
{
EINA_MAGIC;
const char *name;
Eina_Hash *methods;
const EDBus_Signal *signals;
Eina_Array *sign_of_signals;
EDBus_Service_Object *obj;
};
typedef struct _Signal_Argument
{
EINA_INLIST;
unsigned short index;
const char *value;
} Signal_Argument;
typedef struct _EDBus_Real_Method
{
const EDBus_Method *method;
const char *in;
} EDBus_Real_Method;
#endif

View File

@ -0,0 +1,542 @@
#include "edbus_private.h"
#include "edbus_private_types.h"
/* TODO: mempool of EDBus_Proxy, Edbus_Proxy_Context_Event_Cb and
* EDBus_Proxy_Context_Event
*/
typedef struct _EDBus_Proxy_Context_Event_Cb
{
EINA_INLIST;
EDBus_Proxy_Event_Cb cb;
const void *cb_data;
Eina_Bool deleted : 1;
} EDBus_Proxy_Context_Event_Cb;
typedef struct _EDBus_Proxy_Context_Event
{
Eina_Inlist *list;
int walking;
Eina_List *to_delete;
} EDBus_Proxy_Context_Event;
struct _EDBus_Proxy
{
EINA_MAGIC;
int refcount;
EDBus_Object *obj;
const char *interface;
Eina_Inlist *pendings;
Eina_List *handlers;
Eina_Inlist *cbs_free;
EDBus_Proxy_Context_Event event_handlers[EDBUS_PROXY_EVENT_LAST];
};
#define EDBUS_PROXY_CHECK(proxy) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN(proxy); \
if (!EINA_MAGIC_CHECK(proxy, EDBUS_PROXY_MAGIC)) \
{ \
EINA_MAGIC_FAIL(proxy, EDBUS_PROXY_MAGIC); \
return; \
} \
EINA_SAFETY_ON_TRUE_RETURN(proxy->refcount <= 0); \
} \
while (0)
#define EDBUS_PROXY_CHECK_RETVAL(proxy, retval) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN_VAL(proxy, retval); \
if (!EINA_MAGIC_CHECK(proxy, EDBUS_PROXY_MAGIC)) \
{ \
EINA_MAGIC_FAIL(proxy, EDBUS_PROXY_MAGIC); \
return retval; \
} \
EINA_SAFETY_ON_TRUE_RETURN_VAL(proxy->refcount <= 0, retval); \
} \
while (0)
#define EDBUS_PROXY_CHECK_GOTO(proxy, label) \
do \
{ \
EINA_SAFETY_ON_NULL_GOTO(proxy, label); \
if (!EINA_MAGIC_CHECK(proxy, EDBUS_PROXY_MAGIC)) \
{ \
EINA_MAGIC_FAIL(proxy, EDBUS_PROXY_MAGIC); \
goto label; \
} \
EINA_SAFETY_ON_TRUE_GOTO(proxy->refcount <= 0, label); \
} \
while (0)
Eina_Bool
edbus_proxy_init(void)
{
return EINA_TRUE;
}
void
edbus_proxy_shutdown(void)
{
}
static void _edbus_proxy_event_callback_call(EDBus_Proxy *proxy, EDBus_Proxy_Event_Type type, const void *event_info);
static void _edbus_proxy_context_event_cb_del(EDBus_Proxy_Context_Event *ce, EDBus_Proxy_Context_Event_Cb *ctx);
static void
_edbus_proxy_call_del(EDBus_Proxy *proxy)
{
EDBus_Proxy_Context_Event *ce;
_edbus_proxy_event_callback_call(proxy, EDBUS_PROXY_EVENT_DEL, NULL);
/* clear all del callbacks so we don't call them twice at
* _edbus_proxy_clear()
*/
ce = proxy->event_handlers + EDBUS_PROXY_EVENT_DEL;
while (ce->list)
{
EDBus_Proxy_Context_Event_Cb *ctx;
ctx = EINA_INLIST_CONTAINER_GET(ce->list,
EDBus_Proxy_Context_Event_Cb);
_edbus_proxy_context_event_cb_del(ce, ctx);
}
}
static void
_edbus_proxy_clear(EDBus_Proxy *proxy)
{
EDBus_Signal_Handler *h;
EDBus_Pending *p;
Eina_List *iter, *iter_next;
Eina_Inlist *in_l;
DBG("proxy=%p, refcount=%d, interface=%s, obj=%p",
proxy, proxy->refcount, proxy->interface, proxy->obj);
proxy->refcount = 1;
edbus_object_proxy_del(proxy->obj, proxy, proxy->interface);
_edbus_proxy_call_del(proxy);
EINA_LIST_FOREACH_SAFE(proxy->handlers, iter, iter_next, h)
{
DBG("proxy=%p delete owned signal handler %p %s",
proxy, h, edbus_signal_handler_match_get(h));
edbus_signal_handler_del(h);
}
EINA_INLIST_FOREACH_SAFE(proxy->pendings, in_l, p)
{
DBG("proxy=%p delete owned pending call=%p dest=%s path=%s %s.%s()",
proxy, p,
edbus_pending_destination_get(p),
edbus_pending_path_get(p),
edbus_pending_interface_get(p),
edbus_pending_method_get(p));
edbus_pending_cancel(p);
}
edbus_cbs_free_dispatch(&(proxy->cbs_free), proxy);
proxy->refcount = 0;
}
static void
_edbus_proxy_free(EDBus_Proxy *proxy)
{
unsigned int i;
if (proxy->handlers)
{
EDBus_Signal_Handler *h;
CRITICAL("Proxy %p released with live signal handlers!", proxy);
EINA_LIST_FREE (proxy->handlers, h)
ERR("proxy=%p alive handler=%p %s", proxy, h,
edbus_signal_handler_match_get(h));
}
if (proxy->pendings)
CRITICAL("Proxy %p released with live pending calls!", proxy);
for (i = 0; i < EDBUS_PROXY_EVENT_LAST; i++)
{
EDBus_Proxy_Context_Event *ce = proxy->event_handlers + i;
while (ce->list)
{
EDBus_Proxy_Context_Event_Cb *ctx;
ctx = EINA_INLIST_CONTAINER_GET(ce->list,
EDBus_Proxy_Context_Event_Cb);
_edbus_proxy_context_event_cb_del(ce, ctx);
}
eina_list_free(ce->to_delete);
}
eina_stringshare_del(proxy->interface);
EINA_MAGIC_SET(proxy, EINA_MAGIC_NONE);
free(proxy);
}
static void
_on_object_free(void *data, const void *dead_pointer)
{
EDBus_Proxy *proxy = data;
EDBUS_PROXY_CHECK(proxy);
DBG("proxy=%p, refcount=%d, interface=%s, obj=%p",
proxy, proxy->refcount, proxy->interface, proxy->obj);
_edbus_proxy_clear(proxy);
_edbus_proxy_free(proxy);
}
EAPI EDBus_Proxy *
edbus_proxy_get(EDBus_Object *obj, const char *interface)
{
EDBus_Proxy *proxy;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
proxy = edbus_object_proxy_get(obj, interface);
if (proxy) return proxy;
proxy = calloc(1, sizeof(EDBus_Proxy));
EINA_SAFETY_ON_NULL_RETURN_VAL(proxy, NULL);
proxy->refcount = 1;
proxy->obj = obj;
proxy->interface = eina_stringshare_add(interface);
EINA_MAGIC_SET(proxy, EDBUS_PROXY_MAGIC);
if (!edbus_object_proxy_add(obj, proxy))
goto cleanup;
edbus_object_cb_free_add(obj, _on_object_free, proxy);
return proxy;
cleanup:
eina_stringshare_del(proxy->interface);
free(proxy);
return NULL;
}
static void _on_signal_handler_free(void *data, const void *dead_pointer);
static void
_edbus_proxy_unref(EDBus_Proxy *proxy)
{
proxy->refcount--;
if (proxy->refcount > 0) return;
edbus_object_cb_free_del(proxy->obj, _on_object_free, proxy);
_edbus_proxy_clear(proxy);
_edbus_proxy_free(proxy);
}
EAPI EDBus_Proxy *
edbus_proxy_ref(EDBus_Proxy *proxy)
{
EDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
DBG("proxy=%p, pre-refcount=%d, interface=%s, obj=%p",
proxy, proxy->refcount, proxy->interface, proxy->obj);
proxy->refcount++;
return proxy;
}
EAPI void
edbus_proxy_unref(EDBus_Proxy *proxy)
{
EDBUS_PROXY_CHECK(proxy);
DBG("proxy=%p, pre-refcount=%d, interface=%s, obj=%p",
proxy, proxy->refcount, proxy->interface, proxy->obj);
_edbus_proxy_unref(proxy);
}
EAPI void
edbus_proxy_cb_free_add(EDBus_Proxy *proxy, EDBus_Free_Cb cb, const void *data)
{
EDBUS_PROXY_CHECK(proxy);
EINA_SAFETY_ON_NULL_RETURN(cb);
proxy->cbs_free = edbus_cbs_free_add(proxy->cbs_free, cb, data);
}
EAPI void
edbus_proxy_cb_free_del(EDBus_Proxy *proxy, EDBus_Free_Cb cb, const void *data)
{
EDBUS_PROXY_CHECK(proxy);
EINA_SAFETY_ON_NULL_RETURN(cb);
proxy->cbs_free = edbus_cbs_free_del(proxy->cbs_free, cb, data);
}
EAPI void
edbus_proxy_event_callback_add(EDBus_Proxy *proxy, EDBus_Proxy_Event_Type type, EDBus_Proxy_Event_Cb cb, const void *cb_data)
{
EDBus_Proxy_Context_Event *ce;
EDBus_Proxy_Context_Event_Cb *ctx;
EDBUS_PROXY_CHECK(proxy);
EINA_SAFETY_ON_NULL_RETURN(cb);
EINA_SAFETY_ON_TRUE_RETURN(type >= EDBUS_PROXY_EVENT_LAST);
ce = proxy->event_handlers + type;
ctx = calloc(1, sizeof(EDBus_Proxy_Context_Event_Cb));
EINA_SAFETY_ON_NULL_RETURN(ctx);
ctx->cb = cb;
ctx->cb_data = cb_data;
ce->list = eina_inlist_append(ce->list, EINA_INLIST_GET(ctx));
}
static void
_edbus_proxy_context_event_cb_del(EDBus_Proxy_Context_Event *ce, EDBus_Proxy_Context_Event_Cb *ctx)
{
ce->list = eina_inlist_remove(ce->list, EINA_INLIST_GET(ctx));
free(ctx);
}
EAPI void
edbus_proxy_event_callback_del(EDBus_Proxy *proxy, EDBus_Proxy_Event_Type type, EDBus_Proxy_Event_Cb cb, const void *cb_data)
{
EDBus_Proxy_Context_Event *ce;
EDBus_Proxy_Context_Event_Cb *iter, *found = NULL;
EDBUS_PROXY_CHECK(proxy);
EINA_SAFETY_ON_NULL_RETURN(cb);
EINA_SAFETY_ON_TRUE_RETURN(type >= EDBUS_PROXY_EVENT_LAST);
ce = proxy->event_handlers + type;
EINA_INLIST_FOREACH (ce->list, iter)
{
if (cb != iter->cb) continue;
if ((cb_data) && (cb_data != iter->cb_data)) continue;
found = iter;
break;
}
EINA_SAFETY_ON_NULL_RETURN(found);
EINA_SAFETY_ON_TRUE_RETURN(found->deleted);
if (ce->walking)
{
found->deleted = EINA_TRUE;
ce->to_delete = eina_list_append(ce->to_delete, found);
return;
}
_edbus_proxy_context_event_cb_del(ce, found);
}
static void
_edbus_proxy_event_callback_call(EDBus_Proxy *proxy, EDBus_Proxy_Event_Type type, const void *event_info)
{
EDBus_Proxy_Context_Event *ce;
EDBus_Proxy_Context_Event_Cb *iter;
ce = proxy->event_handlers + type;
ce->walking++;
EINA_INLIST_FOREACH (ce->list, iter)
{
if (iter->deleted) continue;
iter->cb((void *)iter->cb_data, proxy, (void *)event_info);
}
ce->walking--;
if (ce->walking > 0) return;
EINA_LIST_FREE (ce->to_delete, iter)
_edbus_proxy_context_event_cb_del(ce, iter);
}
EAPI EDBus_Object *
edbus_proxy_object_get(const EDBus_Proxy *proxy)
{
EDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
return proxy->obj;
}
EAPI const char *
edbus_proxy_interface_get(const EDBus_Proxy *proxy)
{
EDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
return proxy->interface;
}
static void
_on_pending_free(void *data, const void *dead_pointer)
{
EDBus_Proxy *proxy = data;
EDBus_Pending *pending = (EDBus_Pending *)dead_pointer;
EDBUS_PROXY_CHECK(proxy);
proxy->pendings = eina_inlist_remove(proxy->pendings,
EINA_INLIST_GET(pending));
}
static EDBus_Pending *
_edbus_proxy_send(EDBus_Proxy *proxy, EDBus_Message *msg, EDBus_Message_Cb cb, const void *cb_data, double timeout)
{
EDBus_Pending *pending;
pending = _edbus_connection_send(proxy->obj->conn, msg, cb, cb_data, timeout);
if (!cb) return NULL;
EINA_SAFETY_ON_NULL_RETURN_VAL(pending, NULL);
edbus_pending_cb_free_add(pending, _on_pending_free, proxy);
proxy->pendings = eina_inlist_append(proxy->pendings,
EINA_INLIST_GET(pending));
return pending;
}
EAPI EDBus_Pending *
edbus_proxy_send(EDBus_Proxy *proxy, EDBus_Message *msg, EDBus_Message_Cb cb, const void *cb_data, double timeout)
{
EDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(msg, NULL);
return _edbus_proxy_send(proxy, msg, cb, cb_data, timeout);
}
EAPI EDBus_Message *
edbus_proxy_method_call_new(EDBus_Proxy *proxy, const char *member)
{
EDBus_Message *msg;
EDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
msg = edbus_message_method_call_new(
edbus_object_bus_name_get(proxy->obj),
edbus_object_bus_path_get(proxy->obj),
proxy->interface, member);
return msg;
}
static EDBus_Pending *
_edbus_proxy_vcall(EDBus_Proxy *proxy, const char *member, EDBus_Message_Cb cb, const void *cb_data, double timeout, const char *signature, va_list ap)
{
EDBus_Pending *pending;
EDBus_Message *msg = edbus_proxy_method_call_new(proxy, member);
EINA_SAFETY_ON_NULL_RETURN_VAL(msg, NULL);
if (!edbus_message_arguments_vset(msg, signature, ap))
{
edbus_message_unref(msg);
ERR("Error setting arguments");
return NULL;
}
pending = _edbus_proxy_send(proxy, msg, cb, cb_data, timeout);
edbus_message_unref(msg);
return pending;
}
EAPI EDBus_Pending *
edbus_proxy_call(EDBus_Proxy *proxy, const char *member, EDBus_Message_Cb cb, const void *cb_data, double timeout, const char *signature, ...)
{
EDBus_Pending *pending;
va_list ap;
EDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(member, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(signature, NULL);
va_start(ap, signature);
pending = _edbus_proxy_vcall(proxy, member, cb, cb_data, timeout,
signature, ap);
va_end(ap);
return pending;
}
EAPI EDBus_Pending *
edbus_proxy_vcall(EDBus_Proxy *proxy, const char *member, EDBus_Message_Cb cb, const void *cb_data, double timeout, const char *signature, va_list ap)
{
EDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(member, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(signature, NULL);
return _edbus_proxy_vcall(proxy, member, cb, cb_data, timeout,
signature, ap);
}
static void
_on_signal_handler_free(void *data, const void *dead_pointer)
{
EDBus_Proxy *proxy = data;
EDBUS_PROXY_CHECK(proxy);
proxy->handlers = eina_list_remove(proxy->handlers, dead_pointer);
}
EAPI EDBus_Signal_Handler *
edbus_proxy_signal_handler_add(EDBus_Proxy *proxy, const char *member, EDBus_Signal_Cb cb, const void *cb_data)
{
EDBus_Signal_Handler *handler;
const char *name, *path;
EDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
name = edbus_object_bus_name_get(proxy->obj);
path = edbus_object_bus_path_get(proxy->obj);
handler = edbus_signal_handler_add(proxy->obj->conn, name, path,
proxy->interface, member, cb, cb_data);
EINA_SAFETY_ON_NULL_RETURN_VAL(handler, NULL);
edbus_signal_handler_cb_free_add(handler, _on_signal_handler_free, proxy);
proxy->handlers = eina_list_append(proxy->handlers, handler);
return handler;
}
static EDBus_Proxy *
get_properties_proxy(EDBus_Proxy *proxy)
{
return edbus_proxy_get(proxy->obj, EDBUS_FDO_INTERFACE_PROPERTIES);
}
EAPI EDBus_Pending *
edbus_proxy_property_get(EDBus_Proxy *proxy, const char *name, EDBus_Message_Cb cb, const void *data)
{
EDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
return edbus_proxy_call(get_properties_proxy(proxy), "Get", cb, data, -1,
"ss", proxy->interface, name);
}
EAPI EDBus_Pending *
edbus_proxy_property_set(EDBus_Proxy *proxy, const char *name, char type, const void *value, EDBus_Message_Cb cb, const void *data)
{
EDBus_Message *msg;
EDBus_Message_Iter *iter, *variant;
EDBus_Pending *pending;
char sig[2];
EDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
if (!dbus_type_is_basic(type))
{
ERR("Only basic types may be set using edbus_proxy_property_set()");
return NULL;
}
sig[0] = type;
sig[1] = 0;
msg = edbus_proxy_method_call_new(get_properties_proxy(proxy), "Set");
iter = edbus_message_iter_get(msg);
edbus_message_iter_append_basic(iter, 's', proxy->interface);
edbus_message_iter_append_basic(iter, 's', name);
variant = edbus_message_iter_container_new(iter, 'v', sig);
edbus_message_iter_append_basic(variant, type, value);
edbus_message_iter_container_close(iter, variant);
pending = edbus_proxy_send(get_properties_proxy(proxy), msg, cb, data, -1);
edbus_message_unref(msg);
return pending;
}
EAPI EDBus_Pending *
edbus_proxy_property_get_all(EDBus_Proxy *proxy, EDBus_Message_Cb cb, const void *data)
{
EDBUS_PROXY_CHECK_RETVAL(proxy, NULL);
return edbus_proxy_call(get_properties_proxy(proxy), "GetAll", cb, data, -1,
"s", proxy->interface);
}

View File

@ -0,0 +1,137 @@
#ifndef EDBUS_PROXY_H
#define EDBUS_PROXY_H 1
/**
* @defgroup EDBus_Proxy Proxy
*
* @{
*/
/**
* @brief Get a proxy of the following interface name in a EDBus_Object.
*/
EAPI EDBus_Proxy *edbus_proxy_get(EDBus_Object *obj, const char *interface) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
/**
* @brief Increase proxy reference.
*/
EAPI EDBus_Proxy *edbus_proxy_ref(EDBus_Proxy *proxy) EINA_ARG_NONNULL(1);
/**
* @brief Decrease proxy reference.
* If reference == 0 proxy will be freed and all your children's.
*/
EAPI void edbus_proxy_unref(EDBus_Proxy *proxy) EINA_ARG_NONNULL(1);
EAPI EDBus_Object *edbus_proxy_object_get(const EDBus_Proxy *proxy) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_proxy_interface_get(const EDBus_Proxy *proxy) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI void edbus_proxy_data_set(EDBus_Proxy *proxy, const char *key, const void *data) EINA_ARG_NONNULL(1, 2, 3);
EAPI void *edbus_proxy_data_get(const EDBus_Proxy *proxy, const char *key) EINA_ARG_NONNULL(1, 2);
EAPI void *edbus_proxy_data_del(EDBus_Proxy *proxy, const char *key) EINA_ARG_NONNULL(1, 2);
/**
* @brief Add a callback function to be called when occurs a event of the
* type passed.
*/
EAPI void edbus_proxy_cb_free_add(EDBus_Proxy *proxy, EDBus_Free_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
/**
* @brief Remove callback registered in edbus_proxy_cb_free_add().
*/
EAPI void edbus_proxy_cb_free_del(EDBus_Proxy *proxy, EDBus_Free_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
/**
* @brief Constructs a new message to invoke a method on a remote interface.
*/
EAPI EDBus_Message *edbus_proxy_method_call_new(EDBus_Proxy *proxy, const char *member);
/**
* @brief Send a message.
*
* @param proxy the msg will be send in connection that proxy belongs
* @param msg message that will be send
* @param cb if msg is a method call a callback should be passed
* @param cb_data data passed to callback
* @param timeout timeout in milliseconds, -1 to default internal value or
* EDBUS_TIMEOUT_INFINITE for no timeout
*/
EAPI EDBus_Pending *edbus_proxy_send(EDBus_Proxy *proxy, EDBus_Message *msg, EDBus_Message_Cb cb, const void *cb_data, double timeout) EINA_ARG_NONNULL(1, 2);
/**
* @brief Call a method in proxy.
* Send a method call to interface that proxy belong with data.
*
* @param proxy
* @param member method name
* @param cb if msg is a method call a callback should be passed
* to be execute when response arrive
* @param cb_data data passed to callback
* @param timeout timeout in milliseconds, -1 to default internal value or
* EDBUS_TIMEOUT_INFINITE for no timeout
* @param signature of data that will be send
* @param ... data value
*
* @note This function only support basic type to complex types use
* edbus_message_iter_* functions.
*/
EAPI EDBus_Pending *edbus_proxy_call(EDBus_Proxy *proxy, const char *member, EDBus_Message_Cb cb, const void *cb_data, double timeout, const char *signature, ...) EINA_ARG_NONNULL(1, 2, 6);
/**
* @brief Call a method in proxy.
* Send a method call to interface that proxy belong with data.
*
* @param proxy
* @param member method name
* @param cb callback that will be called when response arrive.
* @param cb_data data passed to callback
* @param timeout timeout in milliseconds, -1 to default internal value or
* EDBUS_TIMEOUT_INFINITE for no timeout
* @param signature of data that will be send
* @param ap va_list of data value
*
* @note This function only support basic type to complex types use
* edbus_message_iter_* functions.
*/
EAPI EDBus_Pending *edbus_proxy_vcall(EDBus_Proxy *proxy, const char *member, EDBus_Message_Cb cb, const void *cb_data, double timeout, const char *signature, va_list ap) EINA_ARG_NONNULL(1, 2, 6);
/**
* @brief Add a signal handler.
*
* @param proxy interface where the signal is emitted
* @param member name of the signal
* @param cb callback that will be called when this signal is received
* @param cb_data data that will be passed to callback
*/
EAPI EDBus_Signal_Handler *edbus_proxy_signal_handler_add(EDBus_Proxy *proxy, const char *member, EDBus_Signal_Cb cb, const void *cb_data) EINA_ARG_NONNULL(1, 3);
typedef enum
{
EDBUS_PROXY_EVENT_PROPERTY_CHANGED = 0,
EDBUS_PROXY_EVENT_PROPERTY_REMOVED,
EDBUS_PROXY_EVENT_DEL,
EDBUS_PROXY_EVENT_LAST /**< sentinel, not a real event type */
} EDBus_Proxy_Event_Type;
typedef struct _EDBus_Proxy_Event_Property_Changed
{
const char *name;
const Eina_Value *value;
} EDBus_Proxy_Event_Property_Changed;
typedef struct _EDBus_Proxy_Event_Property_Removed
{
const char *interface;
EDBus_Proxy *proxy;
const char *name;
} EDBus_Proxy_Event_Property_Removed;
typedef void (*EDBus_Proxy_Event_Cb)(void *data, EDBus_Proxy *proxy, void *event_info);
/**
* @brief Add a callback function to be called when occurs a event of the
* type passed.
*/
EAPI void edbus_proxy_event_callback_add(EDBus_Proxy *proxy, EDBus_Proxy_Event_Type type, EDBus_Proxy_Event_Cb cb, const void *cb_data) EINA_ARG_NONNULL(1, 3);
/**
* @brief Remove callback registered in edbus_connection_event_callback_add().
*/
EAPI void edbus_proxy_event_callback_del(EDBus_Proxy *proxy, EDBus_Proxy_Event_Type type, EDBus_Proxy_Event_Cb cb, const void *cb_data) EINA_ARG_NONNULL(1, 3);
/**
* @}
*/
#endif

View File

@ -0,0 +1,616 @@
#include "edbus_private_types.h"
#include "edbus_private.h"
#define DBUS_ANNOTATION(name, value) \
"<annotation" \
" name=\"org.freedesktop.DBus." name "\"" \
" value=\"" value "\"" \
"/>"
#define DBUS_ANNOTATION_DEPRECATED DBUS_ANNOTATION("Deprecated", "true")
#define DBUS_ANNOTATION_NOREPLY DBUS_ANNOTATION("Method.NoReply", "true")
#define EDBUS_SERVICE_INTERFACE_CHECK(obj) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN(obj); \
if (!EINA_MAGIC_CHECK(obj, EDBUS_SERVICE_INTERFACE_MAGIC)) \
{ \
EINA_MAGIC_FAIL(obj, EDBUS_SERVICE_INTERFACE_MAGIC); \
return; \
} \
} \
while (0)
#define EDBUS_SERVICE_INTERFACE_CHECK_RETVAL(obj, retval) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, retval); \
if (!EINA_MAGIC_CHECK(obj, EDBUS_SERVICE_INTERFACE_MAGIC)) \
{ \
EINA_MAGIC_FAIL(obj, EDBUS_SERVICE_INTERFACE_MAGIC); \
return retval; \
} \
} \
while (0)
static void _object_unregister(DBusConnection *conn, void *user_data);
static DBusHandlerResult _object_handler(DBusConnection *conn, DBusMessage *message, void *user_data);
static void _object_free(EDBus_Service_Object *obj);
static void _interface_free(EDBus_Service_Interface *interface);
static void _on_connection_free(void *data, const void *dead_pointer);
static DBusObjectPathVTable vtable = {
_object_unregister,
_object_handler,
NULL,
NULL,
NULL,
NULL
};
EDBus_Service_Interface *introspectable;
static void
_instrospect_append_signal(Eina_Strbuf *buf, const EDBus_Signal *sig)
{
int i;
const char *part, *name;
eina_strbuf_append_printf(buf, "<signal name=\"%s\">", sig->name);
if (sig->flags & EDBUS_SIGNAL_FLAG_DEPRECATED)
eina_strbuf_append(buf, DBUS_ANNOTATION_DEPRECATED);
for (i = 0; &sig->args[i] && sig->args[i].signature; i++)
{
part = sig->args[i].signature;
name = sig->args[i].name;
if (name && name[0])
eina_strbuf_append_printf(buf, "<arg type=\"%s\" name=\"%s\"/>",
part, name);
else
eina_strbuf_append_printf(buf, "<arg type=\"%s\"/>", part);
}
eina_strbuf_append(buf, "</signal>");
}
static void
_introspect_append_method(Eina_Strbuf *buf, const EDBus_Method *method)
{
int i;
const char *part, *name;
eina_strbuf_append_printf(buf, "<method name=\"%s\">", method->member);
if (method->flags & EDBUS_METHOD_FLAG_DEPRECATED)
eina_strbuf_append(buf, DBUS_ANNOTATION_DEPRECATED);
if (method->flags & EDBUS_METHOD_FLAG_NOREPLY)
eina_strbuf_append(buf, DBUS_ANNOTATION_NOREPLY);
for (i = 0; &method->in[i] && method->in[i].signature; i++)
{
part = method->in[i].signature;
name = method->in[i].name;
if (name && name[0])
eina_strbuf_append_printf(buf,
"<arg type=\"%s\" name=\"%s\" direction=\"in\"/>",
part, name);
else
eina_strbuf_append_printf(buf, "<arg type=\"%s\" direction=\"in\"/>",
part);
}
for (i = 0; &method->out[i] && method->out[i].signature; i++)
{
part = method->out[i].signature;
name = method->out[i].name;
if (name && name[0])
eina_strbuf_append_printf(buf,
"<arg type=\"%s\" name=\"%s\" direction=\"out\"/>",
part, name);
else
eina_strbuf_append_printf(buf, "<arg type=\"%s\" direction=\"out\"/>",
part);
}
eina_strbuf_append(buf, "</method>");
}
static void
_introspect_append_interface(Eina_Strbuf *buf, EDBus_Service_Interface *iface)
{
EDBus_Real_Method *method;
Eina_Iterator *iterator;
unsigned short i;
unsigned int size;
eina_strbuf_append_printf(buf, "<interface name=\"%s\">", iface->name);
iterator = eina_hash_iterator_data_new(iface->methods);
EINA_ITERATOR_FOREACH(iterator, method)
_introspect_append_method(buf, method->method);
eina_iterator_free(iterator);
size = eina_array_count(iface->sign_of_signals);
for (i = 0; i < size; i++)
_instrospect_append_signal(buf, &iface->signals[i]);
eina_strbuf_append(buf, "</interface>");
}
static EDBus_Message *
cb_introspect(const EDBus_Service_Interface *_iface, const EDBus_Message *message)
{
EDBus_Service_Object *obj = _iface->obj;
EDBus_Message *reply = edbus_message_method_return_new(message);
if (obj->introspection_dirty || !obj->introspection_data)
{
Eina_Iterator *iterator;
EDBus_Service_Interface *iface;
if (obj->introspection_data)
eina_strbuf_reset(obj->introspection_data);
else
obj->introspection_data = eina_strbuf_new();
EINA_SAFETY_ON_NULL_RETURN_VAL(obj->introspection_data, NULL);
eina_strbuf_append(obj->introspection_data, "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">");
eina_strbuf_append_printf(obj->introspection_data,
"<node name=\"%s\">", obj->path);
iterator = eina_hash_iterator_data_new(obj->interfaces);
EINA_ITERATOR_FOREACH(iterator, iface)
_introspect_append_interface(obj->introspection_data, iface);
eina_iterator_free(iterator);
eina_strbuf_append(obj->introspection_data, "</node>");
obj->introspection_dirty = EINA_FALSE;
}
edbus_message_arguments_set(reply, "s", eina_strbuf_string_get(obj->introspection_data));
return reply;
}
static const EDBus_Method instrospect = { "Introspect", EDBUS_ARGS({ "", "" }),
EDBUS_ARGS({ "s", "xml" }),
cb_introspect, 0
};
static void
_introspectable_create(void)
{
EDBus_Real_Method *r_instrospect;
introspectable = calloc(1, sizeof(EDBus_Service_Interface));
EINA_SAFETY_ON_NULL_RETURN(introspectable);
r_instrospect = malloc(sizeof(EDBus_Real_Method));
EINA_SAFETY_ON_NULL_RETURN(r_instrospect);
r_instrospect->in = "";
r_instrospect->method = &instrospect;
EINA_MAGIC_SET(introspectable, EDBUS_SERVICE_INTERFACE_MAGIC);
introspectable->sign_of_signals = eina_array_new(1);
introspectable->name = eina_stringshare_add("org.freedesktop.DBus.Introspectable");
introspectable->methods = eina_hash_string_small_new(NULL);
eina_hash_add(introspectable->methods, instrospect.member, r_instrospect);
}
static void
_instrospectable_free(void)
{
EDBus_Real_Method *method;
method = eina_hash_find(introspectable->methods, instrospect.member);
eina_stringshare_del(method->in);
free(method);
eina_hash_free(introspectable->methods);
eina_stringshare_del(introspectable->name);
eina_array_free(introspectable->sign_of_signals);
free(introspectable);
}
Eina_Bool
edbus_service_init(void)
{
_introspectable_create();
EINA_SAFETY_ON_NULL_RETURN_VAL(introspectable, EINA_FALSE);
return EINA_TRUE;
}
void
edbus_service_shutdown(void)
{
_instrospectable_free();
}
static EDBus_Service_Object *
_edbus_service_object_add(EDBus_Connection *conn, const char *path)
{
EDBus_Service_Object *obj;
obj = calloc(1, sizeof(EDBus_Service_Object));
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
if (!dbus_connection_register_object_path(conn->dbus_conn, path, &vtable,
obj))
{
free(obj);
return NULL;
}
obj->conn = conn;
obj->path = eina_stringshare_add(path);
obj->interfaces = eina_hash_string_superfast_new(NULL);
edbus_connection_cb_free_add(conn, _on_connection_free, obj);
eina_hash_add(obj->interfaces, introspectable->name, introspectable);
return obj;
}
static EDBus_Service_Interface *
_edbus_service_interface_add(EDBus_Service_Object *obj, const char *interface)
{
EDBus_Service_Interface *iface;
iface = eina_hash_find(obj->interfaces, interface);
if (iface) return iface;
iface = calloc(1, sizeof(EDBus_Service_Interface));
EINA_SAFETY_ON_NULL_RETURN_VAL(iface, NULL);
EINA_MAGIC_SET(iface, EDBUS_SERVICE_INTERFACE_MAGIC);
iface->name = eina_stringshare_add(interface);
iface->methods = eina_hash_string_superfast_new(NULL);
iface->obj = obj;
eina_hash_add(obj->interfaces, iface->name, iface);
return iface;
}
static Eina_Bool
_edbus_service_method_add(EDBus_Service_Interface *interface, EDBus_Method *method)
{
EDBus_Real_Method *rm;
Eina_Strbuf *buf;
int z;
EINA_SAFETY_ON_TRUE_RETURN_VAL(!!eina_hash_find(interface->methods,
method->member), EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(method->member, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(method->cb, EINA_FALSE);
buf = eina_strbuf_new();
for (z = 0; &method->in[z] && method->in[z].signature; z++)
eina_strbuf_append(buf, method->in[z].signature);
EINA_SAFETY_ON_FALSE_GOTO(
dbus_signature_validate(eina_strbuf_string_get(buf), NULL),
error);
rm = malloc(sizeof(EDBus_Real_Method));
EINA_SAFETY_ON_NULL_GOTO(rm, error);
rm->method = method;
rm->in = eina_stringshare_add(eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
//check if out is valid
buf = eina_strbuf_new();
for (z = 0; &method->out[z] && method->out[z].signature; z++)
eina_strbuf_append(buf, method->out[z].signature);
EINA_SAFETY_ON_FALSE_GOTO(
dbus_signature_validate(eina_strbuf_string_get(buf), NULL),
invalid_out);
eina_strbuf_free(buf);
eina_hash_add(interface->methods, method->member, rm);
return EINA_TRUE;
invalid_out:
eina_stringshare_del(rm->in);
free(rm);
error:
eina_strbuf_free(buf);
return EINA_FALSE;
}
EAPI EDBus_Service_Interface *
edbus_service_interface_register(EDBus_Connection *conn, const char *path, const char *interface, const EDBus_Method methods[], const EDBus_Signal signals[])
{
EDBus_Service_Object *obj;
EDBus_Service_Interface *iface;
EDBus_Method *method;
unsigned short i, z;
Eina_Strbuf *buf = NULL;
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(path, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(interface, EINA_FALSE);
if (!dbus_connection_get_object_path_data(conn->dbus_conn, path,
(void*)&obj))
{
ERR("Invalid object path");
return NULL;
}
if (obj == NULL)
obj = _edbus_service_object_add(conn, path);
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
iface = _edbus_service_interface_add(obj, interface);
if (!iface)
{
if (eina_hash_population(obj->interfaces) < 2)
_object_free(obj);
return NULL;
}
for (method = (EDBus_Method *)methods; method && method->member; method++)
_edbus_service_method_add(iface, method);
if (!iface->sign_of_signals)
iface->sign_of_signals = eina_array_new(1);
for (i = 0; &signals[i] && signals[i].name; i++)
{
buf = eina_strbuf_new();
for (z = 0; &signals[i].args[z] && signals[i].args[z].signature; z++)
eina_strbuf_append(buf, signals[i].args[z].signature);
if (!dbus_signature_validate(eina_strbuf_string_get(buf), NULL))
{
ERR("Signal with invalid signature: interface=%s signal=%s",
iface->name, signals[i].name);
eina_strbuf_free(buf);
continue;
}
eina_array_push(iface->sign_of_signals,
eina_stringshare_add(eina_strbuf_string_get(buf)));
eina_strbuf_free(buf);
}
iface->signals = signals;
return iface;
}
static void
_interface_free(EDBus_Service_Interface *interface)
{
unsigned size, i;
Eina_Iterator *iterator;
EDBus_Real_Method *method;
if (interface == introspectable) return;
iterator = eina_hash_iterator_data_new(interface->methods);
EINA_ITERATOR_FOREACH(iterator, method)
{
eina_stringshare_del(method->in);
free(method);
}
eina_iterator_free(iterator);
eina_hash_free(interface->methods);
eina_stringshare_del(interface->name);
size = eina_array_count(interface->sign_of_signals);
for (i = 0; i < size; i++)
eina_stringshare_del(eina_array_data_get(interface->sign_of_signals, i));
eina_array_free(interface->sign_of_signals);
free(interface);
}
static void
_object_free(EDBus_Service_Object *obj)
{
Eina_Iterator *iterator;
EDBus_Service_Interface *iface;
iterator = eina_hash_iterator_data_new(obj->interfaces);
EINA_ITERATOR_FOREACH(iterator, iface)
_interface_free(iface);
edbus_data_del_all(&obj->data);
eina_hash_free(obj->interfaces);
eina_iterator_free(iterator);
if (obj->introspection_data)
eina_strbuf_free(obj->introspection_data);
eina_stringshare_del(obj->path);
free(obj);
}
static void
_on_connection_free(void *data, const void *dead_pointer)
{
EDBus_Service_Object *obj = data;
dbus_connection_unregister_object_path(obj->conn->dbus_conn, obj->path);
}
EAPI void
edbus_service_interface_unregister(EDBus_Service_Interface *iface)
{
EDBUS_SERVICE_INTERFACE_CHECK(iface);
eina_hash_del(iface->obj->interfaces, NULL, iface);
if (eina_hash_population(iface->obj->interfaces) < 2)
edbus_service_object_unregister(iface);
_interface_free(iface);
}
EAPI void
edbus_service_object_unregister(EDBus_Service_Interface *iface)
{
EDBUS_SERVICE_INTERFACE_CHECK(iface);
/*
* It will be freed when _object_unregister() is called
* by libdbus.
*/
edbus_connection_cb_free_del(iface->obj->conn, _on_connection_free, iface->obj);
dbus_connection_unregister_object_path(iface->obj->conn->dbus_conn, iface->obj->path);
}
static void
_object_unregister(DBusConnection *conn, void *user_data)
{
EDBus_Service_Object *obj = user_data;
_object_free(obj);
}
static DBusHandlerResult
_object_handler(DBusConnection *conn, DBusMessage *msg, void *user_data)
{
EDBus_Service_Object *obj;
EDBus_Service_Interface *iface;
EDBus_Real_Method *method;
EDBus_Message *edbus_msg;
EDBus_Message *reply;
obj = user_data;
if (!obj) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
DBG("Connection@%p Got message:\n"
" Type: %s\n"
" Path: %s\n"
" Interface: %s\n"
" Member: %s\n"
" Sender: %s", obj->conn,
dbus_message_type_to_string(dbus_message_get_type(msg)),
dbus_message_get_path(msg),
dbus_message_get_interface(msg),
dbus_message_get_member(msg),
dbus_message_get_sender(msg));
iface = eina_hash_find(obj->interfaces, dbus_message_get_interface(msg));
if (!iface) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
method = eina_hash_find(iface->methods, dbus_message_get_member(msg));
if (!method) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
edbus_msg = edbus_message_new(EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(edbus_msg, DBUS_HANDLER_RESULT_NEED_MEMORY);
edbus_msg->dbus_msg = msg;
dbus_message_iter_init(edbus_msg->dbus_msg, &edbus_msg->iterator->dbus_iterator);
if (method->in && !dbus_message_has_signature(msg, method->in))
{
char buf[DBUS_MAXIMUM_SIGNATURE_LENGTH +
sizeof("Expected signature: ")];
snprintf(buf, sizeof(buf), "Expected signature: %s", method->in);
reply = edbus_message_error_new(edbus_msg,
DBUS_ERROR_INVALID_SIGNATURE, buf);
}
else
{
if (iface->obj)
reply = method->method->cb(iface, edbus_msg);
else
{
//if iface does have obj it is some of FreeDesktop interfaces:
//Introspectable, Properties...
EDBus_Service_Interface *cpy;
cpy = calloc(1, sizeof(EDBus_Service_Interface));
if (!cpy)
{
dbus_message_ref(edbus_msg->dbus_msg);
edbus_message_unref(edbus_msg);
return DBUS_HANDLER_RESULT_NEED_MEMORY;
}
cpy->obj = obj;
reply = method->method->cb(cpy, edbus_msg);
free(cpy);
}
}
dbus_message_ref(edbus_msg->dbus_msg);
edbus_message_unref(edbus_msg);
if (!reply) return DBUS_HANDLER_RESULT_HANDLED;
_edbus_connection_send(obj->conn, reply, NULL, NULL, -1);
edbus_message_unref(reply);
return DBUS_HANDLER_RESULT_HANDLED;
}
EAPI EDBus_Connection *
edbus_service_connection_get(const EDBus_Service_Interface *iface)
{
EDBUS_SERVICE_INTERFACE_CHECK_RETVAL(iface, NULL);
return iface->obj->conn;
}
EAPI const char *
edbus_service_object_path_get(const EDBus_Service_Interface *iface)
{
EDBUS_SERVICE_INTERFACE_CHECK_RETVAL(iface, NULL);
return iface->obj->path;
}
EAPI EDBus_Message *
edbus_service_signal_new(EDBus_Service_Interface *iface, unsigned int signal_id)
{
unsigned size;
EDBUS_SERVICE_INTERFACE_CHECK_RETVAL(iface, EINA_FALSE);
size = eina_array_count(iface->sign_of_signals);
EINA_SAFETY_ON_FALSE_RETURN_VAL(signal_id < size, EINA_FALSE);
return edbus_message_signal_new(iface->obj->path, iface->name,
iface->signals[signal_id].name);
}
EAPI Eina_Bool
edbus_service_signal_emit(EDBus_Service_Interface *iface, unsigned int signal_id, ...)
{
EDBus_Message *sig;
va_list ap;
Eina_Bool r;
const char *signature;
unsigned size;
EDBUS_SERVICE_INTERFACE_CHECK_RETVAL(iface, EINA_FALSE);
size = eina_array_count(iface->sign_of_signals);
EINA_SAFETY_ON_FALSE_RETURN_VAL(signal_id < size, EINA_FALSE);
sig = edbus_service_signal_new(iface, signal_id);
EINA_SAFETY_ON_NULL_RETURN_VAL(sig, EINA_FALSE);
signature = eina_array_data_get(iface->sign_of_signals, signal_id);
va_start(ap, signal_id);
r = edbus_message_arguments_vset(sig, signature, ap);
va_end(ap);
EINA_SAFETY_ON_FALSE_RETURN_VAL(r, EINA_FALSE);
edbus_service_signal_send(iface, sig);
edbus_message_unref(sig);
return EINA_TRUE;
}
EAPI Eina_Bool
edbus_service_signal_send(EDBus_Service_Interface *iface, EDBus_Message *signal_msg)
{
EDBUS_SERVICE_INTERFACE_CHECK_RETVAL(iface, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(signal_msg, EINA_FALSE);
_edbus_connection_send(iface->obj->conn, signal_msg, NULL, NULL, -1);
return EINA_TRUE;
}
EAPI void
edbus_service_object_data_set(EDBus_Service_Interface *iface, const char *key, const void *data)
{
EDBUS_SERVICE_INTERFACE_CHECK(iface);
EINA_SAFETY_ON_NULL_RETURN(key);
EINA_SAFETY_ON_NULL_RETURN(data);
edbus_data_set(&(iface->obj->data), key, data);
}
EAPI void *
edbus_service_object_data_get(const EDBus_Service_Interface *iface, const char *key)
{
EDBUS_SERVICE_INTERFACE_CHECK_RETVAL(iface, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
return edbus_data_get(&(((EDBus_Service_Object *)iface->obj)->data), key);
}
EAPI void *
edbus_service_object_data_del(EDBus_Service_Interface *iface, const char *key)
{
EDBUS_SERVICE_INTERFACE_CHECK_RETVAL(iface, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
return edbus_data_del(&(((EDBus_Service_Object *)iface->obj)->data), key);
}

View File

@ -0,0 +1,133 @@
#ifndef EDBUS_SERVICE_H
#define EDBUS_SERVICE_H 1
/**
* @defgroup EDBus_Service Service
*
* @{
*/
#define EDBUS_METHOD_FLAG_DEPRECATED 1
#define EDBUS_METHOD_FLAG_NOREPLY (1 << 1)
#define EDBUS_SIGNAL_FLAG_DEPRECATED 1
typedef struct _EDBus_Arg_Info
{
const char *signature;
const char *name;
} EDBus_Arg_Info;
/**
* @brief Used to insert complete types to signature of methods or signals.
*
* Example: EDBUS_ARGS({"s", "interface"}, {"s", "property"})
* The signature will be "ss" and each string will have a tag name on
* introspect XML with the respective name.
*/
#define EDBUS_ARGS(args...) (const EDBus_Arg_Info[]){ args, { } }
typedef struct _EDBus_Service_Interface EDBus_Service_Interface;
typedef EDBus_Message * (*EDBus_Method_Cb)(const EDBus_Service_Interface *iface, const EDBus_Message *message);
typedef struct _EDBus_Method
{
const char *member;
const EDBus_Arg_Info *in;
const EDBus_Arg_Info *out;
EDBus_Method_Cb cb;
unsigned int flags;
} EDBus_Method;
typedef struct _EDBus_Signal
{
const char *name;
const EDBus_Arg_Info *args;
unsigned int flags;
} EDBus_Signal;
/**
* @brief Register a interface on the passed path and connection.
*
* @param conn where the interface should listen
* @param path object path
* @param iface interface
* @param methods array of the methods that should be registered in this
* interface, the last item of array should be filled with NULL
* @param signals array of signal that this interface send, the last item
* of array should be filled with NULL
*
* @note methods and signals must be static variables
*
* @return Interface
*/
EAPI EDBus_Service_Interface *edbus_service_interface_register(EDBus_Connection *conn, const char *path, const char *interface, const EDBus_Method methods[], const EDBus_Signal signals[]);
/**
* @brief Unregister a interface.
* If this is the last interface of object path, the object path will be
* remove too.
*/
EAPI void edbus_service_interface_unregister(EDBus_Service_Interface *iface);
/**
* @brief Unregister all interfaces of the object path that this interface belongs
* and the object path.
*/
EAPI void edbus_service_object_unregister(EDBus_Service_Interface *iface);
EAPI EDBus_Connection *edbus_service_connection_get(const EDBus_Service_Interface *iface);
EAPI const char *edbus_service_object_path_get(const EDBus_Service_Interface *iface);
/**
* @brief Emit a signal handler of the interface with non-complex types.
* Each signal handler have a internal id, the first signal handler of
* interface is = 0 the second = 1 and go on.
*
* @param iface interface of the signal
* @param signal_id id of signal
* @param ... values that will be send on signal
*/
EAPI Eina_Bool edbus_service_signal_emit(EDBus_Service_Interface *iface, unsigned int signal_id, ...) EINA_ARG_NONNULL(1);
/**
* @brief Create signal message.
* Each signal handler have a internal id, the first signal handler of
* interface is = 0 the second = 1 and go on.
* This function is used when signal have complex types.
*
* @param iface interface of the signal
* @param signal_id id of signal
*/
EAPI EDBus_Message *edbus_service_signal_new(EDBus_Service_Interface *iface, unsigned int signal_id) EINA_ARG_NONNULL(1);
/**
* @brief Send a signal message.
*/
EAPI Eina_Bool edbus_service_signal_send(EDBus_Service_Interface *iface, EDBus_Message *signal_msg) EINA_ARG_NONNULL(1, 2);
/**
* @brief Store data at object path, this data can be get from all interfaces
* of the same object.
*
* @param iface interface that belong to the object path where data will
* be stored
* @param key to identify data
* @param data
*/
EAPI void edbus_service_object_data_set(EDBus_Service_Interface *iface, const char *key, const void *data);
/**
* @brief Get data stored in object path.
*
* @param iface interface that belong to the object path where data are stored
* @param key that identify data
*
* @return pointer to data if found otherwise NULL
*/
EAPI void *edbus_service_object_data_get(const EDBus_Service_Interface *iface, const char *key);
/**
* @brief Del data stored in object path.
*
* @param iface interface that belong to the object path where data are stored
* @param key that identify data
*
* @return pointer to data if found otherwise NULL
*/
EAPI void *edbus_service_object_data_del(EDBus_Service_Interface *iface, const char *key);
/**
* @}
*/
#endif

View File

@ -0,0 +1,340 @@
#include "edbus_private.h"
#include "edbus_private_types.h"
#include <dbus/dbus.h>
/* TODO: mempool of EDBus_Signal_Handler */
#define SENDER_KEY "sender"
#define PATH_KEY "path"
#define INTERFACE_KEY "interface"
#define MEMBER_KEY "member"
#define ARG_X_KEY "arg%u"
#define EDBUS_SIGNAL_HANDLER_CHECK(handler) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN(handler); \
if (!EINA_MAGIC_CHECK(handler, EDBUS_SIGNAL_HANDLER_MAGIC)) \
{ \
EINA_MAGIC_FAIL(handler, EDBUS_SIGNAL_HANDLER_MAGIC); \
return; \
} \
} \
while (0)
#define EDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, retval) \
do \
{ \
EINA_SAFETY_ON_NULL_RETURN_VAL(handler, retval); \
if (!EINA_MAGIC_CHECK(handler, EDBUS_SIGNAL_HANDLER_MAGIC)) \
{ \
EINA_MAGIC_FAIL(handler, EDBUS_SIGNAL_HANDLER_MAGIC); \
return retval; \
} \
} \
while (0)
static void _edbus_signal_handler_del(EDBus_Signal_Handler *handler);
static void _edbus_signal_handler_clean(EDBus_Signal_Handler *handler);
Eina_Bool
edbus_signal_handler_init(void)
{
return EINA_TRUE;
}
void
edbus_signal_handler_shutdown(void)
{
}
static void
_match_append(Eina_Strbuf *match, const char *key, const char *value)
{
if (value == NULL || !value[0]) return;
if ((eina_strbuf_length_get(match) + strlen(",=''") + strlen(key) + strlen(value))
>= DBUS_MAXIMUM_MATCH_RULE_LENGTH)
{
ERR("cannot add match %s='%s' to %s: too long!", key, value,
eina_strbuf_string_get(match));
return;
}
eina_strbuf_append_printf(match, ",%s='%s'", key, value);
}
#define ARGX "arg"
static int
_sort_arg(const void *d1, const void *d2)
{
const Signal_Argument *arg1, *arg2;
arg1 = d1;
arg2 = d2;
return arg1->index - arg2->index;
}
EAPI Eina_Bool
edbus_signal_handler_match_extra_set(EDBus_Signal_Handler *sh, ...)
{
va_list ap;
char *key = NULL, *value;
Signal_Argument *arg;
DBusError err;
EDBUS_SIGNAL_HANDLER_CHECK_RETVAL(sh, EINA_FALSE);
dbus_error_init(&err);
dbus_bus_remove_match(sh->conn->dbus_conn,
eina_strbuf_string_get(sh->match), &err);
EINA_SAFETY_ON_TRUE_RETURN_VAL(dbus_error_is_set(&err), EINA_FALSE);
va_start(ap, sh);
do
{
if (!key)
{
key = va_arg(ap, char *);
continue;
}
value = va_arg(ap, char *);
arg = calloc(1, sizeof(Signal_Argument));
EINA_SAFETY_ON_NULL_GOTO(arg, error);
if (!strncmp(key, ARGX, strlen(ARGX)))
{
int id = atoi(key+strlen(ARGX)-1);
arg->index = (unsigned short)id;
arg->value = eina_stringshare_add(value);
sh->args = eina_inlist_sorted_state_insert(sh->args,
EINA_INLIST_GET(arg),
_sort_arg,
sh->state_args);
_match_append(sh->match, key, value);
}
key = NULL;
} while(key);
va_end(ap);
dbus_error_init(&err);
dbus_bus_add_match(sh->conn->dbus_conn,
eina_strbuf_string_get(sh->match), &err);
if (!dbus_error_is_set(&err))
return EINA_TRUE;
ERR("Error setting new match.");
return EINA_FALSE;
error:
va_end(ap);
dbus_error_init(&err);
dbus_bus_add_match(sh->conn->dbus_conn,
eina_strbuf_string_get(sh->match), &err);
if (dbus_error_is_set(&err))
ERR("Error setting partial extra arguments.");
return EINA_FALSE;
}
EAPI EDBus_Signal_Handler *
edbus_signal_handler_add(EDBus_Connection *conn, const char *sender, const char *path, const char *interface, const char *member, EDBus_Signal_Cb cb, const void *cb_data)
{
EDBus_Signal_Handler *sh;
Eina_Strbuf *match;
DBusError err;
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
DBG("conn=%p, sender=%s, path=%s, interface=%s, member=%s, cb=%p %p",
conn, sender, path, interface, member, cb, cb_data);
sh = calloc(1, sizeof(EDBus_Signal_Handler));
EINA_SAFETY_ON_NULL_RETURN_VAL(sh, NULL);
match = eina_strbuf_new();
EINA_SAFETY_ON_NULL_GOTO(match, cleanup_create_strbuf);
eina_strbuf_append(match, "type='signal'");
_match_append(match, SENDER_KEY, sender);
_match_append(match, PATH_KEY, path);
_match_append(match, INTERFACE_KEY, interface);
_match_append(match, MEMBER_KEY, member);
dbus_error_init(&err);
dbus_bus_add_match(conn->dbus_conn, eina_strbuf_string_get(match), &err);
if (dbus_error_is_set(&err)) goto cleanup;
if (sender && sender[0] != ':' && strcmp(sender, EDBUS_FDO_BUS))
{
sh->bus = edbus_connection_name_get(conn, sender);
if (!sh->bus) goto cleanup;
edbus_connection_name_owner_monitor(conn, sh->bus, EINA_TRUE);
}
sh->cb = cb;
sh->cb_data = cb_data;
sh->conn = conn;
sh->interface = eina_stringshare_add(interface);
sh->member = eina_stringshare_add(member);
sh->path = eina_stringshare_add(path);
sh->sender = eina_stringshare_add(sender);
sh->match = match;
sh->refcount = 1;
sh->dangling = EINA_FALSE;
sh->state_args = eina_inlist_sorted_state_new();
EINA_MAGIC_SET(sh, EDBUS_SIGNAL_HANDLER_MAGIC);
edbus_connection_signal_handler_add(conn, sh);
return sh;
cleanup:
eina_strbuf_free(match);
cleanup_create_strbuf:
free(sh);
return NULL;
}
static Eina_Bool
signal_handler_deleter(void *data)
{
EDBus_Signal_Handler *handler = data;
_edbus_signal_handler_del(handler);
return ECORE_CALLBACK_CANCEL;
}
static void
_edbus_signal_handler_clean(EDBus_Signal_Handler *handler)
{
DBusError err;
if (handler->dangling) return;
edbus_connection_signal_handler_del(handler->conn, handler);
if (handler->bus)
edbus_connection_name_owner_monitor(handler->conn, handler->bus,
EINA_FALSE);
dbus_error_init(&err);
dbus_bus_remove_match(handler->conn->dbus_conn,
eina_strbuf_string_get(handler->match), &err);
handler->dangling = EINA_TRUE;
}
static void
_edbus_signal_handler_del(EDBus_Signal_Handler *handler)
{
Eina_Inlist *list;
Signal_Argument *arg;
DBG("handler %p, refcount=%d, conn=%p %s",
handler, handler->refcount, handler->conn, handler->sender);
edbus_cbs_free_dispatch(&(handler->cbs_free), handler);
EINA_MAGIC_SET(handler, EINA_MAGIC_NONE);
/* after cbs_free dispatch these shouldn't exit, error if they do */
eina_stringshare_del(handler->sender);
eina_stringshare_del(handler->path);
eina_stringshare_del(handler->interface);
eina_stringshare_del(handler->member);
eina_strbuf_free(handler->match);
EINA_INLIST_FOREACH_SAFE(handler->args, list, arg)
{
eina_stringshare_del(arg->value);
free(arg);
}
eina_inlist_sorted_state_free(handler->state_args);
free(handler);
}
EAPI EDBus_Signal_Handler *
edbus_signal_handler_ref(EDBus_Signal_Handler *handler)
{
EDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
DBG("handler=%p, pre-refcount=%d, match=%s",
handler, handler->refcount, eina_strbuf_string_get(handler->match));
handler->refcount++;
return handler;
}
EAPI void
edbus_signal_handler_unref(EDBus_Signal_Handler *handler)
{
EDBUS_SIGNAL_HANDLER_CHECK(handler);
DBG("handler=%p, pre-refcount=%d, match=%s",
handler, handler->refcount, eina_strbuf_string_get(handler->match));
handler->refcount--;
if (handler->refcount > 0) return;
_edbus_signal_handler_clean(handler);
if (handler->conn->running_signal)
ecore_idler_add(signal_handler_deleter, handler);
else
_edbus_signal_handler_del(handler);
}
EAPI void
edbus_signal_handler_del(EDBus_Signal_Handler *handler)
{
EDBUS_SIGNAL_HANDLER_CHECK(handler);
_edbus_signal_handler_clean(handler);
edbus_signal_handler_unref(handler);
}
EAPI void
edbus_signal_handler_cb_free_add(EDBus_Signal_Handler *handler, EDBus_Free_Cb cb, const void *data)
{
EDBUS_SIGNAL_HANDLER_CHECK(handler);
EINA_SAFETY_ON_NULL_RETURN(cb);
handler->cbs_free = edbus_cbs_free_add(handler->cbs_free, cb, data);
}
EAPI void
edbus_signal_handler_cb_free_del(EDBus_Signal_Handler *handler, EDBus_Free_Cb cb, const void *data)
{
EDBUS_SIGNAL_HANDLER_CHECK(handler);
EINA_SAFETY_ON_NULL_RETURN(cb);
handler->cbs_free = edbus_cbs_free_del(handler->cbs_free, cb, data);
}
EAPI const char *
edbus_signal_handler_sender_get(const EDBus_Signal_Handler *handler)
{
EDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
return handler->sender;
}
EAPI const char *
edbus_signal_handler_path_get(const EDBus_Signal_Handler *handler)
{
EDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
return handler->path;
}
EAPI const char *
edbus_signal_handler_interface_get(const EDBus_Signal_Handler *handler)
{
EDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
return handler->interface;
}
EAPI const char *
edbus_signal_handler_member_get(const EDBus_Signal_Handler *handler)
{
EDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
return handler->member;
}
EAPI const char *
edbus_signal_handler_match_get(const EDBus_Signal_Handler *handler)
{
EDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
return eina_strbuf_string_get(handler->match);
}
EAPI EDBus_Connection *
edbus_signal_handler_connection_get(const EDBus_Signal_Handler *handler)
{
EDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
return handler->conn;
}

View File

@ -0,0 +1,75 @@
#ifndef EDBUS_SIGNAL_HANDLER_H
#define EDBUS_SIGNAL_HANDLER_H 1
/**
* @defgroup EDBus_Signal_Handler Signal Handler
*
* @{
*/
/**
* @brief Add a signal handler.
*
* @param conn connection where the signal is emitted
* @param sender bus name or unique id of where the signal is emitted
* @param path path of remote object
* @param interface that signal belongs
* @param member name of the signal
* @param cb callback that will be called when this signal is received
* @param cb_data data that will be passed to callback
*/
EAPI EDBus_Signal_Handler *edbus_signal_handler_add(EDBus_Connection *conn, const char *sender, const char *path, const char *interface, const char *member, EDBus_Signal_Cb cb, const void *cb_data) EINA_ARG_NONNULL(1, 6);
/**
* @brief Increase signal handler reference.
*/
EAPI EDBus_Signal_Handler *edbus_signal_handler_ref(EDBus_Signal_Handler *handler) EINA_ARG_NONNULL(1);
/**
* @brief Decrease signal handler reference.
* If reference == 0 signal handler will be freed.
*/
EAPI void edbus_signal_handler_unref(EDBus_Signal_Handler *handler) EINA_ARG_NONNULL(1);
/**
* @brief Decrease signal handler reference like edbus_signal_handler_unref()
* but if reference > 0 this signal handler will stop listen signals. In other
* words will be canceled but memory will not be freed.
*/
EAPI void edbus_signal_handler_del(EDBus_Signal_Handler *handler) EINA_ARG_NONNULL(1);
/**
* @brief Add extra argument in match of signal handler to obtain specifics signals.
*
* Example:
* edbus_signal_handler_match_extra_set(sh, "arg0", "org.bansheeproject.Banshee", "arg1", "", NULL);
* With this extra arguments this signal handler callback only will be called
* when Banshee is started.
*
* @note For now is only supported argX.
*
* @param sh signal handler
* @param ... variadic of key and value and must be ended with a NULL
*
* @note To information:
* http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-routing-match-rules
*/
EAPI Eina_Bool edbus_signal_handler_match_extra_set(EDBus_Signal_Handler *sh, ...) EINA_ARG_NONNULL(1) EINA_SENTINEL;
/**
* @brief Add a callback function to be called when signal handler will be freed.
*/
EAPI void edbus_signal_handler_cb_free_add(EDBus_Signal_Handler *handler, EDBus_Free_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
/**
* @brief Remove callback registered in edbus_signal_handler_cb_free_add().
*/
EAPI void edbus_signal_handler_cb_free_del(EDBus_Signal_Handler *handler, EDBus_Free_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2);
EAPI const char *edbus_signal_handler_sender_get(const EDBus_Signal_Handler *handler) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_signal_handler_path_get(const EDBus_Signal_Handler *handler) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_signal_handler_interface_get(const EDBus_Signal_Handler *handler) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_signal_handler_member_get(const EDBus_Signal_Handler *handler) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI const char *edbus_signal_handler_match_get(const EDBus_Signal_Handler *handler) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI EDBus_Connection *edbus_signal_handler_connection_get(const EDBus_Signal_Handler *handler) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
/**
* @}
*/
#endif