Tizen 2.1 base
authorJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 16:42:06 +0000 (01:42 +0900)
committerJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 16:42:06 +0000 (01:42 +0900)
186 files changed:
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
configure.ac [new file with mode: 0644]
depcomp [new file with mode: 0755]
docs/Makefile.am [new file with mode: 0755]
docs/reference/Makefile.am [new file with mode: 0755]
docs/reference/geoclue-docs.sgml [new file with mode: 0755]
docs/reference/geoclue.types [new file with mode: 0755]
docs/reference/implementing-providers.xml [new file with mode: 0755]
docs/reference/using-geoclue.xml [new file with mode: 0755]
docs/tools/Makefile.am [new file with mode: 0755]
docs/tools/spec-strip-docs.xsl [new file with mode: 0755]
docs/tools/spec-to-docbook.xsl [new file with mode: 0755]
example/Makefile.am [new file with mode: 0644]
example/address-example.c [new file with mode: 0755]
example/common-example.c [new file with mode: 0755]
example/geocode-example.c [new file with mode: 0755]
example/master-example.c [new file with mode: 0755]
example/master-pos-example.c [new file with mode: 0644]
example/position-async-example.c [new file with mode: 0755]
example/position-example.c [new file with mode: 0644]
example/revgeocode-example.c [new file with mode: 0755]
geoclue.changes [new file with mode: 0644]
geoclue.pc.in [new file with mode: 0644]
geoclue/Makefile.am [new file with mode: 0644]
geoclue/gc-iface-address.c [new file with mode: 0644]
geoclue/gc-iface-address.h [new file with mode: 0644]
geoclue/gc-iface-geoclue.c [new file with mode: 0644]
geoclue/gc-iface-geoclue.h [new file with mode: 0644]
geoclue/gc-iface-geocode.c [new file with mode: 0644]
geoclue/gc-iface-geocode.h [new file with mode: 0644]
geoclue/gc-iface-nmea.c [new file with mode: 0644]
geoclue/gc-iface-nmea.h [new file with mode: 0644]
geoclue/gc-iface-poi.c [new file with mode: 0644]
geoclue/gc-iface-poi.h [new file with mode: 0644]
geoclue/gc-iface-position-ext.c [new file with mode: 0644]
geoclue/gc-iface-position-ext.h [new file with mode: 0644]
geoclue/gc-iface-position.c [new file with mode: 0644]
geoclue/gc-iface-position.h [new file with mode: 0644]
geoclue/gc-iface-reverse-geocode.c [new file with mode: 0644]
geoclue/gc-iface-reverse-geocode.h [new file with mode: 0644]
geoclue/gc-iface-satellite.c [new file with mode: 0644]
geoclue/gc-iface-satellite.h [new file with mode: 0644]
geoclue/gc-iface-velocity.c [new file with mode: 0644]
geoclue/gc-iface-velocity.h [new file with mode: 0644]
geoclue/gc-provider.c [new file with mode: 0644]
geoclue/gc-provider.h [new file with mode: 0644]
geoclue/gc-web-service.c [new file with mode: 0644]
geoclue/gc-web-service.h [new file with mode: 0644]
geoclue/geoclue-accuracy.c [new file with mode: 0644]
geoclue/geoclue-accuracy.h [new file with mode: 0644]
geoclue/geoclue-address-details.c [new file with mode: 0644]
geoclue/geoclue-address-details.h [new file with mode: 0644]
geoclue/geoclue-address.c [new file with mode: 0644]
geoclue/geoclue-address.h [new file with mode: 0644]
geoclue/geoclue-error.c [new file with mode: 0644]
geoclue/geoclue-error.h [new file with mode: 0644]
geoclue/geoclue-geocode.c [new file with mode: 0644]
geoclue/geoclue-geocode.h [new file with mode: 0644]
geoclue/geoclue-landmark.h [new file with mode: 0644]
geoclue/geoclue-marshal.list [new file with mode: 0644]
geoclue/geoclue-master-client.c [new file with mode: 0644]
geoclue/geoclue-master-client.h [new file with mode: 0644]
geoclue/geoclue-master.c [new file with mode: 0644]
geoclue/geoclue-master.h [new file with mode: 0644]
geoclue/geoclue-nmea.c [new file with mode: 0644]
geoclue/geoclue-nmea.h [new file with mode: 0644]
geoclue/geoclue-poi.c [new file with mode: 0644]
geoclue/geoclue-poi.h [new file with mode: 0644]
geoclue/geoclue-position-ext.c [new file with mode: 0644]
geoclue/geoclue-position-ext.h [new file with mode: 0644]
geoclue/geoclue-position.c [new file with mode: 0644]
geoclue/geoclue-position.h [new file with mode: 0644]
geoclue/geoclue-provider.c [new file with mode: 0644]
geoclue/geoclue-provider.h [new file with mode: 0644]
geoclue/geoclue-reverse-geocode.c [new file with mode: 0644]
geoclue/geoclue-reverse-geocode.h [new file with mode: 0644]
geoclue/geoclue-satellite-info.h [new file with mode: 0644]
geoclue/geoclue-satellite.c [new file with mode: 0644]
geoclue/geoclue-satellite.h [new file with mode: 0644]
geoclue/geoclue-types.c [new file with mode: 0644]
geoclue/geoclue-types.h [new file with mode: 0644]
geoclue/geoclue-velocity.c [new file with mode: 0644]
geoclue/geoclue-velocity.h [new file with mode: 0644]
gtk-doc.make [new file with mode: 0644]
install-sh [new file with mode: 0755]
interfaces/Makefile.am [new file with mode: 0644]
interfaces/gc-iface-address-full.xml [new file with mode: 0755]
interfaces/gc-iface-geoclue-full.xml [new file with mode: 0644]
interfaces/gc-iface-geocode-full.xml [new file with mode: 0755]
interfaces/gc-iface-master-client-full.xml [new file with mode: 0755]
interfaces/gc-iface-master-full.xml [new file with mode: 0755]
interfaces/gc-iface-nmea-full.xml [new file with mode: 0644]
interfaces/gc-iface-poi-full.xml [new file with mode: 0644]
interfaces/gc-iface-position-ext-full.xml [new file with mode: 0755]
interfaces/gc-iface-position-full.xml [new file with mode: 0755]
interfaces/gc-iface-reverse-geocode-full.xml [new file with mode: 0755]
interfaces/gc-iface-satellite-full.xml [new file with mode: 0644]
interfaces/gc-iface-velocity-full.xml [new file with mode: 0755]
libgeoclue.manifest [new file with mode: 0644]
packaging/geoclue.spec [new file with mode: 0644]
providers/Makefile.am [new file with mode: 0644]
providers/example/Makefile.am [new file with mode: 0644]
providers/example/geoclue-example.c [new file with mode: 0644]
providers/example/geoclue-example.provider [new file with mode: 0755]
providers/example/org.freedesktop.Geoclue.Providers.Example.service.in [new file with mode: 0755]
providers/geonames/Makefile.am [new file with mode: 0644]
providers/geonames/geoclue-geonames.c [new file with mode: 0755]
providers/geonames/geoclue-geonames.h [new file with mode: 0755]
providers/geonames/geoclue-geonames.provider [new file with mode: 0755]
providers/geonames/org.freedesktop.Geoclue.Providers.Geonames.service.in [new file with mode: 0755]
providers/gpsd/Makefile.am [new file with mode: 0644]
providers/gpsd/geoclue-gpsd.c [new file with mode: 0644]
providers/gpsd/geoclue-gpsd.provider [new file with mode: 0644]
providers/gpsd/org.freedesktop.Geoclue.Providers.Gpsd.service.in [new file with mode: 0644]
providers/gsmloc/Makefile.am [new file with mode: 0644]
providers/gsmloc/geoclue-gsmloc-ofono.c [new file with mode: 0755]
providers/gsmloc/geoclue-gsmloc-ofono.h [new file with mode: 0755]
providers/gsmloc/geoclue-gsmloc.c [new file with mode: 0644]
providers/gsmloc/geoclue-gsmloc.provider [new file with mode: 0755]
providers/gsmloc/mcc.h [new file with mode: 0755]
providers/gsmloc/ofono-manager.xml [new file with mode: 0755]
providers/gsmloc/ofono-marshal.list [new file with mode: 0755]
providers/gsmloc/ofono-modem.xml [new file with mode: 0755]
providers/gsmloc/ofono-network-operator.xml [new file with mode: 0755]
providers/gsmloc/ofono-network-registration.xml [new file with mode: 0755]
providers/gsmloc/org.freedesktop.Geoclue.Providers.Gsmloc.service.in [new file with mode: 0755]
providers/gypsy/Makefile.am [new file with mode: 0644]
providers/gypsy/geoclue-gypsy.c [new file with mode: 0644]
providers/gypsy/geoclue-gypsy.provider [new file with mode: 0755]
providers/gypsy/org.freedesktop.Geoclue.Providers.Gypsy.service.in [new file with mode: 0755]
providers/hostip/Makefile.am [new file with mode: 0644]
providers/hostip/geoclue-hostip.c [new file with mode: 0755]
providers/hostip/geoclue-hostip.h [new file with mode: 0755]
providers/hostip/geoclue-hostip.provider [new file with mode: 0755]
providers/hostip/org.freedesktop.Geoclue.Providers.Hostip.service.in [new file with mode: 0755]
providers/localnet/Makefile.am [new file with mode: 0644]
providers/localnet/geoclue-localnet.c [new file with mode: 0644]
providers/localnet/geoclue-localnet.provider [new file with mode: 0755]
providers/localnet/geoclue-localnet.xml [new file with mode: 0755]
providers/localnet/org.freedesktop.Geoclue.Providers.Localnet.service.in [new file with mode: 0755]
providers/manual/Makefile.am [new file with mode: 0644]
providers/manual/geoclue-manual.c [new file with mode: 0644]
providers/manual/geoclue-manual.provider [new file with mode: 0755]
providers/manual/geoclue-manual.xml [new file with mode: 0755]
providers/manual/org.freedesktop.Geoclue.Providers.Manual.service.in [new file with mode: 0755]
providers/nominatim/Makefile.am [new file with mode: 0644]
providers/nominatim/geoclue-nominatim.c [new file with mode: 0755]
providers/nominatim/geoclue-nominatim.h [new file with mode: 0755]
providers/nominatim/geoclue-nominatim.provider [new file with mode: 0755]
providers/nominatim/org.freedesktop.Geoclue.Providers.Nominatim.service.in [new file with mode: 0755]
providers/plazes/Makefile.am [new file with mode: 0644]
providers/plazes/geoclue-plazes.c [new file with mode: 0644]
providers/plazes/geoclue-plazes.provider [new file with mode: 0755]
providers/plazes/org.freedesktop.Geoclue.Providers.Plazes.service.in [new file with mode: 0755]
providers/skyhook/Makefile.am [new file with mode: 0644]
providers/skyhook/geoclue-skyhook.c [new file with mode: 0644]
providers/skyhook/geoclue-skyhook.provider [new file with mode: 0644]
providers/skyhook/org.freedesktop.Geoclue.Providers.Skyhook.service.in [new file with mode: 0755]
providers/yahoo/Makefile.am [new file with mode: 0644]
providers/yahoo/geoclue-yahoo.c [new file with mode: 0755]
providers/yahoo/geoclue-yahoo.provider [new file with mode: 0755]
providers/yahoo/org.freedesktop.Geoclue.Providers.Yahoo.service.in [new file with mode: 0755]
src/Makefile.am [new file with mode: 0644]
src/client.c [new file with mode: 0644]
src/client.h [new file with mode: 0755]
src/connectivity-conic.c [new file with mode: 0755]
src/connectivity-conic.h [new file with mode: 0755]
src/connectivity-networkmanager.c [new file with mode: 0644]
src/connectivity-networkmanager.h [new file with mode: 0644]
src/connectivity.c [new file with mode: 0644]
src/connectivity.h [new file with mode: 0644]
src/main.c [new file with mode: 0644]
src/main.h [new file with mode: 0755]
src/master-provider.c [new file with mode: 0644]
src/master-provider.h [new file with mode: 0755]
src/master.c [new file with mode: 0644]
src/master.h [new file with mode: 0755]
src/org.freedesktop.Geoclue.Master.service.in [new file with mode: 0755]
test/Makefile.am [new file with mode: 0644]
test/geoclue-test-gui.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..8c7959c
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,8 @@
+Keith Preston <keithpre@gmail.com>
+Jussi Kukkonen <jku@o-hand.com>
+Iain Holmes <Iain@openedhand.com>
+Sangho Park <sangho.g.park@samsung.com>
+Tae-Hwan Kim <the81.kim@samsung.com>
+Youngae Kang <youngae.kang@samsung.com>
+Yunhan Kim <yhan.kim@samsung.com>
+Genie Kim <daejins.kim@samsung.com>
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..5fde166
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,439 @@
+Geoclue is licensed under the GNU LPGL Version 2
+
+                 GNU LIBRARY GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+                    675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+\f
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+\f
+                 GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..58a1235
--- /dev/null
@@ -0,0 +1,12 @@
+SUBDIRS = interfaces geoclue providers src
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = geoclue.pc
+
+DISTCLEANFILES = \
+        geoclue.pc
+
+EXTRA_DIST = \
+        geoclue.pc.in
+
+DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..19f3cc2
--- /dev/null
+++ b/README
@@ -0,0 +1,24 @@
+
+Current providers recognise these options:
+
+       * org.freedesktop.Geoclue.GPSDevice
+               Gypsy provider will use this device name 
+               (e.g. "00:02:76:C5:81:BF" or "/dev/pgps")
+
+       * org.freedesktop.Geoclue.GPSHost
+               Gpsd provider will contact gpsd on this host.
+        Default is NULL (localhost)
+
+    * org.freedesktop.Geoclue.GPSPort
+               Gpsd provider will contact gpsd on this port.
+        Default is "2947".
+
+
+
+Provider options can be set with SetOptions-method. Geoclue-master
+reads options from gconf (/apps/geoclue/master): as an example, the 
+Gypsy device for geoclue master can be set with
+ gconftool-2  \
+       -t string \
+       -s /apps/geoclue/master/org.freedesktop.Geoclue.GPSDevice 00:02:76:C5:81:BF
+
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..214b294
--- /dev/null
@@ -0,0 +1,35 @@
+#! /bin/sh
+
+LIBTOOLIZE=libtoolize
+AUTOMAKE=automake
+ACLOCAL=aclocal
+AUTOCONF=autoconf
+AUTOHEADER=autoheader
+
+# Check for binaries
+
+[ "x$(which ${LIBTOOLIZE})x" = "xx" ] && {
+    echo "${LIBTOOLIZE} not found. Please install it."
+    exit 1
+}
+
+[ "x$(which ${AUTOMAKE})x" = "xx" ] && {
+    echo "${AUTOMAKE} not found. Please install it."
+    exit 1
+}
+
+[ "x$(which ${ACLOCAL})x" = "xx" ] && {
+    echo "${ACLOCAL} not found. Please install it."
+    exit 1
+}
+
+[ "x$(which ${AUTOCONF})x" = "xx" ] && {
+    echo "${AUTOCONF} not found. Please install it."
+    exit 1
+}
+
+"${ACLOCAL}" \
+&& "${LIBTOOLIZE}" --force \
+&& "${AUTOHEADER}" \
+&& "${AUTOCONF}" \
+&& "${AUTOMAKE}" --add-missing
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..145ad25
--- /dev/null
@@ -0,0 +1,175 @@
+AC_PREREQ(2.59)
+AC_INIT(geoclue, 0.12.0, http://geoclue.freedesktop.org)
+
+AC_CONFIG_SRCDIR(geoclue/gc-iface-geoclue.c)
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE([1.9 foreign])
+GEOCLUE_VERSION=0.12.0
+
+AC_PROG_CC
+AC_ISC_POSIX
+
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_GCC_TRADITIONAL
+AM_PROG_LIBTOOL
+
+#GTK_DOC_CHECK(1.0)
+AC_CHECK_PROGS(XSLT, xsltproc)
+
+AC_ARG_ENABLE(system-bus,
+             [AC_HELP_STRING([--enable-system-bus],
+                             [Use the system bus instead of session bus])],
+             enable_system_bus="$enableval",
+             enable_system_bus=no)
+
+AM_CONDITIONAL(USE_SYSTEM_BUS, test x$enable_system_bus = xyes)
+if test x$enable_system_bus = xyes; then
+       AC_DEFINE(GEOCLUE_DBUS_BUS, DBUS_BUS_SYSTEM, Use the system bus)
+else
+       AC_DEFINE(GEOCLUE_DBUS_BUS, DBUS_BUS_SESSION, Use the session bus)
+fi
+
+PKG_CHECK_MODULES(GEOCLUE, [
+                 glib-2.0
+                 gobject-2.0
+                 dbus-glib-1 >= 0.60
+                 libxml-2.0
+])
+AC_SUBST(GEOCLUE_LIBS)
+AC_SUBST(GEOCLUE_CFLAGS)
+
+PKG_CHECK_MODULES(MASTER, [
+                 gconf-2.0
+])
+AC_SUBST(MASTER_LIBS)
+AC_SUBST(MASTER_CFLAGS)
+
+AC_PATH_PROG(DBUS_BINDING_TOOL, dbus-binding-tool)
+AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
+
+DBUS_SERVICES_DIR="${datadir}/dbus-1/services"
+AC_SUBST(DBUS_SERVICES_DIR)
+AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [Where services dir for D-Bus is])
+
+CFLAGS="$CFLAGS -g -Wall -Werror -Wno-format"
+
+# -----------------------------------------------------------
+# gtk+
+# -----------------------------------------------------------
+AC_ARG_ENABLE(gtk,
+              AS_HELP_STRING([--enable-gtk=@<:@no/yes/auto@:>@],
+                             [build with gtk support]), ,
+                             enable_gtk=no)
+if test "x$enable_gtk" != "xno"; then
+   PKG_CHECK_MODULES(GTK,
+   [
+      gtk+-2.0
+   ], have_gtk="yes", have_gtk="no")
+   if test "x$have_gtk" = "xyes"; then
+      AC_DEFINE(HAVE_GTK, 1, [Define if you have gtk+])
+   fi
+else
+   have_gtk=no
+fi
+
+if test "x$enable_gtk" = "xyes" -a "x$have_gtk" != "xyes"; then
+   AC_MSG_ERROR(["Couldn't find gtk dependencies."])
+fi
+
+AM_CONDITIONAL(HAVE_GTK, test "x$have_gtk" = "xyes")
+AC_SUBST(GTK_LIBS)
+AC_SUBST(GTK_CFLAGS)
+
+# -----------------------------------------------------------
+# connectivity
+# -----------------------------------------------------------
+
+CONNECTIVITY="None"
+
+AC_ARG_ENABLE(conic,
+              AS_HELP_STRING([--enable-conic=@<:@no/yes/auto@:>@],
+                             [build with conic support]), ,
+                             enable_conic=auto)
+
+if test "x$enable_conic" != "xno"; then
+   PKG_CHECK_MODULES(CONIC,
+   [
+      conic
+   ], have_conic="yes", have_conic="no")
+
+   if test "x$have_conic" = "xyes"; then
+      CONNECTIVITY="Maemo LibConIC"
+      CONNECTIVITY_LIBS=${CONIC_LIBS}
+      CONNECTIVITY_CFLAGS=${CONIC_CFLAGS}
+      AC_DEFINE(HAVE_CONIC, 1, [define if libconic is installed])
+   fi
+else
+   have_conic=no
+fi
+
+if test "x$enable_conic" = "xyes" -a "x$have_conic" != "xyes"; then
+   AC_MSG_ERROR(["Couldn't find conic dependencies."])
+fi
+
+AC_ARG_ENABLE(networkmanager,
+              AS_HELP_STRING([--enable-networkmanager=@<:@no/yes/auto@:>@],
+                             [build with NetworkManager support]), ,
+                             enable_networkmanager=auto)
+
+if test "x$enable_networkmanager" != "xno"; then
+   PKG_CHECK_MODULES(NETWORK_MANAGER,
+   [
+      NetworkManager libnm_glib
+   ], have_networkmanager="yes", have_networkmanager="no")
+
+   if test "x$have_networkmanager" = "xyes"; then
+      CONNECTIVITY="Network Manager"
+      CONNECTIVITY_LIBS=${NETWORK_MANAGER_LIBS}
+      CONNECTIVITY_CFLAGS=${NETWORK_MANAGER_CFLAGS}
+      AC_DEFINE(HAVE_NETWORK_MANAGER, 1, [define if Network Manager is installed])
+   fi
+else
+   have_networkmanager=no
+fi
+
+if test "x$enable_networkmanager" = "xyes" -a "x$have_networkmanager" != "xyes"; then
+   AC_MSG_ERROR(["Couldn't find Network Manager dependencies."])
+fi
+
+AC_SUBST(CONNECTIVITY_LIBS)
+AC_SUBST(CONNECTIVITY_CFLAGS)
+
+PROVIDER_SUBDIRS="nominatim"
+
+AC_SUBST(PROVIDER_SUBDIRS)
+AC_SUBST(NO_BUILD_PROVIDERS)
+
+AC_CONFIG_FILES([
+geoclue.pc
+Makefile
+interfaces/Makefile
+geoclue/Makefile
+providers/Makefile
+providers/gpsd/Makefile
+providers/nominatim/Makefile
+src/Makefile
+])
+#docs/Makefile
+#docs/reference/Makefile
+#docs/tools/Makefile
+
+AC_OUTPUT
+
+echo ""
+echo "Geoclue ${VERSION} has been configured as follows: "
+echo "---------------------------------------------------"
+echo "Source code location:   ${srcdir}"
+echo "Compiler:               ${CC}"
+echo "Network connectivity:   ${CONNECTIVITY}"
+echo "Providers:              ${PROVIDER_SUBDIRS}"
+echo "Excluded providers:    ${NO_BUILD_PROVIDERS}"
+echo ""
diff --git a/depcomp b/depcomp
new file mode 100755 (executable)
index 0000000..aeba4e8
--- /dev/null
+++ b/depcomp
@@ -0,0 +1,632 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
+# Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+  '')
+     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+  depmode     Dependency tracking mode.
+  source      Source file read by `PROGRAMS ARGS'.
+  object      Object file output by `PROGRAMS ARGS'.
+  DEPDIR      directory where to store dependencies.
+  depfile     Dependency file to output.
+  tmpdepfile  Temporary file to use when outputing dependencies.
+  libtool     Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "depcomp $scriptversion"
+    exit $?
+    ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+   # This is just like dashmstdout with a different argument.
+   dashmflag=-xM
+   depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+   # This is just like msvisualcpp but w/o cygpath translation.
+   # Just convert the backslash-escaped backslashes to single forward
+   # slashes to satisfy depend.m4
+   cygpath_u="sed s,\\\\\\\\,/,g"
+   depmode=msvisualcpp
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am.  Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+  for arg
+  do
+    case $arg in
+    -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+    *)  set fnord "$@" "$arg" ;;
+    esac
+    shift # fnord
+    shift # $arg
+  done
+  "$@"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+  tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'.  On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like `#:fec' to the end of the
+    # dependency line.
+    tr ' ' '
+' < "$tmpdepfile" \
+    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+    tr '
+' ' ' >> "$depfile"
+    echo >> "$depfile"
+
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' '
+' < "$tmpdepfile" \
+   | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+   >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  In older versions, this file always lives in the
+  # current directory.  Also, the AIX compiler puts `$object:' at the
+  # start of each line; $object doesn't have directory information.
+  # Version 6 uses the directory in both cases.
+  dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+  test "x$dir" = "x$object" && dir=
+  base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$base.u
+    tmpdepfile3=$dir.libs/$base.u
+    "$@" -Wc,-M
+  else
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$dir$base.u
+    tmpdepfile3=$dir$base.u
+    "$@" -M
+  fi
+  stat=$?
+
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form `foo.o: dependent.h'.
+    # Do two passes, one to just change these to
+    # `$object: dependent.h' and one to simply `dependent.h:'.
+    sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+    # That's a tab and a space in the [].
+    sed -e 's,^.*\.[a-z]*:[     ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+icc)
+  # Intel's C compiler understands `-MD -MF file'.  However on
+  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+  # ICC 7.0 will fill foo.d with something like
+  #    foo.o: sub/foo.c
+  #    foo.o: sub/foo.h
+  # which is wrong.  We want:
+  #    sub/foo.o: sub/foo.c
+  #    sub/foo.o: sub/foo.h
+  #    sub/foo.c:
+  #    sub/foo.h:
+  # ICC 7.1 will output
+  #    foo.o: sub/foo.c sub/foo.h
+  # and will wrap long lines using \ :
+  #    foo.o: sub/foo.c ... \
+  #     sub/foo.h ... \
+  #     ...
+
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h',
+  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+    sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp2)
+  # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+  # compilers, which have integrated preprocessors.  The correct option
+  # to use with these is +Maked; it writes dependencies to a file named
+  # 'foo.d', which lands next to the object file, wherever that
+  # happens to be.
+  # Much of this is similar to the tru64 case; see comments there.
+  dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+  test "x$dir" = "x$object" && dir=
+  base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir.libs/$base.d
+    "$@" -Wc,+Maked
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    "$@" +Maked
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+     rm -f "$tmpdepfile1" "$tmpdepfile2"
+     exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+    # Add `dependent.h:' lines.
+    sed -ne '2,${
+              s/^ *//
+              s/ \\*$//
+              s/$/:/
+              p
+            }' "$tmpdepfile" >> "$depfile"
+  else
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile" "$tmpdepfile2"
+  ;;
+
+tru64)
+   # The Tru64 compiler uses -MD to generate dependencies as a side
+   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+   # dependencies in `foo.d' instead, so we check for that too.
+   # Subdirectories are respected.
+   dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+   test "x$dir" = "x$object" && dir=
+   base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+   if test "$libtool" = yes; then
+      # With Tru64 cc, shared objects can also be used to make a
+      # static library.  This mechanism is used in libtool 1.4 series to
+      # handle both shared and static libraries in a single compilation.
+      # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+      #
+      # With libtool 1.5 this exception was removed, and libtool now
+      # generates 2 separate objects for the 2 libraries.  These two
+      # compilations output dependencies in $dir.libs/$base.o.d and
+      # in $dir$base.o.d.  We have to check for both files, because
+      # one of the two compilations can be disabled.  We should prefer
+      # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+      # automatically cleaned when .libs/ is deleted, while ignoring
+      # the former would cause a distcleancheck panic.
+      tmpdepfile1=$dir.libs/$base.lo.d   # libtool 1.4
+      tmpdepfile2=$dir$base.o.d          # libtool 1.5
+      tmpdepfile3=$dir.libs/$base.o.d    # libtool 1.5
+      tmpdepfile4=$dir.libs/$base.d      # Compaq CCC V6.2-504
+      "$@" -Wc,-MD
+   else
+      tmpdepfile1=$dir$base.o.d
+      tmpdepfile2=$dir$base.d
+      tmpdepfile3=$dir$base.d
+      tmpdepfile4=$dir$base.d
+      "$@" -MD
+   fi
+
+   stat=$?
+   if test $stat -eq 0; then :
+   else
+      rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+      exit $stat
+   fi
+
+   for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+   do
+     test -f "$tmpdepfile" && break
+   done
+   if test -f "$tmpdepfile"; then
+      sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+      # That's a tab and a space in the [].
+      sed -e 's,^.*\.[a-z]*:[   ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+   else
+      echo "#dummy" > "$depfile"
+   fi
+   rm -f "$tmpdepfile"
+   ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  test -z "$dashmflag" && dashmflag=-M
+  # Require at least two characters before searching for `:'
+  # in the target name.  This is to cope with DOS-style filenames:
+  # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+  "$@" $dashmflag |
+    sed 's:^[  ]*[^: ][^:][^:]*\:[    ]*:'"$object"'\: :' > "$tmpdepfile"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  "$@" || exit $?
+  # Remove any Libtool call
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+  # X makedepend
+  shift
+  cleared=no eat=no
+  for arg
+  do
+    case $cleared in
+    no)
+      set ""; shift
+      cleared=yes ;;
+    esac
+    if test $eat = yes; then
+      eat=no
+      continue
+    fi
+    case "$arg" in
+    -D*|-I*)
+      set fnord "$@" "$arg"; shift ;;
+    # Strip any option that makedepend may not understand.  Remove
+    # the object too, otherwise makedepend will parse it as a source file.
+    -arch)
+      eat=yes ;;
+    -*|$object)
+      ;;
+    *)
+      set fnord "$@" "$arg"; shift ;;
+    esac
+  done
+  obj_suffix=`echo "$object" | sed 's/^.*\././'`
+  touch "$tmpdepfile"
+  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  "$@" -E |
+    sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+       -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+    sed '$ s: \\$::' > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  IFS=" "
+  for arg
+  do
+    case "$arg" in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+       set fnord "$@"
+       shift
+       shift
+       ;;
+    *)
+       set fnord "$@" "$arg"
+       shift
+       shift
+       ;;
+    esac
+  done
+  "$@" -E 2>/dev/null |
+  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::     \1 \\:p' >> "$depfile"
+  echo "       " >> "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvcmsys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/docs/Makefile.am b/docs/Makefile.am
new file mode 100755 (executable)
index 0000000..9e8b487
--- /dev/null
@@ -0,0 +1,2 @@
+SUBDIRS = reference tools
+
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
new file mode 100755 (executable)
index 0000000..1d4265f
--- /dev/null
@@ -0,0 +1,111 @@
+## Process this file with automake to produce Makefile.in
+
+# We require automake 1.6 at least.
+AUTOMAKE_OPTIONS = 1.6
+
+# This is a blank Makefile.am for using gtk-doc.
+# Copy this to your project's API docs directory and modify the variables to
+# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
+# of using the various options.
+
+# The name of the module, e.g. 'glib'.
+DOC_MODULE=geoclue
+
+# The top-level SGML file. You can change this if you want to.
+DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
+
+# The directory containing the source code. Relative to $(srcdir).
+# gtk-doc will search all .c & .h files beneath here for inline comments
+# documenting the functions and macros.
+# e.g. DOC_SOURCE_DIR=../../../gtk
+DOC_SOURCE_DIR=../../geoclue
+
+# Extra options to pass to gtkdoc-scangobj. Not normally needed.
+SCANGOBJ_OPTIONS=
+
+# Extra options to supply to gtkdoc-scan.
+# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
+SCAN_OPTIONS=
+
+# Extra options to supply to gtkdoc-mkdb.
+# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
+MKDB_OPTIONS=--sgml-mode --output-format=xml
+
+# Extra options to supply to gtkdoc-mktmpl
+# e.g. MKTMPL_OPTIONS=--only-section-tmpl
+MKTMPL_OPTIONS=
+
+# Extra options to supply to gtkdoc-fixref. Not normally needed.
+# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
+FIXXREF_OPTIONS=
+
+# Used for dependencies. The docs will be rebuilt if any of these change.
+# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
+# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
+HFILE_GLOB=$(top_srcdir)/geoclue/*.h
+CFILE_GLOB=$(top_srcdir)/geoclue/*.c
+
+# Header files to ignore when scanning.
+# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
+IGNORE_HFILES= \
+       geoclue-marshal.h \
+       gc-iface-address-bindings.h \
+       gc-iface-reverse-geocode-bindings.h \
+       gc-iface-geoclue-bindings.h \
+       gc-iface-velocity-bindings.h \
+       gc-iface-geocode-bindings.h \
+       gc-iface-position-bindings.h \
+       gc-iface-address-glue.h \
+       gc-iface-reverse-geocode-glue.h \
+       gc-iface-geoclue-glue.h \
+       gc-iface-velocity-glue.h \
+       gc-iface-geocode-glue.h \
+       gc-iface-position-glue.h
+
+# Images to copy into HTML directory.
+# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
+HTML_IMAGES=
+
+dbus_docs = \
+       gc-iface-master-ref.xml \
+       gc-iface-master-client-ref.xml \
+       gc-iface-geoclue-ref.xml \
+       gc-iface-position-ref.xml \
+       gc-iface-address-ref.xml \
+       gc-iface-geocode-ref.xml \
+       gc-iface-reverse-geocode-ref.xml \
+       gc-iface-velocity-ref.xml
+
+
+# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
+# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
+content_files= \
+       implementing-providers.xml \
+       using-geoclue.xml \
+       $(dbus_docs)
+
+# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
+# These files must be listed here *and* in content_files
+# e.g. expand_content_files=running.sgml
+expand_content_files=
+
+# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
+# Only needed if you are using gtkdoc-scangobj to dynamically query widget
+# signals and properties.
+# e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
+# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
+INCLUDES=-I$(top_srcdir) $(GEOCLUE_CFLAGS)
+GTKDOC_LIBS=$(top_builddir)/geoclue/libgeoclue.la $(GEOCLUE_LIBS)
+
+# This includes the standard gtk-doc make rules, copied by gtkdocize.
+include $(top_srcdir)/gtk-doc.make
+
+# Other files to distribute
+# e.g. EXTRA_DIST += version.xml.in
+EXTRA_DIST +=
+
+CLEAN_FILES = $(dbus_docs)
+
+%-ref.xml: $(top_srcdir)/interfaces/%-full.xml
+       $(XSLT) -o $@ $(top_srcdir)/docs/tools/spec-to-docbook.xsl $<
+
diff --git a/docs/reference/geoclue-docs.sgml b/docs/reference/geoclue-docs.sgml
new file mode 100755 (executable)
index 0000000..4554c85
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                                                        "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
+       <bookinfo>
+               <title>Geoclue Reference Manual</title>
+       </bookinfo>
+
+       <xi:include href="using-geoclue.xml"/>
+
+       <reference>
+               <title>C API</title>
+               <xi:include href="xml/geoclue-master.xml"/>
+               <xi:include href="xml/geoclue-master-client.xml"/>
+               <xi:include href="xml/geoclue-provider.xml"/>
+               <xi:include href="xml/geoclue-position.xml"/>
+               <xi:include href="xml/geoclue-address.xml"/>
+               <xi:include href="xml/geoclue-velocity.xml"/>
+               <xi:include href="xml/geoclue-geocode.xml"/>
+               <xi:include href="xml/geoclue-reverse-geocode.xml"/>
+               <xi:include href="xml/geoclue-types.xml"/>
+               <xi:include href="xml/geoclue-accuracy.xml"/>
+               <xi:include href="xml/geoclue-address-details.xml"/>
+               <xi:include href="xml/geoclue-error.xml"/>
+       </reference>
+
+       <reference>
+               <title>D-Bus API</title>
+               <xi:include href="gc-iface-master-ref.xml"/>
+               <xi:include href="gc-iface-master-client-ref.xml"/>
+               <xi:include href="gc-iface-geoclue-ref.xml"/>
+               <xi:include href="gc-iface-position-ref.xml"/>
+               <xi:include href="gc-iface-address-ref.xml"/>
+               <xi:include href="gc-iface-velocity-ref.xml"/>
+               <xi:include href="gc-iface-geocode-ref.xml"/>
+               <xi:include href="gc-iface-reverse-geocode-ref.xml"/>
+       </reference>
+
+</book>
diff --git a/docs/reference/geoclue.types b/docs/reference/geoclue.types
new file mode 100755 (executable)
index 0000000..064bb81
--- /dev/null
@@ -0,0 +1,29 @@
+#include <geoclue/geoclue-master.h>
+#include <geoclue/geoclue-master-client.h>
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-position.h>
+#include <geoclue/geoclue-velocity.h>
+#include <geoclue/geoclue-address.h>
+#include <geoclue/geoclue-geocode.h>
+#include <geoclue/geoclue-reverse-geocode.h>
+
+#include <geoclue/geoclue-accuracy.h>
+#include <geoclue/geoclue-address-details.h>
+#include <geoclue/geoclue-error.h>
+#include <geoclue/geoclue-types.h>
+
+#include <geoclue/gc-web-service.h>
+#include <geoclue/gc-provider.h>
+
+geoclue_master_get_type
+geoclue_master_client_get_type
+geoclue_provider_get_type
+geoclue_position_get_type
+geoclue_velocity_get_type
+geoclue_address_get_type
+geoclue_geocode_get_type
+geoclue_reverse_geocode_get_type
+geoclue_error_get_type
+
+gc_web_service_get_type
+gc_provider_get_type
diff --git a/docs/reference/implementing-providers.xml b/docs/reference/implementing-providers.xml
new file mode 100755 (executable)
index 0000000..38f4f9b
--- /dev/null
@@ -0,0 +1,396 @@
+<?xml version="1.0"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+
+<chapter>
+       <title>Developing a Geoclue provider</title>
+       <section id="overview">
+               <title>Overview</title>
+               <para>
+                       Geoclue providers are D-Bus services that provide geoinformation services
+                       by implementing defined interfaces (such as Position, Address or Geocode).
+                       Writing a provider is possible in any language with D-Bus, but
+                       Geoclue bindings are provided only for C. This how-to will outline the steps
+                       needed to write a provider for Geoclue  and provides
+                       source code in C. The full source code for an exmple provider  and several
+                       other providers can be found in providers/ directory in the Geoclue source tree.
+               </para>
+               <para>
+                       The only must-have requirements for providers are:
+                       <itemizedlist>
+                               <listitem>Must implement the *Geoclue*-interface. This interface has
+                               some generic methods and signals for getting information about the
+                               provider and its status </listitem>
+                               <listitem>Must provide a service file. This is used by D-Bus to start the
+                               service when needed.</listitem>
+                       </itemizedlist>
+               </para>
+               <para>
+                       A useful provider will also implement one, or several, other interfaces. It should
+                       also have a .provider-file so GeoclueMaster can use it.
+                       This howto will use "Position"-interface as an example. Possible interfaces
+                       are listed here:
+               </para>
+               <variablelist>
+                       <varlistentry>
+                               <term>Geoclue</term>
+                               <listitem><para>Methods and signals common to all providers.</para></listitem>
+                       </varlistentry>
+
+                       <varlistentry>
+                               <term>Position</term>
+                               <listitem><para>Methods and signals for acquiring current position
+                               (latitude, longitude and altitude).</para></listitem>
+                       </varlistentry>
+
+                       <varlistentry>
+                               <term>Velocity</term>
+                               <listitem><para>Methods and signals for acquiring current velocity.</para></listitem>
+                       </varlistentry>
+
+                       <varlistentry>
+                               <term>Address</term>
+                               <listitem><para>Methods and signals for acquiring current address
+                               (e.g. country, city, street address).</para></listitem>
+                       </varlistentry>
+
+                       <varlistentry>
+                               <term>Geocode</term>
+                               <listitem><para>Method for geocoding a known address to position.</para></listitem>
+                       </varlistentry>
+
+                       <varlistentry>
+                               <term>ReverseGeocode</term>
+                               <listitem><para>Method for reverse geocoding a known position to an address.</para></listitem>
+                       </varlistentry>
+               </variablelist>
+       </section>
+
+       <section id="example_in_c">
+               <title>Minimal example in C</title>
+               <para>
+                       In this chapter we'll look at implementing a minimal provider (which just implements
+                       Geoclue-interface). Next chapter will show how other interface implementations can
+                       be added using GObject interfaces.
+               </para>
+               <sect2 id="service_file">
+                       <title>Service file</title>
+                       <para>
+                               Once your provider is installed, the service file allows D-Bus to start it
+                               on demand. This is what your
+                               org.freedesktop.Geoclue.Providers.MyExample.service.in should look like
+                               (see Makefile.am for the processing):
+                       </para>
+                               <programlisting>
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Providers.MyExample
+Exec=@libexecdir@/geoclue-my-example
+                               </programlisting>
+
+               </sect2>
+
+               <sect2 id="provider_file">
+                       <title>Provider file</title>
+                       <para>
+                               Provider files describe the provider for Geoclue Master. This is still
+                               somewhat experimental, but a .provider-file for MyExample should look like this:
+                       </para>
+                       <programlisting>
+[Geoclue Provider]
+Name=My Example
+Service=org.freedesktop.Geoclue.Providers.MyExample
+Path=/org/freedesktop/Geoclue/Providers/MyExample
+Interfaces=org.freedesktop.Geoclue.Position
+Accuracy=0
+Provides=ProvidesUpdates
+Requires=
+                       </programlisting>
+                       <para>
+                               TODO: list accuracylevels, Requires, Provides...
+                       </para>
+               </sect2>
+
+               <sect2>
+                       <subtitle>Makefile.am and configure.ac</subtitle>
+                       <para>
+                               A typical provider can be implemented in a single c-file with a very short
+                               Makefile.am. This snippet assumes the code is built inside the geoclue source
+                               tree:
+                       </para>
+                       <programlisting>
+libexec_PROGRAMS = geoclue-my-example
+
+geoclue_my_example_CFLAGS =        \
+               -I$(top_srcdir)         \
+               -I$(top_builddir)       \
+               $(GEOCLUE_CFLAGS)
+
+geoclue_my_example_LDADD =         \
+               $(GEOCLUE_LIBS)         \
+               $(top_builddir)/geoclue/libgeoclue-provider.la
+
+geoclue_my_example_SOURCES =       \
+               geoclue-example.c
+
+providersdir = $(datadir)/geoclue-providers
+providers_DATA = geoclue-my-example.provider
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Providers.MyExample.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $&lt; &gt; $@
+                       </programlisting>
+                       <para>
+                               To get the provider built along with everything else in Geoclue, configure.ac
+                               must be edited: The Makefile filename needs to be added into $AC_CONFIG_FILES
+                               and the provider directory needs to be added to $PROVIDER_SUBDIRS.
+                       </para>
+               </sect2>
+               <sect2>
+
+                       <subtitle>The code</subtitle>
+                       <para>
+                       When coding in C, providers should be implemented as GObjects derived from
+                       GcProvider, as GcProvider will take care of the D-Bus service setup (name
+                       request and object registration). It will also partially implement the
+                       Geoclue-interface.
+                       </para>
+
+                       <para>
+                       First, include gc-provider.h:
+                       </para>
+                       <programlisting>
+#include &lt;config.h&gt;
+#include &lt;geoclue/gc-provider.h&gt;
+                       </programlisting>
+                       <para>
+                       Define our ExampleProvider GObject (derive from GcProvider):
+                       </para>
+                       <programlisting>
+typedef struct {
+       GcProvider parent;
+       GMainLoop *loop;
+} GeoclueExample;
+
+typedef struct {
+       GcProviderClass parent_class;
+} GeoclueExampleClass;
+
+#define GEOCLUE_TYPE_EXAMPLE (geoclue_example_get_type ())
+#define GEOCLUE_EXAMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_EXAMPLE, GeoclueExample))
+
+G_DEFINE_TYPE (GeoclueExample, geoclue_example, GC_TYPE_PROVIDER)
+                       </programlisting>
+
+                       <para>
+                       Next, implement Geoclue-interface functions (take a look at gc-iface-geoclue.h)
+                       and use them to override GcProvider:
+                       </para>
+                       <programlisting>
+static gboolean
+get_status (GcIfaceGeoclue *gc,
+               gboolean       *available,
+               GError        **error)
+{
+       *available = TRUE;
+
+       return TRUE;
+}
+
+static gboolean
+shutdown (GcIfaceGeoclue *gc,
+         GError        **error)
+{
+       GeoclueExample *example = GEOCLUE_EXAMPLE (gc);
+
+       g_main_loop_quit (example->loop);
+       return TRUE;
+}
+
+static void
+geoclue_example_class_init (GeoclueExampleClass *klass)
+{
+       GcProviderClass *p_class = (GcProviderClass *) klass;
+
+       p_class->get_status = get_status;
+       p_class->shutdown = shutdown;
+}
+                       </programlisting>
+                       <para>
+                       get_status() and shutdown() return TRUE as an indication that the method
+                       was succesfully invoked. The actual return values are set in pointer
+                       arguments such as "available" in get_status(). See the interface
+                       documentation to find out how the functions should behave.
+                       </para>
+
+                       <para>
+                       Next, write a initialization function for the provider:
+                       </para>
+                       <programlisting>
+static void
+geoclue_example_init (GeoclueExample *example)
+{
+       gc_provider_set_details (GC_PROVIDER (example),
+                                "org.freedesktop.Geoclue.Providers.MyExample",
+                                "/org/freedesktop/Geoclue/Providers/MyExample",
+                                "My Example", "Example provider");
+}
+                       </programlisting>
+                       <para>
+                       GcProvider will use the service name and path to setup the D-Bus service.
+                       Name and description (the last two arguments) will be used to implement
+                       get_provider_info().
+                       </para>
+
+                       <para>
+                       That's pretty much it. We still need a main() function to run the code:
+                       </para>
+                       <programlisting>
+int
+main (int    argc,
+      char **argv)
+{
+       GeoclueExample *example;
+
+       g_type_init ();
+
+       example = g_object_new (GEOCLUE_TYPE_EXAMPLE, NULL);
+       example->loop = g_main_loop_new (NULL, TRUE);
+
+       g_main_loop_run (example->loop);
+
+       g_main_loop_unref (example->loop);
+       g_object_unref (example);
+
+       return 0;
+}
+                       </programlisting>
+
+                       <para>
+                               The provider should compile and run now. Start it and test with a D-Bus call:
+                       </para>
+                       <programlisting>
+dbus-send --print-reply \
+          --dest="org.freedesktop.Geoclue.Providers.MyExample" \
+          /org/freedesktop/Geoclue/Providers/MyExample \
+          org.freedesktop.Geoclue.GetProviderInfo
+                       </programlisting>
+               </sect2>
+       </section>
+       <section>
+                       <title>Adding functionality by implementing other interfaces</title>
+
+                       <para>
+                       Adding functionality to the (so far fairly impotent) provider is not
+                       difficult. These are the steps needed to implement interface X:
+                       </para>
+                       <itemizedlist>
+                         <listitem>Include the interface header (gc-iface-X.h)</listitem>
+                         <listitem>Use G_IMPLEMENT_INTERFACE in your provider type definition</listitem>
+                         <listitem>Implement the methods and signals defined in gc-iface-X.h</listitem>
+                         <listitem>Implement a interface initialization function</listitem>
+                       </itemizedlist>
+
+                       <para>
+                               In our example we're implementing the Position interface:
+                       </para>
+                       <programlisting>
+#include &lt;geoclue/gc-iface-position.h&gt;
+                       </programlisting>
+                       <para>
+                               The type definition should now look like this:
+                       </para>
+                       <programlisting>
+static void geoclue_example_position_init (GcIfacePositionClass *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueExample, geoclue_example, GC_TYPE_PROVIDER,
+                G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION,
+                                       geoclue_example_position_init))
+                       </programlisting>
+
+                       <para>
+                       Next, take a look at the interface header (gc-iface-position.h). Implement
+                       the interface method and write some signal emission code:
+                       </para>
+                       <programlisting>
+
+
+static gboolean
+get_position (GcIfacePosition       *gc,
+                 GeocluePositionFields *fields,
+                 int                   *timestamp,
+                 double                *latitude,
+                 double                *longitude,
+                 double                *altitude,
+                 GeoclueAccuracy      **accuracy,
+                 GError               **error)
+{
+       *fields =  GEOCLUE_POSITION_FIELDS_LATITUDE | GEOCLUE_POSITION_FIELDS_LONGITUDE,
+       *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0.0, 0.0);
+       *latitude = 60.0;
+       *longitude = 25.0;
+
+       return TRUE;
+}
+
+
+
+static gboolean
+emit_position_signal (GeoclueExample *example)
+{
+       static GeoclueAccuracy *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0);
+
+       / * make up some coordinates * /
+       static double lat = 60.0;
+       static double lon = 25.0;
+
+       lat += 0.1;
+       lon -= 0.1;
+
+       g_debug ("Emitting position\n");
+
+       gc_iface_position_emit_position_changed
+               (GC_IFACE_POSITION (example),
+                GEOCLUE_POSITION_FIELDS_LATITUDE | GEOCLUE_POSITION_FIELDS_LONGITUDE,
+                time (NULL),
+                lat, lon, 0,
+                accuracy);
+
+       geoclue_accuracy_free (accuracy);
+
+       return TRUE;
+}
+                       </programlisting>
+                       <para>
+                       Yes, this implementation is too useful... For more realistic
+                       examples see the included providers in providers/-directory. Note the
+                       use of convenience function gc_iface_position_emit_position_changed() for
+                       signal emission.
+                       </para>
+
+                       <para>
+                       The example does not have a real position data source, so we'll
+                       emulate signal emission: add a g_timeout_add call in main(), before running the
+                       main loop.
+                       </para>
+                       <programlisting>
+g_timeout_add (5000, (GSourceFunc)emit_position_signal, example);
+                       </programlisting>
+
+                       <para>
+                       Finally, the interface method needs to be initialized to the implementation we just defined:
+                       </para>
+                       <programlisting>
+static void
+geoclue_example_position_init (GcIfacePositionClass *iface)
+{
+       iface->get_position = get_position;
+}
+                       </programlisting>
+                       <para>
+                       You can try your provider out by starting it and running
+                       "example/position-example MyExample"
+                       </para>
+       </section>
+</chapter>
diff --git a/docs/reference/using-geoclue.xml b/docs/reference/using-geoclue.xml
new file mode 100755 (executable)
index 0000000..f06efe1
--- /dev/null
@@ -0,0 +1,327 @@
+<?xml version="1.0"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+
+<chapter>
+       <title>Using Geoclue in applications</title>
+       <section id="overview">
+               <title>Overview</title>
+               <sect2>
+                       <subtitle>Why use Geoclue</subtitle>
+                       <para>
+                               Building context-sensitive applications is difficult. Location-sensitivy is no
+                               exception, but Geoclue tries to help there. With Geoclue it is possible to build
+                               location-aware applications with less work and less knowledge about the actual
+                               geoinformation sources.
+                       </para>
+                       <para> Main features of Geoclue are:
+                               <itemizedlist>
+                               <listitem>Standardized D-Bus (and GObject) interfaces to various geographical data sources</listitem>
+                               <listitem>Easy and fast to implement: Need to get data from provider XYZ?
+                               Chances are, Geoclue is the easiest way to do that...</listitem>
+                               <listitem>Geoclue Master provider (experimental at the moment) makes things eaven easier:
+                               you don't even have to choose a data provider, just let Geoclue choose the
+                               best possible provider for you.</listitem>
+                               <listitem>Adding new providers (data sources) is straight-forward: Even when the geoinformation
+                               source you want is not already in Geoclue, Implementing a Geoclue provider may
+                               well turn out to be the easiest way forward.</listitem>
+                               </itemizedlist>
+                       </para>
+               </sect2>
+               <sect2>
+                       <subtitle>Requirements</subtitle>
+                       <para>
+                               Geoclue is a collection of D-Bus APIs. Internally it's implemented with GLib and GObject (as is the C wrapper library).
+                               Several included providers also use Libxml2, and the master provider uses GConf.
+                       </para>
+                       <para>
+                               There is a GObject-based C API, but using Geoclue is possible from any programming language
+                               with D-Bus support.
+                       </para>
+               </sect2>
+               <sect2>
+                       <subtitle>Using basic Geoclue providers</subtitle>
+                       <para>
+                               D-Bus can automatically start services as they're needed so basic method calls
+                               can be made without any preparation. However, geoclue providers may shut down when
+                               they're not used. This means that clients using signals and clients that set any options
+                               should always use AddReference() and RemoveReference() methods to ensure server
+                               persistence. In C the wrapper takes care of this.
+                       </para>
+                       <para>
+                               Clients should not assume that method calls will return instantly or that the
+                               response will contain valid data. Examples of possible problems
+                               <itemizedlist>
+                                       <listitem>Many geoclue providers use web services so method calls may take seconds or even time out.</listitem>
+                                       <listitem>GPS providers usually respond instantly, but will not have a valid data until after getting a fix (which may take anything from a few seconds to minutes)</listitem>
+                               </itemizedlist>
+                               Using signals should be the first option whenever the used provider supports them.
+                               When signals are not available, asynchronous method calls can be used in
+                               applications where UI responsiveness is important.
+                       </para>
+               </sect2>
+               <sect2>
+                       <subtitle>Using Geoclue Master</subtitle>
+                       <para>Master provider was designed to solve the following problems:
+                               <itemizedlist>
+                                       <listitem>A single provider cannot be the best solution to all problems</listitem>
+                                       <listitem>The "best" providers will be different depending on the user</listitem>
+                                       <listitem>Supporting a single geodata source can be a big job for an application developer, supporting several would be a nightmare</listitem>
+                               </itemizedlist>
+                       </para>
+                       <para>
+                               Master provider implements the same interfaces as regular providers, but internally
+                               it uses whichever regular provider happens to be the best one (with "best" defined as
+                               a provider that fulfills the accuracy requirements and does not surpass resource restrictions).
+                               The internally used provider may change over time -- this does not interrupt clients use in any way,
+                               but the changes can be observed using the MasterClient API.
+                       </para>
+                       <para>
+                               A typical Master provider use includes:
+                               <itemizedlist>
+                               <listitem>Getting a client-specific GeoclueMasterClient from GeoclueMaster</listitem>
+                               <listitem>Setting GeoclueMasterClient requirements (such as accuracy)</listitem>
+                               <listitem>Starting the wanted interfaces (such as Position) </listitem>
+                               <listitem>Using the client just like a regular provider</listitem>
+                               </itemizedlist>
+                       </para>
+
+                       <para>
+                               Master provider is fairly new and may not be as stable as the rest of Geoclue.
+                       </para>
+               </sect2>
+               <sect2>
+                       <subtitle>Current providers</subtitle>
+                       TODO: list the providers shipped with geoclue, shortly explain their features.
+               </sect2>
+       </section>
+       <section id="simple-example">
+               <title>Using basic Geoclue providers: simple example in C</title>
+               <para>There are several examples in the geoclue source, these are included here to
+               give a quick overview.
+               </para>
+               <para>
+                       Here is a very simple example of using a specific Geoclue Position provider.
+                       Note that we're using the synchronous version of the method call here, so
+                       geoclue_position_get_position() will block until the response comes (or until D-Bus timeouts).
+               </para>
+               <programlisting>
+#include &lt;geoclue/geoclue-position.h&gt;
+
+int main()
+{
+       GeocluePosition *pos;
+       GeocluePositionFields fields;
+       double lat, lon;
+       GError *error = NULL;
+
+       g_type_init ();
+
+       / * Create the position object * /
+       pos = geoclue_position_new ("org.freedesktop.Geoclue.Providers.Hostip",
+                                   "/org/freedesktop/Geoclue/Providers/Hostip");
+
+       / * call get_position. Note that unneeded output variables (here
+           timestamp, altitude and accuracy) can be left NULL * /
+       fields = geoclue_position_get_position (pos, NULL,
+                                               &amp;lat, &amp;lon, NULL,
+                                               NULL, &amp;error);
+       if (error) {
+               g_printerr ("Error in get_position: %s.\n", error->message);
+               g_error_free (error);
+               g_object_unref (pos);
+               return 1;
+       }
+
+       if (fields &amp; GEOCLUE_POSITION_FIELDS_LATITUDE &amp;&amp;
+           fields &amp; GEOCLUE_POSITION_FIELDS_LONGITUDE) {
+               g_print ("According to Hostip.info we're at %.3f, %.3f.\n",
+                         lat, lon);
+       } else {
+               g_print ("Hostip does not have a valid location available.\nVisit http://www.hostip.info/ to correct this");
+       }
+       g_object_unref (pos);
+
+       return 0;
+}
+               </programlisting>
+               <para>Save as test-hostip.c and compile with
+               </para>
+               <programlisting>
+gcc `pkg-config --libs --cflags geoclue`  -o test-hostip test-hostip.c
+               </programlisting>
+               <para>Here is a similarly simple example using GLib mainloop and Gypsy provider with
+               position-changed signals:
+               </para>
+               <programlisting>
+#include &lt;geoclue/geoclue-position.h&gt;
+
+/ * device name or bluetooth address * /
+#define GPS_DEVICE_NAME "00:02:76:C5:81:BF"
+
+static void
+position_changed (GeocluePosition      *position,
+                  GeocluePositionFields fields,
+                  int                   timestamp,
+                  double                latitude,
+                  double                longitude,
+                  double                altitude,
+                  GeoclueAccuracy      *accuracy,
+                  gpointer              userdata)
+{
+       g_print ("Position changed:\n");
+       if (fields &amp; GEOCLUE_POSITION_FIELDS_LATITUDE &amp;&amp;
+           fields &amp; GEOCLUE_POSITION_FIELDS_LONGITUDE) {
+               g_print ("\t%f, %f\n\n", latitude, longitude);
+       } else {
+               g_print ("\tLatitude and longitude not available.\n\n");
+       }
+}
+
+int main()
+{
+       GMainLoop *loop;
+       GHashTable *options;
+       GeocluePosition *pos;
+       GError *error = NULL;
+
+       g_type_init ();
+
+       / * Create the position object * /
+       pos = geoclue_position_new ("org.freedesktop.Geoclue.Providers.Gypsy",
+                                   "/org/freedesktop/Geoclue/Providers/Gypsy");
+
+       / * Set GPS device name option for Gypsy * /
+       options = g_hash_table_new (g_str_hash, g_str_equal);
+       g_hash_table_insert (options, "org.freedesktop.Geoclue.GPSDevice", GPS_DEVICE_NAME);
+       if (!geoclue_provider_set_options (GEOCLUE_PROVIDER (pos), options, &amp;error)) {
+               g_printerr ("Error setting options: %s\n", error->message);
+               g_error_free (error);
+               g_hash_table_destroy (options);
+               g_object_unref (pos);
+                return 1;
+       }
+       g_hash_table_destroy (options);
+
+       / * connect to signal * /
+       g_signal_connect (G_OBJECT (pos), "position-changed",
+                         G_CALLBACK (position_changed), NULL);
+
+       g_print ("Waiting for position change signals...\n");
+       loop = g_main_loop_new (NULL, FALSE);
+       g_main_loop_run (loop);
+
+       g_main_loop_unref (loop);
+       g_object_unref (pos);
+
+       return 0;
+}
+               </programlisting>
+       </section>
+       <section id="simple-master-example">
+               <title>Master provider: simple example in C</title>
+               <para>
+                       Here is the "Hello World" for Geoclue Master. It shows one of the advantages of
+                       using the Master provider: Even most web service
+                       providers can be used as signal emitting providers (master queries them whenever
+                       network connection changes).
+               </para>
+
+               <programlisting>
+#include &lt;geoclue/geoclue-master.h&gt;
+
+static void
+position_changed (GeocluePosition      *position,
+                  GeocluePositionFields fields,
+                  int                   timestamp,
+                  double                latitude,
+                  double                longitude,
+                  double                altitude,
+                  GeoclueAccuracy      *accuracy,
+                  gpointer              userdata)
+{
+       g_print ("Position changed:\n");
+       if (fields &amp; GEOCLUE_POSITION_FIELDS_LATITUDE &amp;&amp;
+           fields &amp; GEOCLUE_POSITION_FIELDS_LONGITUDE) {
+               g_print ("\t%f, %f\n\n", latitude, longitude);
+       } else {
+               g_print ("\tLatitude and longitude not available.\n\n");
+       }
+}
+
+int main()
+{
+       GMainLoop *loop;
+       GeoclueMaster *master;
+       GeoclueMasterClient *client;
+       GeocluePosition *pos;
+       GeocluePositionFields fields;
+       double lat, lon;
+       GError *error = NULL;
+
+       g_type_init ();
+
+       / * create a MasterClient using Master * /
+       master = geoclue_master_get_default ();
+       client = geoclue_master_create_client (master, NULL, &amp;error);
+       g_object_unref (master);
+
+       if (!client) {
+               g_printerr ("Error creating GeoclueMasterClient: %s\n", error->message);
+               g_error_free (error);
+               return 1;
+       }
+
+       / * Set our requirements: We want at least city level accuracy, require signals,
+           and allow the use of network (but not e.g. GPS) * /
+       if (!geoclue_master_client_set_requirements (client,
+                                                    GEOCLUE_ACCURACY_LEVEL_LOCALITY,
+                                                    0, TRUE,
+                                                    GEOCLUE_RESOURCE_NETWORK,
+                                                    &amp;error)){
+               g_printerr ("set_requirements failed: %s", error->message);
+               g_error_free (error);
+               g_object_unref (client);
+               return 1;
+
+       }
+
+       / * Get a Position object * /
+       pos = geoclue_master_client_create_position (client, NULL);
+       if (!pos) {
+               g_printerr ("Failed to get a position object");
+               g_object_unref (client);
+               return 1;
+       }
+
+       / * call get_position. We do not know which provider actually provides
+           the answer (although we could find out using MasterClient API) * /
+       fields = geoclue_position_get_position (pos, NULL,
+                                               &amp;lat, &amp;lon, NULL,
+                                               NULL, &amp;error);
+       if (error) {
+               g_printerr ("Error in geoclue_position_get_position: %s.\n", error->message);
+               g_error_free (error);
+               error = NULL;
+       } else {
+               if (fields &amp; GEOCLUE_POSITION_FIELDS_LATITUDE &amp;&amp;
+                   fields &amp; GEOCLUE_POSITION_FIELDS_LONGITUDE) {
+                       g_print ("We're at %.3f, %.3f.\n", lat, lon);
+               }
+       }
+
+
+       g_signal_connect (G_OBJECT (pos), "position-changed",
+                         G_CALLBACK (position_changed), NULL);
+
+       g_print ("Waiting for position change signals...\n");
+       loop = g_main_loop_new (NULL, FALSE);
+       g_main_loop_run (loop);
+
+       g_main_loop_unref (loop);
+       g_object_unref (pos);
+       g_object_unref (client);
+       return 0;
+}
+               </programlisting>
+       </section>
+</chapter>
diff --git a/docs/tools/Makefile.am b/docs/tools/Makefile.am
new file mode 100755 (executable)
index 0000000..6fc0a9a
--- /dev/null
@@ -0,0 +1,2 @@
+EXTRA_DIST = spec-strip-docs.xsl spec-to-docbook.xsl
+
diff --git a/docs/tools/spec-strip-docs.xsl b/docs/tools/spec-strip-docs.xsl
new file mode 100755 (executable)
index 0000000..1025814
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version='1.0'?>
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd"
+                exclude-result-prefixes="doc">
+
+       <xsl:output method="xml"
+                   indent="yes"
+                   encoding="UTF-8"
+                   omit-xml-declaration="no"
+                   doctype-system="http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"
+                   doctype-public="-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" />
+
+       <xsl:template match="*">
+               <xsl:copy>
+                       <xsl:for-each select="@*">
+                               <xsl:if test="not(starts-with(name(.), 'doc:'))">
+                                       <xsl:copy/>
+                               </xsl:if>
+                       </xsl:for-each>
+                       <xsl:apply-templates/>
+               </xsl:copy>
+       </xsl:template>
+
+       <xsl:template match="node">
+               <node>
+                       <xsl:for-each select="@*">
+                               <xsl:if test="not(starts-with(name(.), 'xmlns'))">
+                                       <xsl:copy/>
+                               </xsl:if>
+                       </xsl:for-each>
+                       <xsl:apply-templates/>
+               </node>
+       </xsl:template>
+
+       <xsl:template match="doc:*"/>
+       <xsl:template match="text()"/>
+</xsl:stylesheet>
+
diff --git a/docs/tools/spec-to-docbook.xsl b/docs/tools/spec-to-docbook.xsl
new file mode 100755 (executable)
index 0000000..5578161
--- /dev/null
@@ -0,0 +1,473 @@
+<?xml version='1.0'?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd"
+  exclude-result-prefixes="doc">
+<!--
+     Convert D-Bus Glib xml into DocBook refentries
+     Copyright (C) 2007 William Jon McCann
+     License: GPL
+-->
+<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
+
+<xsl:template match="/node">
+  <xsl:apply-templates select="interface"/>
+</xsl:template>
+
+<xsl:template match="interface">
+
+<xsl:variable name="interface" select="@name"/>
+<xsl:variable name="basename">
+  <xsl:call-template name="interface-basename">
+    <xsl:with-param name="str" select="$interface"/>
+  </xsl:call-template>
+</xsl:variable>
+
+<refentry><xsl:attribute name="id"><xsl:value-of select="$basename"/></xsl:attribute>
+  <refmeta>
+
+    <refentrytitle role="top_of_page"><xsl:value-of select="@name"/></refentrytitle>
+  </refmeta>
+
+  <refnamediv>
+    <refname><xsl:value-of select="@name"/></refname>
+    <refpurpose><xsl:value-of select="$basename"/> interface</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv role="synopsis">
+
+    <title role="synopsis.title">Methods</title>
+    <synopsis>
+  <xsl:call-template name="methods-synopsis">
+    <xsl:with-param name="basename" select="$basename"/>
+  </xsl:call-template>
+    </synopsis>
+  </refsynopsisdiv>
+
+  <refsect1 role="signal_proto">
+
+    <title role="signal_proto.title">Signals</title>
+    <synopsis>
+  <xsl:call-template name="signals-synopsis">
+    <xsl:with-param name="basename" select="$basename"/>
+  </xsl:call-template>
+    </synopsis>
+  </refsect1>
+
+  <refsect1 role="impl_interfaces">
+
+    <title role="impl_interfaces.title">Implemented Interfaces</title>
+    <para>
+    <xsl:value-of select="$interface"/> implements
+    org.freedesktop.DBus.Introspectable,
+    org.freedesktop.DBus.Properties
+    </para>
+  </refsect1>
+
+  <refsect1 role="properties">
+    <title role="properties.title">Properties</title>
+
+    <synopsis>
+  <xsl:call-template name="properties-synopsis">
+    <xsl:with-param name="basename" select="$basename"/>
+  </xsl:call-template>
+    </synopsis>
+  </refsect1>
+
+  <refsect1 role="desc">
+    <title role="desc.title">Description</title>
+
+    <para>
+      <xsl:apply-templates select="doc:doc"/>
+    </para>
+  </refsect1>
+
+  <refsect1 role="details">
+    <title role="details.title">Details</title>
+    <xsl:call-template name="method-details">
+      <xsl:with-param name="basename" select="$basename"/>
+
+    </xsl:call-template>
+  </refsect1>
+
+  <refsect1 role="signals">
+    <title role="signals.title">Signal Details</title>
+    <xsl:call-template name="signal-details">
+      <xsl:with-param name="basename" select="$basename"/>
+    </xsl:call-template>
+  </refsect1>
+
+  <refsect1 role="property_details">
+    <title role="property_details.title">Property Details</title>
+    <xsl:call-template name="property-details">
+      <xsl:with-param name="basename" select="$basename"/>
+    </xsl:call-template>
+  </refsect1>
+
+</refentry>
+</xsl:template>
+
+
+<xsl:template name="property-doc">
+  <xsl:apply-templates select="doc:doc/doc:description"/>
+
+  <variablelist role="params">
+    <xsl:for-each select="arg">
+<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term>
+<listitem><simpara><xsl:value-of select="doc:doc/doc:summary"/></simpara></listitem>
+</varlistentry>
+    </xsl:for-each>
+  </variablelist>
+
+  <xsl:apply-templates select="doc:doc/doc:since"/>
+  <xsl:apply-templates select="doc:doc/doc:deprecated"/>
+  <xsl:apply-templates select="doc:doc/doc:permission"/>
+  <xsl:apply-templates select="doc:doc/doc:seealso"/>
+</xsl:template>
+
+
+<xsl:template name="property-details">
+  <xsl:param name="basename"/>
+  <xsl:variable name="longest">
+
+    <xsl:call-template name="find-longest">
+      <xsl:with-param name="set" select="@name"/>
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:for-each select="property">
+  <refsect2>
+    <title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>:<xsl:value-of select="@name"/></xsl:attribute></anchor>The "<xsl:value-of select="@name"/>" property</title>
+
+<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$basename"/></secondary></indexterm>
+<programlisting>'<xsl:value-of select="@name"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="2"/></xsl:call-template>
+<xsl:call-template name="property-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/></xsl:call-template></programlisting>
+
+  <xsl:call-template name="property-doc"/>
+
+  </refsect2>
+  </xsl:for-each>
+</xsl:template>
+
+<xsl:template name="signal-doc">
+  <xsl:apply-templates select="doc:doc/doc:description"/>
+
+  <variablelist role="params">
+    <xsl:for-each select="arg">
+<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term>
+<listitem><simpara><xsl:value-of select="doc:doc/doc:summary"/></simpara></listitem>
+</varlistentry>
+    </xsl:for-each>
+  </variablelist>
+
+  <xsl:apply-templates select="doc:doc/doc:since"/>
+  <xsl:apply-templates select="doc:doc/doc:deprecated"/>
+
+  <xsl:apply-templates select="doc:doc/doc:permission"/>
+  <xsl:apply-templates select="doc:doc/doc:seealso"/>
+</xsl:template>
+
+<xsl:template name="signal-details">
+  <xsl:param name="basename"/>
+  <xsl:variable name="longest">
+    <xsl:call-template name="find-longest">
+      <xsl:with-param name="set" select="@name"/>
+    </xsl:call-template>
+
+  </xsl:variable>
+  <xsl:for-each select="signal">
+  <refsect2>
+    <title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>::<xsl:value-of select="@name"/></xsl:attribute></anchor>The <xsl:value-of select="@name"/> signal</title>
+<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$basename"/></secondary></indexterm>
+<programlisting><xsl:value-of select="@name"/> (<xsl:call-template name="signal-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/><xsl:with-param name="prefix" select="."/></xsl:call-template>)</programlisting>
+
+  <xsl:call-template name="signal-doc"/>
+
+  </refsect2>
+  </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="doc:code">
+<programlisting>
+<xsl:apply-templates />
+</programlisting>
+</xsl:template>
+
+<xsl:template match="doc:summary">
+
+<!-- by default don't display -->
+</xsl:template>
+
+<xsl:template match="doc:example">
+<informalexample>
+<xsl:apply-templates />
+</informalexample>
+</xsl:template>
+
+<xsl:template match="doc:para">
+<para>
+<xsl:apply-templates />
+</para>
+</xsl:template>
+
+<xsl:template match="doc:description">
+<xsl:apply-templates />
+
+</xsl:template>
+
+<xsl:template match="doc:since">
+<para role="since">Since <xsl:value-of select="@version"/>
+</para>
+</xsl:template>
+
+<xsl:template match="doc:deprecated">
+  <xsl:variable name="name" select="../../@name"/>
+  <xsl:variable name="parent">
+    <xsl:call-template name="interface-basename">
+      <xsl:with-param name="str" select="../../../@name"/>/>
+    </xsl:call-template>
+
+  </xsl:variable>
+
+  <xsl:variable name="type" select="name(../..)"/>
+
+  <para role="deprecated">
+  <warning><para><literal><xsl:value-of select="$name"/></literal> is deprecated since version <xsl:value-of select="@version"/> and should not be used in newly-written code. Use
+
+  <xsl:variable name="to">
+  <xsl:choose>
+    <xsl:when test="contains($type,'property')">
+
+      <xsl:value-of select="$parent"/>:<xsl:value-of select="@instead"/>
+    </xsl:when>
+    <xsl:when test="contains($type,'signal')">
+      <xsl:value-of select="$parent"/>::<xsl:value-of select="@instead"/>
+    </xsl:when>
+    <xsl:when test="contains($type,'method')">
+      <xsl:value-of select="$parent"/>.<xsl:value-of select="@instead"/>
+
+    </xsl:when>
+    <xsl:when test="contains($type,'interface')">
+      <xsl:value-of select="@instead"/>
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:value-of select="@instead"/>
+    </xsl:otherwise>
+  </xsl:choose>
+  </xsl:variable>
+
+  <xsl:call-template name="create-link">
+    <xsl:with-param name="type" select="$type"/>
+    <xsl:with-param name="to" select="$to"/>
+    <xsl:with-param name="val" select="@instead"/>
+  </xsl:call-template>
+instead.</para></warning>
+</para>
+</xsl:template>
+
+<xsl:template match="doc:permission">
+
+<para role="permission">
+<xsl:apply-templates />
+</para>
+</xsl:template>
+
+<xsl:template match="doc:seealso">
+<para>
+See also:
+<xsl:apply-templates />
+
+</para>
+</xsl:template>
+
+<xsl:template name="create-link">
+  <xsl:param name="type"/>
+  <xsl:param name="to"/>
+
+  <xsl:param name="val"/>
+
+  <xsl:choose>
+    <xsl:when test="contains($type,'property')">
+      <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><literal><xsl:value-of select="$val"/></literal></link>
+    </xsl:when>
+    <xsl:when test="contains($type,'signal')">
+      <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><literal><xsl:value-of select="$val"/></literal></link>
+    </xsl:when>
+
+    <xsl:when test="contains($type,'method')">
+      <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><function><xsl:value-of select="$val"/></function></link>
+    </xsl:when>
+    <xsl:when test="contains($type,'interface')">
+      <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><xsl:value-of select="$val"/></link>
+    </xsl:when>
+  </xsl:choose>
+</xsl:template>
+
+<xsl:template match="doc:ref">
+
+  <xsl:call-template name="create-link">
+    <xsl:with-param name="type" select="@type"/>
+    <xsl:with-param name="to" select="@to"/>
+    <xsl:with-param name="val" select="."/>
+  </xsl:call-template>
+</xsl:template>
+
+<xsl:template name="method-doc">
+  <xsl:apply-templates select="doc:doc/doc:description"/>
+
+  <variablelist role="params">
+
+    <xsl:for-each select="arg">
+<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term>
+<listitem>
+<para><xsl:value-of select="doc:doc/doc:summary"/></para>
+  <xsl:apply-templates select="doc:doc/doc:description"/>
+</listitem>
+</varlistentry>
+    </xsl:for-each>
+  </variablelist>
+
+  <xsl:apply-templates select="doc:doc/doc:since"/>
+
+  <xsl:apply-templates select="doc:doc/doc:deprecated"/>
+  <xsl:apply-templates select="doc:doc/doc:permission"/>
+  <xsl:apply-templates select="doc:doc/doc:seealso"/>
+</xsl:template>
+
+<xsl:template name="method-details">
+  <xsl:param name="basename"/>
+  <xsl:variable name="longest">
+    <xsl:call-template name="find-longest">
+      <xsl:with-param name="set" select="@name"/>
+
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:for-each select="method">
+    <refsect2>
+    <title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>.<xsl:value-of select="@name"/></xsl:attribute></anchor><xsl:value-of select="@name"/> ()</title>
+<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$basename"/></secondary></indexterm>
+<programlisting><xsl:value-of select="@name"/> (<xsl:call-template name="method-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/><xsl:with-param name="prefix" select="."/></xsl:call-template>)</programlisting>
+
+    <xsl:call-template name="method-doc"/>
+    </refsect2>
+
+  </xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="properties-synopsis">
+  <xsl:param name="basename"/>
+  <xsl:variable name="longest">
+    <xsl:call-template name="find-longest">
+
+      <xsl:with-param name="set" select="property/@name"/>
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:for-each select="property">
+<link><xsl:attribute name="linkend"><xsl:value-of select="$basename"/>:<xsl:value-of select="@name"/></xsl:attribute>'<xsl:value-of select="@name"/>'</link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template> <xsl:call-template name="property-args"><xsl:with-param name="indent" select="$longest + 2"/></xsl:call-template>
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="signals-synopsis">
+  <xsl:param name="basename"/>
+  <xsl:variable name="longest">
+    <xsl:call-template name="find-longest">
+      <xsl:with-param name="set" select="signal/@name"/>
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:for-each select="signal">
+<link><xsl:attribute name="linkend"><xsl:value-of select="$basename"/>::<xsl:value-of select="@name"/></xsl:attribute><xsl:value-of select="@name"/></link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template>(<xsl:call-template name="signal-args"><xsl:with-param name="indent" select="$longest + 2"/><xsl:with-param name="prefix" select="signal"/></xsl:call-template>)
+
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="methods-synopsis">
+  <xsl:param name="basename"/>
+  <xsl:variable name="longest">
+    <xsl:call-template name="find-longest">
+      <xsl:with-param name="set" select="method/@name"/>
+    </xsl:call-template>
+  </xsl:variable>
+
+  <xsl:for-each select="method">
+<link><xsl:attribute name="linkend"><xsl:value-of select="$basename"/>.<xsl:value-of select="@name"/></xsl:attribute><xsl:value-of select="@name"/></link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template>(<xsl:call-template name="method-args"><xsl:with-param name="indent" select="$longest + 2"/><xsl:with-param name="prefix" select="method"/></xsl:call-template>)
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="method-args"><xsl:param name="indent"/><xsl:param name="prefix"/><xsl:variable name="longest"><xsl:call-template name="find-longest"><xsl:with-param name="set" select="$prefix/arg/@type"/></xsl:call-template></xsl:variable><xsl:for-each select="arg"><xsl:value-of select="@direction"/>
+<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="4 - string-length(@direction)"/></xsl:call-template>'<xsl:value-of select="@type"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@type) + 1"/></xsl:call-template>
+<xsl:value-of select="@name"/><xsl:if test="not(position() = last())">,
+<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$indent"/></xsl:call-template></xsl:if>
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="signal-args"><xsl:param name="indent"/><xsl:param name="prefix"/><xsl:variable name="longest"><xsl:call-template name="find-longest"><xsl:with-param name="set" select="$prefix/arg/@type"/></xsl:call-template></xsl:variable><xsl:for-each select="arg">'<xsl:value-of select="@type"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@type) + 1"/></xsl:call-template>
+<xsl:value-of select="@name"/><xsl:if test="not(position() = last())">,
+<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$indent"/></xsl:call-template></xsl:if>
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="property-args"><xsl:param name="indent"/>
+<xsl:value-of select="@access"/><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="9 - string-length(@access) + 1"/></xsl:call-template>'<xsl:value-of select="@type"/>'
+</xsl:template>
+
+
+<xsl:template name="pad-spaces">
+  <xsl:param name="width"/>
+  <xsl:variable name="spaces" xml:space="preserve">                                                                        </xsl:variable>
+  <xsl:value-of select="substring($spaces,1,$width)"/>
+</xsl:template>
+
+
+<xsl:template name="find-longest">
+  <xsl:param name="set"/>
+  <xsl:param name="index" select="1"/>
+  <xsl:param name="longest" select="0"/>
+
+  <xsl:choose>
+    <xsl:when test="$index > count($set)">
+      <!--finished looking-->
+      <xsl:value-of select="$longest"/>
+    </xsl:when>
+    <xsl:when test="string-length($set[$index])>$longest">
+      <!--found new longest-->
+      <xsl:call-template name="find-longest">
+
+        <xsl:with-param name="set" select="$set"/>
+        <xsl:with-param name="index" select="$index + 1"/>
+        <xsl:with-param name="longest" select="string-length($set[$index])"/>
+      </xsl:call-template>
+    </xsl:when>
+    <xsl:otherwise>
+      <!--this isn't any longer-->
+      <xsl:call-template name="find-longest">
+        <xsl:with-param name="set" select="$set"/>
+
+        <xsl:with-param name="index" select="$index + 1"/>
+        <xsl:with-param name="longest" select="$longest"/>
+      </xsl:call-template>
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+
+<xsl:template name="interface-basename">
+  <xsl:param name="str"/>
+  <xsl:choose>
+
+    <xsl:when test="contains($str,'.')">
+      <xsl:call-template name="interface-basename">
+       <xsl:with-param name="str" select="substring-after($str,'.')"/>
+      </xsl:call-template>
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:value-of select="$str"/>
+    </xsl:otherwise>
+  </xsl:choose>
+
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/example/Makefile.am b/example/Makefile.am
new file mode 100644 (file)
index 0000000..097cfa8
--- /dev/null
@@ -0,0 +1,23 @@
+noinst_PROGRAMS = \
+       position-example \
+       position-async-example \
+       master-example \
+       master-pos-example \
+       address-example \
+       geocode-example \
+       revgeocode-example \
+       common-example
+
+position_example_SOURCES = position-example.c
+position_async_example_SOURCES = position-async-example.c
+master_example_SOURCES = master-example.c
+master_pos_example_SOURCES = master-pos-example.c
+address_example_SOURCES = address-example.c
+geocode_example_SOURCES = geocode-example.c
+revgeocode_example_SOURCES = revgeocode-example.c
+common_example_SOURCES = common-example.c
+
+AM_CFLAGS = $(GEOCLUE_CFLAGS)
+LDADD = \
+       $(GEOCLUE_LIBS) \
+    $(top_builddir)/geoclue/libgeoclue.la
diff --git a/example/address-example.c b/example/address-example.c
new file mode 100755 (executable)
index 0000000..68946fe
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Geoclue
+ * address-example.c - Example using the Address client API
+ *
+ * Author: Jussi Kukkonen <jku@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <glib.h>
+#include <geoclue/geoclue-address.h>
+
+/* GHFunc, use with g_hash_table_foreach */
+static void
+print_address_key_and_value (char *key, char *value, gpointer user_data)
+{
+       g_print ("    %s: %s\n", key, value);
+}
+
+static GHashTable *
+parse_options (int    argc,
+               char **argv)
+{
+        GHashTable *options;
+        int i;
+
+        options = g_hash_table_new (g_str_hash, g_str_equal);
+        for (i = 2; i < argc; i += 2) {
+                g_hash_table_insert (options, argv[i], argv[i + 1]);
+        }
+
+        return options;
+}
+
+int main (int argc, char** argv)
+{
+       gchar *service, *path;
+       GeoclueAddress *address = NULL;
+       int timestamp;
+       GHashTable *details = NULL;
+       GeoclueAccuracy *accuracy = NULL;
+       GeoclueAccuracyLevel level;
+       GError *error = NULL;
+
+       g_type_init();
+
+       if (argc < 2 || argc % 2 != 0) {
+               g_printerr ("Usage:\n  address-example <provider_name> [option value]\n");
+               return 1;
+       }
+       g_print ("Using provider '%s'\n", argv[1]);
+       service = g_strdup_printf ("org.freedesktop.Geoclue.Providers.%s", argv[1]);
+       path = g_strdup_printf ("/org/freedesktop/Geoclue/Providers/%s", argv[1]);
+
+       /* Create new GeoclueAddress */
+       address = geoclue_address_new (service, path);
+       g_free (service);
+       g_free (path);
+       if (address == NULL) {
+               g_printerr ("Error while creating GeoclueAddress object.\n");
+               return 1;
+       }
+
+        /* Set options */
+        if (argc > 2) {
+                GHashTable *options;
+
+                options = parse_options (argc, argv);
+                if (!geoclue_provider_set_options (GEOCLUE_PROVIDER (address), options, &error)) {
+                        g_printerr ("Error setting options: %s\n",
+                                    error->message);
+                        g_error_free (error);
+                        error = NULL;
+                }
+                g_hash_table_destroy (options);
+        }
+
+       /* Query current address */
+       if (!geoclue_address_get_address (address, &timestamp,
+                                             &details, &accuracy,
+                                             &error)) {
+               g_printerr ("Error getting address: %s\n", error->message);
+               g_error_free (error);
+               g_object_unref (address);
+               return 1;
+       }
+       geoclue_accuracy_get_details (accuracy, &level, NULL, NULL);
+
+       /* address data is in GHashTable details, need to turn that into a string */
+       g_print ("Current address: (accuracy level %d)\n", level);
+       g_hash_table_foreach (details, (GHFunc)print_address_key_and_value, NULL);
+
+       g_hash_table_destroy (details);
+       geoclue_accuracy_free (accuracy);
+       g_object_unref (address);
+
+       return 0;
+}
diff --git a/example/common-example.c b/example/common-example.c
new file mode 100755 (executable)
index 0000000..aec1ede
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Geoclue
+ * common-example.c - Example using the Geoclue common client API
+ *
+ * Author: Jussi Kukkonen <jku@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <glib.h>
+#include <geoclue/geoclue-position.h>
+
+int main (int argc, char** argv)
+{
+       gchar *service, *path;
+       GeocluePosition *pos = NULL;
+       gchar *name = NULL;
+       gchar *desc = NULL;
+       GeoclueStatus status;
+        GHashTable *options;
+       GError *error = NULL;
+
+       g_type_init();
+
+       if (argc != 2) {
+               g_printerr ("Usage:\n  common-example <provider_name>\n");
+               return 1;
+       }
+       g_print ("Using provider '%s'\n", argv[1]);
+       service = g_strdup_printf ("org.freedesktop.Geoclue.Providers.%s", argv[1]);
+       path = g_strdup_printf ("/org/freedesktop/Geoclue/Providers/%s", argv[1]);
+
+
+       /* Create new GeoclueCommon */
+       pos = geoclue_position_new (service, path);
+       g_free (service);
+       g_free (path);
+       if (pos == NULL) {
+               g_printerr ("Error while creating GeocluePosition object.\n");
+               return 1;
+       }
+
+
+       options = g_hash_table_new (g_str_hash, g_str_equal);
+        g_hash_table_insert (options, "GPSProvider", "Gypsy");
+        g_hash_table_insert (options, "PlaySong", "MGMT-Kids.mp3");
+
+        if (!geoclue_provider_set_options (GEOCLUE_PROVIDER (pos), options, &error)) {
+                g_printerr ("Error setting options: %s\n\n", error->message);
+                g_error_free (error);
+                error = NULL;
+        } else {
+                g_print ("Options set correctly\n\n");
+        }
+        g_hash_table_destroy (options);
+
+       if (!geoclue_provider_get_provider_info (GEOCLUE_PROVIDER (pos),
+                                                &name, &desc,
+                                                &error)) {
+               g_printerr ("Error getting provider info: %s\n\n", error->message);
+               g_error_free (error);
+               error = NULL;
+       } else {
+               g_print ("Provider info:\n");
+               g_print ("\tName: %s\n", name);
+               g_print ("\tDescription: %s\n\n", desc);
+               g_free (name);
+               g_free (desc);
+       }
+
+       if (!geoclue_provider_get_status (GEOCLUE_PROVIDER (pos), &status, &error)) {
+               g_printerr ("Error getting status: %s\n\n", error->message);
+               g_error_free (error);
+               error = NULL;
+       } else {
+               switch (status) {
+                case GEOCLUE_STATUS_ERROR:
+                        g_print ("Provider status: error\n");
+                        break;
+                case GEOCLUE_STATUS_UNAVAILABLE:
+                        g_print ("Provider status: unavailable\n");
+                        break;
+                case GEOCLUE_STATUS_ACQUIRING:
+                        g_print ("Provider status: acquiring\n");
+                        break;
+                case GEOCLUE_STATUS_AVAILABLE:
+                        g_print ("Provider status: available\n");
+                        break;
+               }
+       }
+
+       g_object_unref (pos);
+
+       return 0;
+}
diff --git a/example/geocode-example.c b/example/geocode-example.c
new file mode 100755 (executable)
index 0000000..322a2bf
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Geoclue
+ * geocode-example.c - Example using the Geocode client API
+ *
+ * Provider options are not used in this sample. See other files for
+ * examples on that.
+ *
+ * Author: Jussi Kukkonen <jku@openedhand.com>
+ * Copyright 2007, 2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <glib.h>
+#include <geoclue/geoclue-geocode.h>
+
+int main (int argc, char** argv)
+{
+       gchar *service, *path;
+       GeoclueGeocode *geocoder = NULL;
+       GeocluePositionFields fields;
+       double lat, lon;
+       GeoclueAccuracy *accuracy = NULL;
+       GError *error = NULL;
+
+       g_type_init();
+
+       if (argc < 2) {
+               g_printerr ("Usage:\n  geocode-example <provider_name> [\"freeform address\"]\n\n"
+                           "  If freeform address is not given, a hard coded address hash "
+                           "will be used.\n");
+               return 1;
+       }
+
+       g_print ("Using provider '%s'\n", argv[1]);
+       service = g_strdup_printf ("org.freedesktop.Geoclue.Providers.%s", argv[1]);
+       path = g_strdup_printf ("/org/freedesktop/Geoclue/Providers/%s", argv[1]);
+       /* Create new GeoclueGeocode */
+       geocoder = geoclue_geocode_new (service, path);
+       g_free (service);
+       g_free (path);
+       if (geocoder == NULL) {
+               g_printerr ("Error while creating GeoclueGeocode object.\n");
+               return 1;
+       }
+
+       if (argc == 2) {
+               GHashTable *address = NULL;
+               /* Address we'd like geocoded */
+               address = geoclue_address_details_new();
+               geoclue_address_details_insert (address, "locality", "Helsinki");
+               geoclue_address_details_insert (address, "postalcode", "00330");
+               geoclue_address_details_insert (address, "countrycode", "FI");
+               geoclue_address_details_insert (address, "street", "Solnantie 24");
+
+               /* Geocode. We're not interested in altitude
+                  this time, so leave it NULL. */
+               fields = geoclue_geocode_address_to_position (geocoder, address,
+                                                             &lat, &lon, NULL,
+                                                             &accuracy, &error);
+               g_hash_table_destroy (address);
+       } else {
+               char *str;
+               str = g_strjoinv (" ", &argv[2]);
+               fields = geoclue_geocode_freeform_address_to_position
+                               (geocoder, str,
+                                &lat, &lon, NULL,
+                                &accuracy, &error);
+               g_free (str);
+       }
+
+       if (error) {
+               g_printerr ("Error while geocoding: %s\n", error->message);
+               g_error_free (error);
+               g_object_unref (geocoder);
+
+               return 1;
+       }
+
+           /* Print out coordinates if they are valid */
+       if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
+           fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) {
+
+               GeoclueAccuracyLevel level;
+
+               geoclue_accuracy_get_details (accuracy, &level, NULL, NULL);
+               g_print ("Geocoded position (accuracy level %d): \n", level);
+               g_print ("\t%f, %f\n", lat, lon);
+
+       } else {
+               g_print ("Latitude and longitude not available.\n");
+       }
+
+       geoclue_accuracy_free (accuracy);
+       g_object_unref (geocoder);
+       return 0;
+
+}
diff --git a/example/master-example.c b/example/master-example.c
new file mode 100755 (executable)
index 0000000..c10192f
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Geoclue
+ * master-example.c - Example using the Master client API
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* This example uses geoclue master to get approximate position
+ * and address signals. Following params are
+ * given to geoclue_master_client_set_requirements():
+ *     min_accuracy = GEOCLUE_ACCURACY_LEVEL_LOCALITY
+ *             Locality means a city or a town. Expect coordinates
+ *             to routinely have 10-20 km error.
+ *     min_time = 0
+ *             No limit on frequency of position-changed signals
+ *             (this is not actually implemented yet)
+ *     require_updates = TRUE
+ *             We want position-changed and address-changed signals
+ *     allowed_resources = GEOCLUE_RESOURCE_NETWORK
+ *             Web services may be used but e.g. GPS is off limits
+ *
+ * To ensure at least one working provider for your testing, visit
+ * hostip.info and define your IPs location if it's not set or is
+ * marked as "guessed"
+ *
+ * */
+
+#include <geoclue/geoclue-master.h>
+#include <geoclue/geoclue-address.h>
+#include <geoclue/geoclue-position.h>
+
+/* Provider methods */
+static void
+provider_changed_cb (GeoclueMasterClient *client,
+                     char *name,
+                     char *description,
+                     char *service,
+                     char *path,
+                     gpointer userdata)
+{
+       g_print ("%s provider changed: %s\n", (char *)userdata, name);
+}
+
+
+/* Address methods */
+static void
+print_address_key_and_value (char *key, char *value, gpointer user_data)
+{
+       g_print ("\t%s: %s\n", key, value);
+}
+
+static void
+address_changed_cb (GeoclueAddress  *address,
+                   int              timestamp,
+                   GHashTable      *details,
+                   GeoclueAccuracy *accuracy)
+{
+       GeoclueAccuracyLevel level;
+       geoclue_accuracy_get_details (accuracy, &level, NULL, NULL);
+       g_print ("New address (accuracy level %d):\n", level);
+       g_hash_table_foreach (details, (GHFunc)print_address_key_and_value, NULL);
+       g_print ("\n");
+}
+
+static GeoclueAddress *
+init_address (GeoclueMasterClient *client)
+{
+       GError *error = NULL;
+       GeoclueAddress *address;
+       GHashTable *details = NULL;
+       GeoclueAccuracyLevel level;
+       GeoclueAccuracy *accuracy = NULL;
+       int timestamp = 0;
+
+       /* create the object and connect to signal */
+       address = geoclue_master_client_create_address (client, &error);
+       if (!address) {
+               g_warning ("Creating GeoclueAddress failed: %s", error->message);
+               g_error_free (error);
+               return NULL;
+       }
+       g_signal_connect (G_OBJECT (address), "address-changed",
+                         G_CALLBACK (address_changed_cb), NULL);
+
+       /* print initial address */
+       if (!geoclue_address_get_address (address, &timestamp,
+                                         &details, &accuracy,
+                                         &error)) {
+               g_printerr ("Error getting address: %s\n", error->message);
+               g_error_free (error);
+       } else {
+               geoclue_accuracy_get_details (accuracy, &level, NULL, NULL);
+               g_print ("Current address: (accuracy level %d):\n", level);
+               g_hash_table_foreach (details, (GHFunc)print_address_key_and_value, NULL);
+               g_print ("\n");
+               g_hash_table_destroy (details);
+               geoclue_accuracy_free (accuracy);
+       }
+       return address;
+}
+
+
+/* Position methods */
+static void
+position_changed_cb (GeocluePosition      *position,
+                    GeocluePositionFields fields,
+                    int                   timestamp,
+                    double                latitude,
+                    double                longitude,
+                    double                altitude,
+                    GeoclueAccuracy      *accuracy,
+                    gpointer              userdata)
+{
+       GeoclueAccuracyLevel level;
+
+       geoclue_accuracy_get_details (accuracy, &level, NULL, NULL);
+       g_print ("New position (accuracy level %d):\n", level);
+
+       if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
+           fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) {
+               g_print ("\t%f, %f\n\n", latitude, longitude);
+       } else {
+               g_print ("\nlatitude and longitude not valid.\n");
+       }
+}
+
+static GeocluePosition *
+init_position (GeoclueMasterClient *client)
+{
+       GeocluePosition *position;
+       GError *error = NULL;
+       GeocluePositionFields fields;
+       double lat = 0.0, lon = 0.0;
+       GeoclueAccuracy *accuracy;
+
+       position = geoclue_master_client_create_position (client, &error);
+       if (!position) {
+               g_warning ("Creating GeocluePosition failed: %s", error->message);
+               g_error_free (error);
+               return NULL;
+       }
+
+       g_signal_connect (G_OBJECT (position), "position-changed",
+                         G_CALLBACK (position_changed_cb), NULL);
+
+       /*print initial position */
+       fields = geoclue_position_get_position (position, NULL,
+                                               &lat, &lon, NULL,
+                                               &accuracy, &error);
+       if (error != NULL) {
+               g_warning ("%s", error->message);
+               g_error_free (error);
+       } else {
+               GeoclueAccuracyLevel level;
+
+               geoclue_accuracy_get_details (accuracy, &level, NULL, NULL);
+               g_print ("New position (accuracy level %d):\n", level);
+
+               if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
+                   fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) {
+                       g_print ("\t%f, %f\n\n", lat, lon);
+               } else {
+                       g_print ("\nlatitude and longitude not valid.\n");
+               }
+
+               geoclue_accuracy_free (accuracy);
+       }
+
+       return position;
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+       GeoclueMaster *master;
+       GeoclueMasterClient *client;
+       GeocluePosition *pos;
+       GeoclueAddress *addr;
+       GMainLoop *mainloop;
+
+       g_type_init ();
+
+       master = geoclue_master_get_default ();
+       client = geoclue_master_create_client (master, NULL, NULL);
+       g_object_unref (master);
+
+       g_signal_connect (G_OBJECT (client), "address-provider-changed",
+                         G_CALLBACK (provider_changed_cb), "Address");
+       g_signal_connect (G_OBJECT (client), "position-provider-changed",
+                         G_CALLBACK (provider_changed_cb), "Position");
+
+       if (!geoclue_master_client_set_requirements (client,
+                                                    GEOCLUE_ACCURACY_LEVEL_LOCALITY,
+                                                    0,
+                                                    TRUE,
+                                                    GEOCLUE_RESOURCE_NETWORK,
+                                                    NULL)){
+               g_printerr ("set_requirements failed");
+               g_object_unref (client);
+               return 1;
+       }
+
+       addr = init_address (client);
+       pos = init_position (client);
+
+       mainloop = g_main_loop_new (NULL, FALSE);
+       g_main_loop_run (mainloop);
+
+       g_main_loop_unref (mainloop);
+       g_object_unref (pos);
+       g_object_unref (addr);
+       g_object_unref (client);
+
+       return 0;
+}
diff --git a/example/master-pos-example.c b/example/master-pos-example.c
new file mode 100644 (file)
index 0000000..94fa84a
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Geoclue
+ * master-example.c - Example using the Master client API
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ *          Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2008 by Garmin Ltd. or its subsidiaries
+ *           2008 OpenedHand Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+/* This example shows typical GPS-like usage. Following params are
+ * given to geoclue_master_client_set_requirements():
+ *     min_accuracy = GEOCLUE_ACCURACY_LEVEL_DETAILED
+ *             We require the highest level of accuracy
+ *     min_time = 0
+ *             No limit on frequency of position-changed signals
+ *             (this is not actually implemented yet)
+ *     require_updates = TRUE
+ *             We need position-changed signals
+ *     allowed_resources = GEOCLUE_RESOURCE_ALL
+ *             Any available resource can be used
+ *
+ * Geoclue master will try to select a suitable provider based on these
+ * requirements -- currently only Gypsy and Gpsd providers fulfill
+ * the above requiremens. Gpsd-provider should work out-of-the-box as
+ * long as gpsd is running in the default port. Gypsy provider requires
+ * that you set device name in the options: see README for details.
+ *
+ */
+
+#include <string.h>
+
+#include <geoclue/geoclue-master.h>
+#include <geoclue/geoclue-position.h>
+
+static void
+provider_changed_cb (GeoclueMasterClient *client,
+                     char *iface,
+                     char *name,
+                     char *description,
+                     gpointer userdata)
+{
+       if (strlen (name) == 0) {
+               g_print ("No provider available\n");
+       } else {
+               g_print ("now using provider: %s\n", name);
+       }
+}
+
+static void
+position_changed_cb (GeocluePosition      *position,
+                    GeocluePositionFields fields,
+                    int                   timestamp,
+                    double                latitude,
+                    double                longitude,
+                    double                altitude,
+                    GeoclueAccuracy      *accuracy,
+                    gpointer              userdata)
+{
+       if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
+           fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) {
+               GeoclueAccuracyLevel level;
+
+               geoclue_accuracy_get_details (accuracy, &level, NULL, NULL);
+               g_print ("got position (accuracy level %d):\n", level);
+               g_print ("\t%f, %f\n", latitude, longitude);
+
+       } else {
+               g_print ("position emitted, but latitude and longitude are not valid.\n");
+       }
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+       GError *error = NULL;
+       GMainLoop *mainloop;
+       GeoclueMaster *master;
+       GeoclueMasterClient *client;
+       GeocluePosition *position;
+
+       g_type_init ();
+
+       master = geoclue_master_get_default ();
+       client = geoclue_master_create_client (master, NULL, NULL);
+       g_object_unref (master);
+
+       g_signal_connect (G_OBJECT (client), "position-provider-changed",
+                         G_CALLBACK (provider_changed_cb), NULL);
+
+       /* We want provider that has detailed accuracy and emits signals.
+        * The provider is allowed to use any resources available. */
+       if (!geoclue_master_client_set_requirements (client,
+                                                    GEOCLUE_ACCURACY_LEVEL_DETAILED,
+                                                    0, TRUE,
+                                                    GEOCLUE_RESOURCE_ALL,
+                                                    NULL)){
+               g_printerr ("Setting requirements failed");
+               g_object_unref (client);
+               return 1;
+       }
+
+       position = geoclue_master_client_create_position (client, &error);
+       if (!position) {
+               g_warning ("Creating GeocluePosition failed: %s", error->message);
+               g_error_free (error);
+               g_object_unref (client);
+               return 1;
+       }
+
+       g_signal_connect (G_OBJECT (position), "position-changed",
+                         G_CALLBACK (position_changed_cb), NULL);
+
+       mainloop = g_main_loop_new (NULL, FALSE);
+       g_main_loop_run (mainloop);
+
+       g_main_loop_unref (mainloop);
+       g_object_unref (client);
+       g_object_unref (position);
+
+       return 0;
+}
diff --git a/example/position-async-example.c b/example/position-async-example.c
new file mode 100755 (executable)
index 0000000..50ffbcf
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Geoclue
+ * position-example.c - Example using the Position client API
+ *                      (asynchronous method call)
+ *
+ * Author: Jussi Kukkonen <jku@openedhand.com>
+ * Copyright 2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* NOTE: provider options are not used in this example  */
+
+#include <glib.h>
+#include <geoclue/geoclue-position.h>
+
+static void
+position_callback (GeocluePosition      *pos,
+                  GeocluePositionFields fields,
+                  int                   timestamp,
+                  double                latitude,
+                  double                longitude,
+                  double                altitude,
+                  GeoclueAccuracy      *accuracy,
+                  GError               *error,
+                  gpointer              userdata)
+{
+       if (error) {
+               g_printerr ("Error getting position: %s\n", error->message);
+               g_error_free (error);
+       } else {
+               if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
+                   fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) {
+                       GeoclueAccuracyLevel level;
+
+                       geoclue_accuracy_get_details (accuracy, &level, NULL, NULL);
+                       g_print ("Current position (accuracy %d):\n", level);
+                       g_print ("\t%f, %f\n", latitude, longitude);
+               } else {
+                       g_print ("Current position not available.\n");
+               }
+       }
+       g_main_loop_quit ((GMainLoop *)userdata);
+}
+
+int main (int argc, char** argv)
+{
+       gchar *service, *path;
+       GMainLoop *mainloop;
+       GeocluePosition *pos = NULL;
+
+       if (argc < 2 || argc % 2 != 0) {
+               g_printerr ("Usage:\n  position-example <provider_name>");
+               return 1;
+       }
+
+       g_type_init();
+       mainloop = g_main_loop_new (NULL, FALSE);
+
+       g_print ("Using provider '%s'\n", argv[1]);
+       service = g_strdup_printf ("org.freedesktop.Geoclue.Providers.%s", argv[1]);
+       path = g_strdup_printf ("/org/freedesktop/Geoclue/Providers/%s", argv[1]);
+
+
+       pos = geoclue_position_new (service, path);
+       g_free (service);
+       g_free (path);
+       if (pos == NULL) {
+               g_printerr ("Error while creating GeocluePosition object.\n");
+               return 1;
+       }
+
+       geoclue_position_get_position_async (pos,
+                                            (GeocluePositionCallback) position_callback,
+                                            mainloop);
+       g_print ("Asynchronous call made, going to main loop now...\n");
+       g_main_loop_run (mainloop);
+
+       g_main_loop_unref (mainloop);
+       g_object_unref (pos);
+
+       return 0;
+}
diff --git a/example/position-example.c b/example/position-example.c
new file mode 100644 (file)
index 0000000..a2b7d2e
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Geoclue
+ * position-example.c - Example using the Position client API
+ *
+ * Author: Jussi Kukkonen <jku@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <glib.h>
+#include <geoclue/geoclue-position.h>
+
+static void
+position_changed_cb (GeocluePosition      *position,
+                    GeocluePositionFields fields,
+                    int                   timestamp,
+                    double                latitude,
+                    double                longitude,
+                    double                altitude,
+                    GeoclueAccuracy      *accuracy,
+                    gpointer              userdata)
+{
+       if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
+           fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) {
+
+               GeoclueAccuracyLevel level;
+               double horiz_acc;
+
+               geoclue_accuracy_get_details (accuracy, &level, &horiz_acc, NULL);
+               g_print ("Current position:\n");
+               g_print ("\t%f, %f\n", latitude, longitude);
+               g_print ("\tAccuracy level %d (%.0f meters)\n", level, horiz_acc);
+
+       } else {
+               g_print ("Latitude and longitude not available.\n");
+       }
+}
+
+static GHashTable *
+parse_options (int    argc,
+               char **argv)
+{
+        GHashTable *options;
+        int i;
+
+        options = g_hash_table_new (g_str_hash, g_str_equal);
+        for (i = 2; i < argc; i += 2) {
+                g_hash_table_insert (options, argv[i], argv[i + 1]);
+        }
+
+        return options;
+}
+
+int main (int argc, char** argv)
+{
+       gchar *service, *path;
+       GeocluePosition *pos = NULL;
+       GeocluePositionFields fields;
+       int timestamp;
+       double lat, lon;
+       GeoclueAccuracy *accuracy = NULL;
+       GMainLoop *mainloop;
+       GError *error = NULL;
+
+       g_type_init();
+
+       if (argc < 2 || argc % 2 != 0) {
+               g_printerr ("Usage:\n  position-example <provider_name> [option,value]\n");
+               return 1;
+       }
+
+       g_print ("Using provider '%s'\n", argv[1]);
+       service = g_strdup_printf ("org.freedesktop.Geoclue.Providers.%s", argv[1]);
+       path = g_strdup_printf ("/org/freedesktop/Geoclue/Providers/%s", argv[1]);
+
+       mainloop = g_main_loop_new (NULL, FALSE);
+
+       /* Create new GeocluePosition */
+       pos = geoclue_position_new (service, path);
+       if (pos == NULL) {
+               g_printerr ("Error while creating GeocluePosition object.\n");
+               return 1;
+       }
+
+       g_free (service);
+       g_free (path);
+
+        if (argc > 2) {
+                GHashTable *options;
+
+                options = parse_options (argc, argv);
+                if (!geoclue_provider_set_options (GEOCLUE_PROVIDER (pos), options, &error)) {
+                        g_printerr ("Error setting options: %s\n",
+                                    error->message);
+                        g_error_free (error);
+                        error = NULL;
+                }
+                g_hash_table_destroy (options);
+        }
+
+       /* Query current position. We're not interested in altitude
+          this time, so leave it NULL. Same can be done with all other
+          arguments that aren't interesting to the client */
+       fields = geoclue_position_get_position (pos, &timestamp,
+                                               &lat, &lon, NULL,
+                                               &accuracy, &error);
+       if (error) {
+               g_printerr ("Error getting position: %s\n", error->message);
+               g_error_free (error);
+               g_object_unref (pos);
+               return 1;
+       }
+
+       /* Print out coordinates if they are valid */
+       if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
+           fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) {
+
+               GeoclueAccuracyLevel level;
+               double horiz_acc;
+
+               geoclue_accuracy_get_details (accuracy, &level, &horiz_acc, NULL);
+               g_print ("Current position:\n");
+               g_print ("\t%f, %f\n", lat, lon);
+               g_print ("\tAccuracy level %d (%.0f meters)\n", level, horiz_acc);
+
+       } else {
+               g_print ("Latitude and longitude not available.\n");
+       }
+
+       geoclue_accuracy_free (accuracy);
+
+       g_signal_connect (G_OBJECT (pos), "position-changed",
+                         G_CALLBACK (position_changed_cb), NULL);
+
+       g_main_loop_run (mainloop);
+       return 0;
+
+}
diff --git a/example/revgeocode-example.c b/example/revgeocode-example.c
new file mode 100755 (executable)
index 0000000..2207234
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Geoclue
+ * revgeocode-example.c - Example using the ReverseGeocode client API
+ *
+ * Author: Jussi Kukkonen <jku@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <glib.h>
+#include <stdlib.h>
+#include <geoclue/geoclue-reverse-geocode.h>
+
+/* GHFunc, use with g_hash_table_foreach */
+static void
+print_address_key_and_value (char *key, char *value, gpointer user_data)
+{
+       g_print ("    %s: %s\n", key, value);
+}
+
+static GHashTable *
+parse_options (int    argc,
+               char **argv)
+{
+        GHashTable *options;
+        int i;
+
+        options = g_hash_table_new (g_str_hash, g_str_equal);
+        for (i = 4; i < argc; i += 2) {
+                g_hash_table_insert (options, argv[i], argv[i + 1]);
+        }
+
+        return options;
+}
+
+int main (int argc, char** argv)
+{
+       gchar *service, *path;
+       GeoclueReverseGeocode *revgeocoder = NULL;
+       GeoclueAccuracy *accuracy, *out_accuracy;
+       GHashTable *address = NULL;
+       double lat, lon;
+       GError *error = NULL;
+
+       g_type_init();
+
+       if (argc < 4) {
+               g_printerr ("Usage:\n  revgeocode-example <provider_name> <lat> <lon>\n");
+               return 1;
+       }
+       g_print ("Using provider '%s'\n", argv[1]);
+       service = g_strdup_printf ("org.freedesktop.Geoclue.Providers.%s", argv[1]);
+       path = g_strdup_printf ("/org/freedesktop/Geoclue/Providers/%s", argv[1]);
+
+       /* Create new GeoclueReverseGeocode */
+       revgeocoder = geoclue_reverse_geocode_new (service, path);
+       g_free (service);
+       g_free (path);
+       if (revgeocoder == NULL) {
+               g_printerr ("Error while creating GeoclueGeocode object.\n");
+               return 1;
+       }
+
+
+        /* Set options */
+        if (argc > 4) {
+                GHashTable *options;
+
+                options = parse_options (argc, argv);
+                if (!geoclue_provider_set_options (GEOCLUE_PROVIDER (revgeocoder), options, &error)) {
+                        g_printerr ("Error setting options: %s\n",
+                                    error->message);
+                        g_error_free (error);
+                        error = NULL;
+                }
+                g_hash_table_destroy (options);
+        }
+
+       address = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                        (GDestroyNotify)g_free,
+                                        (GDestroyNotify)g_free);
+
+       lat = atof (argv[2]);
+       lon = atof (argv[3]);
+       accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_STREET, 0.0, 0.0);
+       if (!geoclue_reverse_geocode_position_to_address (revgeocoder,
+                                                         lat, lon, accuracy,
+                                                         &address, &out_accuracy, &error)) {
+               g_printerr ("Error while reverse geocoding: %s\n", error->message);
+               g_error_free (error);
+               g_object_unref (revgeocoder);
+               return 1;
+       }
+
+       /* Print out the address */
+       GeoclueAccuracyLevel level;
+       geoclue_accuracy_get_details (out_accuracy, &level, NULL, NULL);
+       g_print ("Reverse Geocoded  [%f, %f] to address (accuracy %d):\n", lat, lon, level);
+       g_hash_table_foreach (address, (GHFunc)print_address_key_and_value, NULL);
+
+       g_hash_table_destroy (address);
+       g_object_unref (revgeocoder);
+       return 0;
+
+}
diff --git a/geoclue.changes b/geoclue.changes
new file mode 100644 (file)
index 0000000..2a71642
--- /dev/null
@@ -0,0 +1,383 @@
+[Version] geoclue_0.12.0-28
+[date] 15 Jan 2013
+[Title] In order to build geoclue with GCC-4.7, apply patches(lp_718911.patch,
+       lp_738584.patch, and lp_829436.patch) on https://launchpad.net/ubuntu/+source/geoclue/0.12.0-1ubuntu10
+[Issue#] NA
+[Problem] build break with GCC-4.7
+[Cause] NA
+[Solution] update new patches
+[Developer] Youngae Kang <youngae.kang@samsung.com>
+
+================================================================================
+
+geoclue (0.12.0-27slp2) unstable; urgency=low
+
+  * Add PositionVelocity interface.
+  * Tag : geoclue_0.12.0-27slp2
+
+ -- Minjune Kim <sena06.kim@samsung.com>  Wed, 02 Jan 2013 14:11:04 +0900
+
+geoclue (0.12.0-26slp2) unstable; urgency=low
+
+  * Support POI
+  * Tag : geoclue_0.12.0-26slp2
+
+ -- Minjune Kim <sena06.kim@samsung.com>  Mon, 02 Jul 2012 23:27:13 +0900
+
+geoclue (0.12.0-25slp2) unstable; urgency=low
+
+  * fix for system proxy setting
+  * Tag : geoclue_0.12.0-25slp2
+
+ -- Genie Kim <daejins.kim@samsung.com>  Mon, 02 Apr 2012 20:24:00 +0900
+
+geoclue (0.12.0-24slp2) unstable; urgency=low
+
+  * add feature for last position & velocity & satellite
+  * Tag : geoclue_0.12.0-24slp2
+
+ -- Genie Kim <daejins.kim@samsung.com>  Mon, 27 Feb 2012 17:30:01 +0900
+
+geoclue (0.12.0-23slp2) unstable; urgency=low
+
+  * remove geoclue-gpsd
+  * Tag : geoclue_0.12.0-23slp2
+
+ -- Minjune kim <sena06.kim.kim@samsung.com>  Wed, 22 Feb 2012 16:55:45 +0900
+
+geoclue (0.12.0-22slp2) unstable; urgency=low
+
+  * remove geoclue-gpsd
+  * Tag : geoclue_0.12.0-22slp2
+
+ -- Genie Kim <daejins.kim@samsung.com>  Fri, 10 Feb 2012 17:58:42 +0900
+
+geoclue (0.12.0-21slp2) unstable; urgency=low
+
+  * add altitude / h_accuracy / v_accurcy in last position(geoclue_0.12.0-21slp2.patch)
+  * Tag : geoclue_0.12.0-21slp2 
+
+ -- Genie Kim <daejins.kim@samsung.com>  Tue, 10 Jan 2012 19:48:21 +0900
+
+geoclue (0.12.0-20slp2) unstable; urgency=low
+
+  * use quilt for patch(tizen.patch) 
+  * add last knonw position(geoclue_0.12.0-20slp2.patch)
+  * Tag : geoclue_0.12.0-20slp2
+
+ -- Genie Kim <daejins.kim@samsung.com>  Mon, 02 Jan 2012 19:27:14 +0900
+
+geoclue (0.12.0-19slp2+5) unstable; urgency=low
+
+  * add geoclue-gpsd install file
+  * Tag : geoclue_0.12.0-19slp2+5
+
+ -- Genie Kim <daejins.kim@samsung.com>  Mon, 19 Dec 2011 13:56:07 +0900
+
+geoclue (0.12.0-19slp2+4) unstable; urgency=low
+
+  * activate geoclue-gpsd
+  * Tag : geoclue_0.12.0-19slp2+4
+
+ -- Genie Kim <daejins.kim@samsung.com>  Wed, 07 Dec 2011 16:47:11 +0900
+
+geoclue (0.12.0-19slp2+3) unstable; urgency=low
+
+  * remove not using packages
+  * Tag : geoclue_0.12.0-19slp2+3
+
+ -- Genie Kim <daejins.kim@samsung.com>  Tue, 06 Dec 2011 22:36:09 +0900
+
+geoclue (0.12.0-19slp2+2) unstable; urgency=low
+
+  * Remove geoclue-gpsd package for add new feature and geoclue-gpsd is moved under geoclue-providers
+  * Tag : geoclue_0.12.0-19slp2+2
+
+ -- Genie Kim <daejins.kim@samsung.com>  Sat, 26 Nov 2011 12:15:52 +0900
+
+geoclue (0.12.0-19slp2+1) unstable; urgency=low
+
+  * Fix bug in dbus signal for satellite information
+  * Tag : geoclue_0.12.0-19slp2+1 
+
+ -- Yunhan Kim <yhan.kim@samsung.com>  Fri, 21 Oct 2011 09:03:40 +0900
+
+geoclue (0.12.0-18slp2+5) unstable; urgency=low
+
+  * remove GTK dependency
+  * Tag : geoclue_0.12.0-18slp2+5 
+
+ -- Genie Kim <daejins.kim@samsung.com>  Thu, 15 Sep 2011 13:55:47 +0900
+
+geoclue (0.12.0-18slp2+4) unstable; urgency=low
+
+  * upgrade of dbus-glib : remove Depends
+  * Tag : geoclue_0.12.0-18slp2+4 
+
+ -- Genie Kim <daejins.kim@samsung.com>  Tue, 02 Aug 2011 11:30:11 +0900
+
+geoclue (0.12.0-18slp2+3) unstable; urgency=low
+
+  * Add and change boilerplate
+  * Tag : geoclue_0.12.0-18slp2+3
+
+ -- Genie Kim <daejins.kim@samsung.com>  Tue, 19 Jul 2011 17:22:02 +0900
+
+geoclue (0.12.0-18slp2+2) unstable; urgency=low
+
+  * Install geoclue-nominatim package
+  * Tag : geoclue_0.12.0-18slp2+2
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Mon, 13 Jun 2011 11:20:07 +0900
+
+geoclue (0.12.0-18slp2+1) unstable; urgency=low
+
+  * Release again for glib upgrade
+  * Tag : geoclue_0.12.0-18slp2+1
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Wed, 30 Mar 2011 15:13:47 +0900
+
+geoclue (0.12.0-17slp2+17) unstable; urgency=low
+
+  * Fix geoclue-gpsd & Add debug package
+  * Tag : geoclue_0.12.0-17slp2+17
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Wed, 24 Nov 2010 22:38:02 +0900
+
+geoclue (0.12.0-17slp2+16) unstable; urgency=low
+
+  * Remove test-gui & remove auto genarated files
+  * Tag : geoclue_0.12.0-17slp2+16
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Fri, 12 Nov 2010 13:31:03 +0900
+
+geoclue (0.12.0-17slp2+15) unstable; urgency=low
+
+  * Release geoclue_0.12.0-17slp2+15
+  * Tag : geoclue_0.12.0-17slp2+15
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Wed, 10 Nov 2010 17:00:18 +0900
+
+geoclue (0.12.0-16slp2+13) unstable; urgency=low
+
+  * Add xps provider
+  * Tag : geoclue_0.12.0-16slp2+13
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Mon, 08 Nov 2010 13:18:51 +0900
+
+geoclue (0.12.0-15slp2+12) unstable; urgency=low
+
+  * Remove skyhooks & gpsd packages
+  * Tag : geoclue_0.12.0-15slp2+12
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Fri, 29 Oct 2010 16:21:45 +0900
+
+geoclue (0.12.0-14slp2+11) unstable; urgency=low
+
+  * Fix for Limo contrib.
+  * Tag : geoclue_0.12.0-14slp2+11
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Fri, 29 Oct 2010 16:21:41 +0900
+
+geoclue (0.12.0-13slp2+10) unstable; urgency=low
+
+  * Fix BS for multi process 
+  * Tag : geoclue_0.12.0-13slp2+10
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Tue, 12 Oct 2010 21:09:36 +0900
+
+geoclue (0.12.0-12slp2+9) unstable; urgency=low
+
+  * Apply tweak guide
+  * Tag : geoclue_0.12.0-12slp2+9
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Fri, 17 Sep 2010 19:17:45 +0900
+
+geoclue (0.12.0-11slp2+8) unstable; urgency=low
+
+  * Bug fix for impolite clients
+  * Tag : geoclue_0.12.0-11slp2+8
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Thu, 09 Sep 2010 11:52:42 +0900
+
+geoclue (0.12.0-10slp2+7) unstable; urgency=low
+
+  * We can use sync API if lbs-engine is already initialized
+  * Tag : geoclue_0.12.0-10slp2+7
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Mon, 06 Sep 2010 10:53:59 +0900
+
+geoclue (0.12.0-9slp2+6) unstable; urgency=low
+
+  * Modify lbs-sync API & Fix signaling & Add lbs-example & Remove lbs-stub
+  * Tag : geoclue_0.12.0-9slp2+6
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Sat, 04 Sep 2010 17:55:05 +0900
+
+geoclue (0.12.0-8slp2+5) unstable; urgency=low
+
+  * change lbs-stub --> lbs-client (lbs-engine)
+  * Tag : geoclue_0.12.0-8slp2+5
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Wed, 01 Sep 2010 11:41:56 +0900
+
+geoclue (0.12.0-7slp2+4) unstable; urgency=low
+
+  * Add G_END_DECLS ( Bug fix )
+  * Tag : geoclue_0.12.0-7slp2+4
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Mon, 30 Aug 2010 18:14:30 +0900
+
+geoclue (0.12.0-6slp2+3) unstable; urgency=low
+
+  * Modifying version
+  * Tag : geoclue_0.12.0-6slp2+3
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Sat, 28 Aug 2010 21:59:03 +0900
+
+geoclue (0.12.0-1slp2+3) unstable; urgency=low
+
+  * Add nmea&sattelite interface
+  * Tag : geoclue_0.12.0-1slp2+3
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Sat, 28 Aug 2010 21:38:51 +0900
+
+geoclue (0.12.0-5slp2+2) unstable; urgency=low
+
+  * Temporary patch for browser (lbs-engine --> lbs stub)
+  * Tag : geoclue_0.12.0-5slp2+2
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Fri, 27 Aug 2010 14:00:04 +0900
+
+geoclue (0.12.0-5slp2+1) unstable; urgency=low
+
+  * Change libgeoclue0.install.in --> libgeoclue.install.in
+  * Tag : geoclue_0.12.0-5slp2+1
+
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Sat, 21 Aug 2010 01:00:44 +0900
+
+geoclue (0.12.0-4slp2+1) unstable; urgency=low
+
+  * Version up
+  * Tag : geoclue_0.12.0-4slp2+1
+  
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Sat, 21 Aug 2010 00:41:18 +0900
+
+geoclue (0.12.0-3slp2+1) unstable; urgency=low
+
+  * Change git tag again
+  * Tag : geoclue_0.12.0-3slp2+1
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Fri, 20 Aug 2010 17:10:00 +0900
+
+geoclue (0.12.0-2slp2+1) unstable; urgency=low
+
+  * Change git tag
+  * Tag : geoclue_0.12.0-2slp2+1
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Fri, 20 Aug 2010 16:55:13 +0900
+
+geoclue (0.12.0-1slp2+1) unstable; urgency=low
+
+  * Fix geoclue-lbs for receiving callback from lbs-client
+  * Change debian/control for using lbs-client
+  * Tag : geoclue_0.12.0-1slp2+1
+
+ -- Tae-Hwan Kim <the81.kim@samsung.com>  Fri, 20 Aug 2010 14:22:17 +0900
+
+geoclue (0.11.1-13slp2+3) unstable; urgency=low
+
+  * Disable to check gtkdocize
+  * Tag : geoclue_0.11.1-13slp2+3
+
+ -- Gyuyoung Kim <gyuyoung.kim@samsung.com>  Sat, 05 Jun 2010 16:43:43 +0900
+
+geoclue (0.11.1-13slp2+2) unstable; urgency=low
+
+  * Change DBUS_BUS_SESSION with DBUS_BUS_SYSTEM
+  * Tag : geoclue_0.11.1-13slp2+2
+
+ -- Gyuyoung Kim <gyuyoung.kim@samsung.com>  Mon, 24 May 2010 13:36:37 +0900
+
+geoclue (0.11.1-13slp2+1) unstable; urgency=low
+
+  * Followd SLP package naming rule 
+
+ -- Joone Hur <joone.hur@samsung.com>  Thu, 01 Apr 2010 09:36:53 +0900
+
+geoclue (0.11.1-12) unstable; urgency=low
+
+  * Added missing gtk dependency for library
+
+ -- Lukasz Slachciak <l.slachciak@samsung.com>  Wed, 31 Mar 2010 10:50:30 +0200
+
+geoclue (0.11.1-11) unstable; urgency=low
+
+  * Uploaders section added
+
+ -- Lukasz Slachciak <l.slachciak@samsung.com>  Thu, 25 Mar 2010 16:31:33 +0100
+
+geoclue (0.11.1-10) unstable; urgency=low
+
+  * Toolchain upgrade
+
+ -- Lukasz Slachciak <l.slachciak@samsung.com>  Thu, 25 Mar 2010 10:55:21 +0100
+
+geoclue (0.11.1-9) unstable; urgency=low
+
+  * add missing skyhook files to the package
+  * hostip provider allows for FORCE_IP env var
+  * let's have SUWON location by default
+  * use the data returned by LBS CLIENT in the signal - this could work with GPS now
+
+ -- Jaroslaw Staniek <j.staniek@samsung.com>  Tue, 16 Mar 2010 17:16:20 +0100
+
+geoclue (0.11.1-8) unstable; urgency=low
+
+  * Merged with changes from vanilla geoclue; this adds skyhook provider
+
+ -- Jaroslaw Staniek <j.staniek@samsung.com>  Fri, 12 Mar 2010 16:12:51 +0100
+
+geoclue (0.11.1-7) unstable; urgency=low
+
+  * Add LBS stub library (working) for testing LBS provider
+  * Make geoclue LBS provider emit position-changed signal
+
+ -- Jaroslaw Staniek <j.staniek@samsung.com>  Mon, 08 Mar 2010 17:07:01 +0100
+
+geoclue (0.11.1-6) unstable; urgency=low
+
+  * Update lbs service config
+
+ -- Jaroslaw Staniek <j.staniek@samsung.com>  Mon, 22 Feb 2010 16:25:06 +0100
+
+geoclue (0.11.1-5) unstable; urgency=low
+
+  * added LBS Position Provider
+
+ -- Jaroslaw Staniek <j.staniek@samsung.com>  Mon, 22 Feb 2010 15:02:20 +0100
+
+geoclue (0.11.1-4) unstable; urgency=low
+
+  * add gtk deps for devel package, required by geoclue-test-gui
+
+ -- Jaroslaw Staniek <j.staniek@samsung.com>  Thu, 21 Jan 2010 15:05:55 +0100
+
+geoclue (0.11.1-3) unstable; urgency=low
+
+  * more deps on gconf
+
+ -- Jaroslaw Staniek <j.staniek@samsung.com>  Tue, 19 Jan 2010 12:56:49 +0100
+
+geoclue (0.11.1-2) unstable; urgency=low
+
+  * added dependency on gconf
+
+ -- Jaroslaw Staniek <j.staniek@samsung.com>  Tue, 19 Jan 2010 11:48:25 +0100
+
+geoclue (0.11.1-1) unstable; urgency=low
+
+  * Initial release.
+
+ -- Jaroslaw Staniek <j.staniek@samsung.com>  Thu, 14 Jan 2010 15:45:33 +0100
diff --git a/geoclue.pc.in b/geoclue.pc.in
new file mode 100644 (file)
index 0000000..51b0d3e
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir = @datarootdir@
+datadir=@datadir@
+
+Name: geoclue
+Description: Geoinformation service
+Requires: dbus-glib-1 libxml-2.0
+Version: @VERSION@
+Libs: -L${libdir} -lgeoclue
+Cflags: -I${includedir}
diff --git a/geoclue/Makefile.am b/geoclue/Makefile.am
new file mode 100644 (file)
index 0000000..5f10715
--- /dev/null
@@ -0,0 +1,230 @@
+lib_LTLIBRARIES = libgeoclue.la
+
+nodist_libgeoclue_la_SOURCES = \
+       geoclue-marshal.c       \
+       geoclue-marshal.h       \
+       gc-iface-address-bindings.h     \
+       gc-iface-address-glue.h \
+       gc-iface-geoclue-bindings.h     \
+       gc-iface-geoclue-glue.h \
+       gc-iface-geocode-bindings.h     \
+       gc-iface-geocode-glue.h \
+       gc-iface-poi-bindings.h \
+       gc-iface-poi-glue.h     \
+       gc-iface-master-bindings.h      \
+       gc-iface-master-client-bindings.h       \
+       gc-iface-position-bindings.h    \
+       gc-iface-position-glue.h        \
+       gc-iface-position-ext-bindings.h        \
+       gc-iface-position-ext-glue.h    \
+       gc-iface-nmea-bindings.h        \
+       gc-iface-nmea-glue.h    \
+       gc-iface-reverse-geocode-bindings.h     \
+       gc-iface-reverse-geocode-glue.h \
+       gc-iface-velocity-bindings.h    \
+       gc-iface-velocity-glue.h \
+       gc-iface-satellite-bindings.h   \
+       gc-iface-satellite-glue.h
+
+BUILT_SOURCES = \
+       $(nodist_libgeoclue_la_SOURCES) \
+       geoclue-enum-types.h            \
+       geoclue-enum-types.c
+
+libgeoclue_la_SOURCES =        \
+       geoclue-accuracy.c      \
+       geoclue-address.c       \
+       geoclue-address-details.c       \
+       geoclue-provider.c      \
+       geoclue-error.c         \
+       geoclue-geocode.c       \
+       geoclue-poi.c   \
+       geoclue-master.c        \
+       geoclue-master-client.c \
+       geoclue-position.c      \
+       geoclue-position-ext.c  \
+       geoclue-nmea.c  \
+       geoclue-reverse-geocode.c       \
+       geoclue-types.c         \
+       geoclue-velocity.c      \
+       geoclue-satellite.c     \
+       gc-provider.c           \
+       gc-web-service.c        \
+       gc-iface-address.c      \
+       gc-iface-geoclue.c      \
+       gc-iface-geocode.c      \
+       gc-iface-poi.c  \
+       gc-iface-position.c     \
+       gc-iface-position-ext.c \
+       gc-iface-nmea.c \
+       gc-iface-reverse-geocode.c      \
+       gc-iface-velocity.c     \
+       gc-iface-satellite.c    \
+       geoclue-enum-types.c
+
+libgeoclue_la_LIBADD = \
+       $(GEOCLUE_LIBS)
+
+libgeoclue_la_CFLAGS =         \
+       -I$(top_srcdir)         \
+       -I$(top_builddir)       \
+       $(GEOCLUE_CFLAGS)
+
+geoclue_headers =              \
+       gc-iface-address.h      \
+       gc-iface-geoclue.h      \
+       gc-iface-geocode.h      \
+       gc-iface-poi.h  \
+       gc-iface-position.h     \
+       gc-iface-position-ext.h \
+       gc-iface-nmea.h \
+       gc-iface-reverse-geocode.h      \
+       gc-iface-velocity.h     \
+       gc-iface-satellite.h    \
+       gc-provider.h           \
+       gc-web-service.h        \
+       geoclue-accuracy.h      \
+       geoclue-address.h       \
+       geoclue-address-details.h       \
+       geoclue-provider.h      \
+       geoclue-error.h         \
+       geoclue-geocode.h       \
+       geoclue-master.h        \
+       geoclue-master-client.h \
+       geoclue-poi.h           \
+       geoclue-landmark.h      \
+       geoclue-position.h      \
+       geoclue-position-ext.h  \
+       geoclue-nmea.h  \
+       geoclue-reverse-geocode.h       \
+       geoclue-types.h         \
+       geoclue-velocity.h      \
+       geoclue-satellite.h     \
+       geoclue-satellite-info.h        \
+       geoclue-enum-types.h
+
+libgeoclue_includedir = $(includedir)/geoclue
+libgeoclue_include_HEADERS =   \
+       $(geoclue_headers)
+
+EXTRA_DIST =                   \
+       geoclue-marshal.list
+
+CLEANFILES = $(BUILT_SOURCES)  \
+       stamp-gc-iface-address-glue.h   \
+       stamp-gc-iface-geoclue-glue.h   \
+       stamp-gc-iface-geocode-glue.h   \
+       stamp-gc-iface-poi-glue.h       \
+       stamp-gc-iface-position-glue.h  \
+       stamp-gc-iface-position-ext-glue.h      \
+       stamp-gc-iface-nmea-glue.h      \
+       stamp-gc-iface-reverse-geocode-glue.h   \
+       stamp-gc-iface-velocity-glue.h \
+       stamp-gc-iface-satellite-glue.h
+
+DISTCLEANFILES = \
+       $(nodist_libgeoclue_la_SOURCES) \
+       geoclue-enum-types.h            \
+       geoclue-enum-types.c
+
+geoclue-marshal.h: geoclue-marshal.list $(GLIB_GENMARSHAL)
+       $(GLIB_GENMARSHAL) $< --header --prefix=geoclue_marshal > $@
+geoclue-marshal.c: geoclue-marshal.list geoclue-marshal.h $(GLIB_GENMARSHAL)
+       echo "#include \"geoclue-marshal.h\"" > $@ \
+       && $(GLIB_GENMARSHAL) --prefix=geoclue_marshal $(srcdir)/geoclue-marshal.list --body >> $@
+
+%-glue.h: stamp-%-glue.h
+       @true
+
+stamp-gc-iface-address-glue.h: ../interfaces/gc-iface-address.xml
+       $(DBUS_BINDING_TOOL) --prefix=gc_iface_address --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
+
+stamp-gc-iface-geoclue-glue.h: ../interfaces/gc-iface-geoclue.xml
+       $(DBUS_BINDING_TOOL) --prefix=gc_iface_geoclue --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
+
+stamp-gc-iface-geocode-glue.h: ../interfaces/gc-iface-geocode.xml
+       $(DBUS_BINDING_TOOL) --prefix=gc_iface_geocode --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
+
+stamp-gc-iface-poi-glue.h: ../interfaces/gc-iface-poi.xml
+       $(DBUS_BINDING_TOOL) --prefix=gc_iface_poi --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
+
+stamp-gc-iface-position-glue.h: ../interfaces/gc-iface-position.xml
+       $(DBUS_BINDING_TOOL) --prefix=gc_iface_position --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
+
+stamp-gc-iface-position-ext-glue.h: ../interfaces/gc-iface-position-ext.xml
+       $(DBUS_BINDING_TOOL) --prefix=gc_iface_position_ext --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
+
+stamp-gc-iface-nmea-glue.h: ../interfaces/gc-iface-nmea.xml
+       $(DBUS_BINDING_TOOL) --prefix=gc_iface_nmea --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
+
+stamp-gc-iface-reverse-geocode-glue.h: ../interfaces/gc-iface-reverse-geocode.xml
+       $(DBUS_BINDING_TOOL) --prefix=gc_iface_reverse_geocode --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
+
+stamp-gc-iface-velocity-glue.h: ../interfaces/gc-iface-velocity.xml
+       $(DBUS_BINDING_TOOL) --prefix=gc_iface_velocity --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
+
+stamp-gc-iface-satellite-glue.h: ../interfaces/gc-iface-satellite.xml
+       $(DBUS_BINDING_TOOL) --prefix=gc_iface_satellite --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
+
+%-bindings.h: stamp-%-bindings.h
+       @true
+stamp-%-bindings.h: ../interfaces/%.xml
+       $(DBUS_BINDING_TOOL) --mode=glib-client --prefix=geoclue $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
+
+geoclue_headers_to_scan_for_enums = geoclue-error.h
+# Generate the enums source code, with glib-mkenums:
+# This is based on the same Makefile.am stuff in pango:
+geoclue_built_headers = geoclue-enum-types.h
+geoclue_built_cfiles = geoclue-enum-types.c
+
+geoclue-enum-types.h: $(geoclue_headers_to_scan_for_enums) Makefile
+       $(AM_V_GEN) (cd $(srcdir) && glib-mkenums \
+                       --fhead "#ifndef __GEOCLUE_ENUM_TYPES_H__\n#define __GEOCLUE_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
+                       --fprod "/* enumerations from \"@filename@\" */\n" \
+                       --vhead "GType @enum_name@_get_type (void);\n#define GEOCLUE_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n"       \
+                       --ftail "G_END_DECLS\n\n#endif /* __GEOCLUE_ENUM_TYPES_H__ */" \
+               $(geoclue_headers_to_scan_for_enums)) > $@
+
+geoclue-enum-types.c: $(geoclue_headers_to_scan_for_enums) Makefile geoclue-enum-types.h
+       $(AM_V_GEN) (cd $(srcdir) && glib-mkenums \
+                       --fhead "#include <geoclue-error.h>\n" \
+                       --fhead "#include \"geoclue-enum-types.h\"\n" \
+                       --fhead "#include <glib-object.h>" \
+                       --fprod "\n/* enumerations from \"@filename@\" */" \
+                       --vhead "GType\n@enum_name@_get_type (void)\n{\n  static GType etype = 0;\n  if (etype == 0) {\n    static const G@Type@Value values[] = {"     \
+                       --vprod "      { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+                       --vtail "      { 0, NULL, NULL }\n    };\n    etype = g_@type@_register_static (\"@EnumName@\", values);\n  }\n  return etype;\n}\n" \
+               $(geoclue_headers_to_scan_for_enums)) > $@
diff --git a/geoclue/gc-iface-address.c b/geoclue/gc-iface-address.c
new file mode 100644 (file)
index 0000000..2cfa018
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Geoclue
+ * gc-iface-address.c - GInterface for org.freedesktop.Address
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <glib.h>
+
+#include <dbus/dbus-glib.h>
+
+#include <geoclue/geoclue-marshal.h>
+#include <geoclue/gc-iface-address.h>
+
+enum {
+       ADDRESS_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+static gboolean
+gc_iface_address_get_address (GcIfaceAddress   *gc,
+                             int              *timestamp,
+                             GHashTable      **address,
+                             GeoclueAccuracy **accuracy,
+                             GError          **error);
+#include "gc-iface-address-glue.h"
+
+static void
+gc_iface_address_base_init (gpointer klass)
+{
+       static gboolean initialized = FALSE;
+
+       if (initialized) {
+               return;
+       }
+       initialized = TRUE;
+
+       signals[ADDRESS_CHANGED] = g_signal_new ("address-changed",
+                                                G_OBJECT_CLASS_TYPE (klass),
+                                                G_SIGNAL_RUN_LAST, 0,
+                                                NULL, NULL,
+                                                geoclue_marshal_VOID__INT_POINTER_BOXED,
+                                                G_TYPE_NONE, 3,
+                                                G_TYPE_INT,
+                                                DBUS_TYPE_G_STRING_STRING_HASHTABLE,
+                                                GEOCLUE_ACCURACY_TYPE);
+       dbus_g_object_type_install_info (gc_iface_address_get_type (),
+                                        &dbus_glib_gc_iface_address_object_info);
+}
+
+GType
+gc_iface_address_get_type (void)
+{
+       static GType type = 0;
+
+       if (!type) {
+               const GTypeInfo info = {
+                       sizeof (GcIfaceAddressClass),
+                       gc_iface_address_base_init,
+                       NULL,
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                                              "GcIfaceAddress", &info, 0);
+       }
+
+       return type;
+}
+
+static gboolean
+gc_iface_address_get_address (GcIfaceAddress   *gc,
+                             int              *timestamp,
+                             GHashTable      **address,
+                             GeoclueAccuracy **accuracy,
+                             GError          **error)
+{
+       return GC_IFACE_ADDRESS_GET_CLASS (gc)->get_address
+               (gc, timestamp, address, accuracy, error);
+}
+
+void
+gc_iface_address_emit_address_changed (GcIfaceAddress  *gc,
+                                      int              timestamp,
+                                      GHashTable      *address,
+                                      GeoclueAccuracy *accuracy)
+{
+       g_signal_emit (gc, signals[ADDRESS_CHANGED], 0, timestamp,
+                      address, accuracy);
+}
diff --git a/geoclue/gc-iface-address.h b/geoclue/gc-iface-address.h
new file mode 100644 (file)
index 0000000..dafcc09
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Geoclue
+ * gc-iface-address.h - GInterface for org.freedesktop.Address
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GC_IFACE_ADDRESS_H
+#define _GC_IFACE_ADDRESS_H
+
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+#include <geoclue/geoclue-address-details.h>
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_IFACE_ADDRESS (gc_iface_address_get_type ())
+#define GC_IFACE_ADDRESS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_IFACE_ADDRESS, GcIfaceAddress))
+#define GC_IFACE_ADDRESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GC_TYPE_IFACE_ADDRESS, GcIfaceAddressClass))
+#define GC_IS_IFACE_ADDRESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GC_TYPE_IFACE_ADDRESS))
+#define GC_IS_IFACE_ADDRESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GC_TYPE_IFACE_ADDRESS))
+#define GC_IFACE_ADDRESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GC_TYPE_IFACE_ADDRESS, GcIfaceAddressClass))
+
+typedef struct _GcIfaceAddress GcIfaceAddress; /* Dummy typedef */
+typedef struct _GcIfaceAddressClass GcIfaceAddressClass;
+
+struct _GcIfaceAddressClass {
+       GTypeInterface base_iface;
+
+       /* signals */
+       void (* address_changed) (GcIfaceAddress  *gc,
+                                 int              timestamp,
+                                 GHashTable      *address,
+                                 GeoclueAccuracy *accuracy);
+
+       /* vtable */
+       gboolean (*get_address) (GcIfaceAddress   *gc,
+                                int              *timestamp,
+                                GHashTable      **address,
+                                GeoclueAccuracy **accuracy,
+                                GError          **error);
+};
+
+GType gc_iface_address_get_type (void);
+
+void gc_iface_address_emit_address_changed (GcIfaceAddress  *gc,
+                                           int              timestamp,
+                                           GHashTable      *address,
+                                           GeoclueAccuracy *accuracy);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/gc-iface-geoclue.c b/geoclue/gc-iface-geoclue.c
new file mode 100644 (file)
index 0000000..238f2f0
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Geoclue
+ * gc-iface-geoclue.c - GInterface for org.freedesktop.Geoclue
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <glib.h>
+
+#include <dbus/dbus-glib.h>
+
+#include <geoclue/gc-iface-geoclue.h>
+
+enum {
+       STATUS_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+static gboolean gc_iface_geoclue_get_provider_info (GcIfaceGeoclue  *gc,
+                                                   gchar          **name,
+                                                   gchar          **description,
+                                                   GError         **error);
+static gboolean gc_iface_geoclue_get_status (GcIfaceGeoclue *gc,
+                                            GeoclueStatus  *status,
+                                            GError        **error);
+static gboolean gc_iface_geoclue_set_options (GcIfaceGeoclue *gc,
+                                              GHashTable     *options,
+                                              GError        **error);
+static void gc_iface_geoclue_add_reference (GcIfaceGeoclue *gc,
+                                            DBusGMethodInvocation *context);
+static void gc_iface_geoclue_remove_reference (GcIfaceGeoclue *gc,
+                                               DBusGMethodInvocation *context);
+
+#include "gc-iface-geoclue-glue.h"
+
+
+static void
+gc_iface_geoclue_base_init (gpointer klass)
+{
+       static gboolean initialized = FALSE;
+
+       if (initialized) {
+               return;
+       }
+       initialized = TRUE;
+
+       signals[STATUS_CHANGED] = g_signal_new ("status-changed",
+                                               G_OBJECT_CLASS_TYPE (klass),
+                                               G_SIGNAL_RUN_LAST,
+                                               G_STRUCT_OFFSET (GcIfaceGeoclueClass, status_changed),
+                                               NULL, NULL,
+                                               g_cclosure_marshal_VOID__INT,
+                                               G_TYPE_NONE, 1,
+                                               G_TYPE_INT);
+       dbus_g_object_type_install_info (gc_iface_geoclue_get_type (),
+                                        &dbus_glib_gc_iface_geoclue_object_info);
+}
+
+GType
+gc_iface_geoclue_get_type (void)
+{
+       static GType type = 0;
+
+       if (!type) {
+               const GTypeInfo info = {
+                       sizeof (GcIfaceGeoclueClass),
+                       gc_iface_geoclue_base_init,
+                       NULL,
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                                              "GcIfaceGeoclue", &info, 0);
+       }
+
+       return type;
+}
+
+static gboolean
+gc_iface_geoclue_get_provider_info (GcIfaceGeoclue  *gc,
+                                   gchar          **name,
+                                   gchar          **description,
+                                   GError         **error)
+{
+       return GC_IFACE_GEOCLUE_GET_CLASS (gc)->get_provider_info (gc,
+                                                                  name,
+                                                                  description,
+                                                                  error);
+}
+
+static gboolean
+gc_iface_geoclue_get_status (GcIfaceGeoclue *gc,
+                            GeoclueStatus  *status,
+                            GError        **error)
+{
+       return GC_IFACE_GEOCLUE_GET_CLASS (gc)->get_status (gc, status,
+                                                           error);
+}
+
+static gboolean
+gc_iface_geoclue_set_options (GcIfaceGeoclue *gc,
+                              GHashTable     *options,
+                              GError        **error)
+{
+        return GC_IFACE_GEOCLUE_GET_CLASS (gc)->set_options (gc, options,
+                                                             error);
+}
+
+static void
+gc_iface_geoclue_add_reference (GcIfaceGeoclue *gc,
+                                DBusGMethodInvocation *context)
+{
+       GC_IFACE_GEOCLUE_GET_CLASS (gc)->add_reference (gc, context);
+}
+static void
+gc_iface_geoclue_remove_reference (GcIfaceGeoclue *gc,
+                                   DBusGMethodInvocation *context)
+{
+       GC_IFACE_GEOCLUE_GET_CLASS (gc)->remove_reference (gc, context);
+}
+
+void
+gc_iface_geoclue_emit_status_changed (GcIfaceGeoclue *gc,
+                                     GeoclueStatus   status)
+{
+       g_signal_emit (gc, signals[STATUS_CHANGED], 0, status);
+}
diff --git a/geoclue/gc-iface-geoclue.h b/geoclue/gc-iface-geoclue.h
new file mode 100644 (file)
index 0000000..8b6393c
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Geoclue
+ * gc-iface-geoclue.h - GInterface for org.freedesktop.Geoclue
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GC_IFACE_GEOCLUE_H
+#define _GC_IFACE_GEOCLUE_H
+
+#include <geoclue/geoclue-types.h>
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_IFACE_GEOCLUE (gc_iface_geoclue_get_type ())
+#define GC_IFACE_GEOCLUE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_IFACE_GEOCLUE, GcIfaceGeoclue))
+#define GC_IFACE_GEOCLUE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GC_TYPE_IFACE_GEOCLUE, GcIfaceGeoclueClass))
+#define GC_IS_IFACE_GEOCLUE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GC_TYPE_IFACE_GEOCLUE))
+#define GC_IS_IFACE_GEOCLUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GC_TYPE_IFACE_GEOCLUE))
+#define GC_IFACE_GEOCLUE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GC_TYPE_IFACE_GEOCLUE, GcIfaceGeoclueClass))
+
+typedef struct _GcIfaceGeoclue GcIfaceGeoclue; /* Dummy typedef */
+typedef struct _GcIfaceGeoclueClass GcIfaceGeoclueClass;
+
+struct _GcIfaceGeoclueClass {
+       GTypeInterface base_iface;
+
+       /* signals */
+       void (* status_changed) (GcIfaceGeoclue *geoclue,
+                                GeoclueStatus   status);
+
+       /* vtable */
+       gboolean (*get_provider_info) (GcIfaceGeoclue  *gc,
+                                      gchar          **name,
+                                      gchar          **description,
+                                      GError         **error);
+       gboolean (*get_status) (GcIfaceGeoclue *geoclue,
+                               GeoclueStatus  *status,
+                               GError        **error);
+        gboolean (*set_options) (GcIfaceGeoclue *geoclue,
+                                 GHashTable     *options,
+                                 GError        **error);
+        void (*add_reference) (GcIfaceGeoclue        *geoclue,
+                               DBusGMethodInvocation *context);
+        void (*remove_reference) (GcIfaceGeoclue        *geoclue,
+                                  DBusGMethodInvocation *context);
+};
+
+GType gc_iface_geoclue_get_type (void);
+
+void gc_iface_geoclue_emit_status_changed (GcIfaceGeoclue *gc,
+                                          GeoclueStatus   status);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/gc-iface-geocode.c b/geoclue/gc-iface-geocode.c
new file mode 100644 (file)
index 0000000..73db3b6
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Geoclue
+ * gc-iface-geocode.c - GInterface for org.freedesktop.Geocode
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ *          Jussi Kukkonen <jku@linux.intel.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *           2010 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* This is a GInterface for implementing Geoclue Geocode providers */
+
+#include <glib.h>
+
+#include <dbus/dbus-glib.h>
+
+#include <geoclue/geoclue-accuracy.h>
+#include <geoclue/gc-iface-geocode.h>
+
+static gboolean
+gc_iface_geocode_address_to_position (GcIfaceGeocode   *gc,
+                                     GHashTable       *address,
+                                     int              *fields,
+                                     double           *latitude,
+                                     double           *longitude,
+                                     double           *altitude,
+                                     GeoclueAccuracy **accuracy,
+                                     GError          **error);
+
+static gboolean
+gc_iface_geocode_freeform_address_to_position (GcIfaceGeocode   *gc,
+                                               const char       *address,
+                                               int              *fields,
+                                               double           *latitude,
+                                               double           *longitude,
+                                               double           *altitude,
+                                               GeoclueAccuracy **accuracy,
+                                               GError          **error);
+#include "gc-iface-geocode-glue.h"
+
+static void
+gc_iface_geocode_base_init (gpointer klass)
+{
+       static gboolean initialized = FALSE;
+
+       if (initialized) {
+               return;
+       }
+       initialized = TRUE;
+
+       dbus_g_object_type_install_info (gc_iface_geocode_get_type (),
+                                        &dbus_glib_gc_iface_geocode_object_info);
+}
+
+GType
+gc_iface_geocode_get_type (void)
+{
+       static GType type = 0;
+
+       if (!type) {
+               const GTypeInfo info = {
+                       sizeof (GcIfaceGeocodeClass),
+                       gc_iface_geocode_base_init,
+                       NULL,
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                                              "GcIfaceGeocode", &info, 0);
+       }
+
+       return type;
+}
+
+static gboolean
+gc_iface_geocode_address_to_position (GcIfaceGeocode   *gc,
+                                     GHashTable       *address,
+                                     int              *fields,
+                                     double           *latitude,
+                                     double           *longitude,
+                                     double           *altitude,
+                                     GeoclueAccuracy **accuracy,
+                                     GError          **error)
+{
+       return GC_IFACE_GEOCODE_GET_CLASS (gc)->address_to_position
+               (gc, address, (GeocluePositionFields *) fields,
+                latitude, longitude, altitude, accuracy, error);
+}
+
+static gboolean
+gc_iface_geocode_freeform_address_to_position (GcIfaceGeocode   *gc,
+                                               const char       *address,
+                                               int              *fields,
+                                               double           *latitude,
+                                               double           *longitude,
+                                               double           *altitude,
+                                               GeoclueAccuracy **accuracy,
+                                               GError          **error)
+{
+       return GC_IFACE_GEOCODE_GET_CLASS (gc)->freeform_address_to_position
+               (gc, address, (GeocluePositionFields *) fields,
+                latitude, longitude, altitude, accuracy, error);
+}
diff --git a/geoclue/gc-iface-geocode.h b/geoclue/gc-iface-geocode.h
new file mode 100644 (file)
index 0000000..c7bf7c7
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Geoclue
+ * gc-iface-geocode.h - GInterface for org.freedesktop.Geocode
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GC_IFACE_GEOCODE_H
+#define _GC_IFACE_GEOCODE_H
+
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_IFACE_GEOCODE (gc_iface_geocode_get_type ())
+#define GC_IFACE_GEOCODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_IFACE_GEOCODE, GcIfaceGeocode))
+#define GC_IFACE_GEOCODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GC_TYPE_IFACE_GEOCODE, GcIfaceGeocodeClass))
+#define GC_IS_IFACE_GEOCODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GC_TYPE_IFACE_GEOCODE))
+#define GC_IS_IFACE_GEOCODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GC_TYPE_IFACE_GEOCODE))
+#define GC_IFACE_GEOCODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GC_TYPE_IFACE_GEOCODE, GcIfaceGeocodeClass))
+
+typedef struct _GcIfaceGeocode GcIfaceGeocode; /* Dummy typedef */
+typedef struct _GcIfaceGeocodeClass GcIfaceGeocodeClass;
+
+struct _GcIfaceGeocodeClass {
+       GTypeInterface base_iface;
+
+       /* vtable */
+       gboolean (*address_to_position) (GcIfaceGeocode        *gc,
+                                        GHashTable            *address,
+                                        GeocluePositionFields *fields,
+                                        double                *latitude,
+                                        double                *longitude,
+                                        double                *altitude,
+                                        GeoclueAccuracy      **accuracy,
+                                        GError               **error);
+
+       gboolean (*freeform_address_to_position) (GcIfaceGeocode        *gc,
+                                                 const char            *address,
+                                                 GeocluePositionFields *fields,
+                                                 double                *latitude,
+                                                 double                *longitude,
+                                                 double                *altitude,
+                                                 GeoclueAccuracy      **accuracy,
+                                                 GError               **error);
+};
+
+GType gc_iface_geocode_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/gc-iface-nmea.c b/geoclue/gc-iface-nmea.c
new file mode 100644 (file)
index 0000000..3a15656
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Geoclue
+ * gc-iface-nmea.c - GInterface for org.freedesktop.Geoclue.Nmea
+ *
+ * Author: Tae-Hwan Kim <the81.kim@samsung.com>, Youngae Kang <youngae.kang@samsung.com>,
+ *         Yunhan Kim <yhan.kim@samsung.com>, Genie Kim <daejins.kim@samsung.com>
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+#include <glib.h>
+
+#include <dbus/dbus-glib.h>
+#include <geoclue/gc-iface-nmea.h>
+#include <geoclue/geoclue-marshal.h>
+
+enum {
+       NMEA_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+static gboolean
+gc_iface_nmea_get_nmea (GcIfaceNmea *nmea,
+                       int         *timestamp,
+                       char       **nmea_data,
+                       GError     **error);
+
+#include "gc-iface-nmea-glue.h"
+
+static void
+gc_iface_nmea_base_init (gpointer klass)
+{
+       static gboolean initialized = FALSE;
+
+       if (initialized) {
+               return;
+       }
+       initialized = TRUE;
+
+       signals[NMEA_CHANGED] = g_signal_new ("nmea-changed",
+                                             G_OBJECT_CLASS_TYPE (klass),
+                                             G_SIGNAL_RUN_LAST, 0,
+                                             NULL, NULL,
+                                             geoclue_marshal_VOID__INT_STRING,
+                                             G_TYPE_NONE, 2,
+                                             G_TYPE_INT,
+                                             G_TYPE_STRING);
+
+       dbus_g_object_type_install_info (gc_iface_nmea_get_type (),
+                                        &dbus_glib_gc_iface_nmea_object_info);
+}
+
+GType
+gc_iface_nmea_get_type (void)
+{
+       static GType type = 0;
+
+       if (!type) {
+               const GTypeInfo info = {
+                       sizeof (GcIfaceNmeaClass),
+                       gc_iface_nmea_base_init,
+                       NULL,
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                                              "GcIfaceNmea", &info, 0);
+       }
+
+       return type;
+}
+
+static gboolean
+gc_iface_nmea_get_nmea (GcIfaceNmea *gc,
+                       int         *timestamp,
+                       char       **nmea_data,
+                       GError     **error)
+{
+       return GC_IFACE_NMEA_GET_CLASS (gc)->get_nmea (gc, timestamp, nmea_data, error);
+}
+
+void
+gc_iface_nmea_emit_nmea_changed (GcIfaceNmea *gc,
+                                int          timestamp,
+                                char        *nmea_data)
+{
+       g_signal_emit (gc, signals[NMEA_CHANGED], 0, timestamp, nmea_data);
+}
diff --git a/geoclue/gc-iface-nmea.h b/geoclue/gc-iface-nmea.h
new file mode 100644 (file)
index 0000000..0f5ec20
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Geoclue
+ * gc-iface-nmea.h - GInterface for org.freedesktop.Geoclue.Nmea
+ *
+ * Author: Tae-Hwan Kim <the81.kim@samsung.com>, Youngae Kang <youngae.kang@samsung.com>,
+ *         Yunhan Kim <yhan.kim@samsung.com>, Genie Kim <daejins.kim@samsung.com>
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GC_IFACE_NMEA_H
+#define _GC_IFACE_NMEA_H
+
+#include <geoclue/geoclue-types.h>
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_IFACE_NMEA (gc_iface_nmea_get_type ())
+#define GC_IFACE_NMEA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_IFACE_NMEA, GcIfaceNmea))
+#define GC_IFACE_NMEA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GC_TYPE_IFACE_NMEA, GcIfaceNmeaClass))
+#define GC_IS_IFACE_NMEA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GC_TYPE_IFACE_NMEA))
+#define GC_IS_IFACE_NMEA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GC_TYPE_IFACE_NMEA))
+#define GC_IFACE_NMEA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GC_TYPE_IFACE_NMEA, GcIfaceNmeaClass))
+
+typedef struct _GcIfaceNmea GcIfaceNmea; /* Dummy typedef */
+
+typedef struct _GcIfaceNmeaClass {
+        GTypeInterface base_iface;
+
+       /* signals */
+       void (* nmea_changed) (GcIfaceNmea *gc,
+                              int          timestamp,
+                              char        *nmea_data);
+
+       /* vtable */
+       gboolean (* get_nmea) (GcIfaceNmea *gc,
+                              int         *timestamp,
+                              char       **nmea_data,
+                              GError     **error);
+} GcIfaceNmeaClass;
+
+GType gc_iface_nmea_get_type (void);
+
+void gc_iface_nmea_emit_nmea_changed (GcIfaceNmea *gc,
+                                     int timestamp,
+                                     char *nmea_data);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/gc-iface-poi.c b/geoclue/gc-iface-poi.c
new file mode 100644 (file)
index 0000000..8024dca
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Geoclue
+ * gc-iface-poi.c - GInterface for org.freedesktop.Poi
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ *          Jussi Kukkonen <jku@linux.intel.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *           2010 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* This is a GInterface for implementing Geoclue Poi providers */
+
+#include <glib.h>
+
+#include <dbus/dbus-glib.h>
+
+#include <geoclue/geoclue-accuracy.h>
+#include <geoclue/gc-iface-poi.h>
+
+static gboolean
+gc_iface_poi_search_by_position (GcIfacePoi   *gc,
+            const char *keyword,
+            const char *lang,
+            const char *country_code,
+            int limit,
+            double left,
+            double top,
+            double right,
+            double bottom,
+            int        *count,
+            GPtrArray  **landmark,
+            GError          **error);
+
+#include "gc-iface-poi-glue.h"
+
+static void
+gc_iface_poi_base_init (gpointer klass)
+{
+       static gboolean initialized = FALSE;
+
+       if (initialized) {
+               return;
+       }
+       initialized = TRUE;
+
+       dbus_g_object_type_install_info (gc_iface_poi_get_type (),
+                                        &dbus_glib_gc_iface_poi_object_info);
+}
+
+GType
+gc_iface_poi_get_type (void)
+{
+       static GType type = 0;
+
+       if (!type) {
+               const GTypeInfo info = {
+                       sizeof (GcIfacePoiClass),
+                       gc_iface_poi_base_init,
+                       NULL,
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                                              "GcIfacePoi", &info, 0);
+       }
+
+       return type;
+}
+
+static gboolean
+gc_iface_poi_search_by_position (GcIfacePoi            *gc,
+                               const char              *keyword,
+                               const char              *lang,
+                               const char              *country_code,
+                               int                     limit,
+                               double                  left,
+                               double                  top,
+                               double                  right,
+                               double                  bottom,
+                               int                     *count,
+                               GPtrArray               **landmark,
+                               GError                  **error)
+{
+       return GC_IFACE_POI_GET_CLASS (gc)->search_by_position
+               (gc, keyword, lang, country_code, limit, left, top, right, bottom, count, landmark, error);
+}
diff --git a/geoclue/gc-iface-poi.h b/geoclue/gc-iface-poi.h
new file mode 100644 (file)
index 0000000..4710435
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Geoclue
+ * gc-iface-poi.h - GInterface for org.freedesktop.Poi
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GC_IFACE_POI_H
+#define _GC_IFACE_POI_H
+
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_IFACE_POI (gc_iface_poi_get_type ())
+#define GC_IFACE_POI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_IFACE_POI, GcIfacePoi))
+#define GC_IFACE_POI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GC_TYPE_IFACE_POI, GcIfacePoiClass))
+#define GC_IS_IFACE_POI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GC_TYPE_IFACE_POI))
+#define GC_IS_IFACE_POI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GC_TYPE_IFACE_POI))
+#define GC_IFACE_POI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GC_TYPE_IFACE_POI, GcIfacePoiClass))
+
+typedef struct _GcIfacePoi GcIfacePoi; /* Dummy typedef */
+typedef struct _GcIfacePoiClass GcIfacePoiClass;
+
+struct _GcIfacePoiClass {
+       GTypeInterface base_iface;
+
+       /* vtable */
+       gboolean (*search_by_position) (GcIfacePoi      *gc,
+                                       const char      *keyword,
+                                       const char      *lang,
+                                       const char      *country_code,
+                                       int             limit,
+                                       double          left,
+                                       double          top,
+                                       double          right,
+                                       double          bottom,
+                                       int             *count,
+                                       GPtrArray       **landmark,
+                                       GError         **error);
+};
+
+GType gc_iface_poi_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/gc-iface-position-ext.c b/geoclue/gc-iface-position-ext.c
new file mode 100644 (file)
index 0000000..a647258
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Geoclue
+ * gc-iface-position.c - GInterface for org.freedesktop.Geoclue.Position
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <glib.h>
+
+#include <dbus/dbus-glib.h>
+#include <geoclue/gc-iface-position-ext.h>
+#include <geoclue/geoclue-marshal.h>
+#include <geoclue/geoclue-accuracy.h>
+
+enum {
+       POSITION_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+static gboolean
+gc_iface_position_ext_get_position (GcIfacePositionExt *position,
+                                                 int                           *fields,
+                                                 int                           *timestamp,
+                                                 double                        *latitude,
+                                                 double                        *longitude,
+                                                 double                        *altitude,
+                                                 double                        *speed,
+                                                 double                        *direction,
+                                                 double                        *climb,
+                                                 GeoclueAccuracy               **accuracy,
+                                                 GError                        **error);
+
+static gboolean
+gc_iface_position_ext_get_last_position (GcIfacePositionExt    *position,
+                                    int                        *fields,
+                                    int                        *timestamp,
+                                    double                     *latitude,
+                                    double                     *longitude,
+                                    double                     *altitude,
+                                    double                     *speed,
+                                    double                     *direction,
+                                    double                     *climb,
+                                    GeoclueAccuracy            **accuracy,
+                                    GError                     **error);
+
+#include "gc-iface-position-ext-glue.h"
+
+static void
+gc_iface_position_ext_base_init (gpointer klass)
+{
+       static gboolean initialized = FALSE;
+
+       if (initialized) {
+               return;
+       }
+       initialized = TRUE;
+
+       signals[POSITION_CHANGED] = g_signal_new ("position-changed",
+                                                 G_OBJECT_CLASS_TYPE (klass),
+                                                 G_SIGNAL_RUN_LAST, 0,
+                                                 NULL, NULL,
+                                                 geoclue_marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE_DOUBLE_DOUBLE_DOUBLE_BOXED,
+                                                 G_TYPE_NONE, 9,
+                                                 G_TYPE_INT,
+                                                 G_TYPE_INT,
+                                                 G_TYPE_DOUBLE,
+                                                 G_TYPE_DOUBLE,
+                                                 G_TYPE_DOUBLE,
+                                                 G_TYPE_DOUBLE,
+                                                 G_TYPE_DOUBLE,
+                                                 G_TYPE_DOUBLE,
+                                                 GEOCLUE_ACCURACY_TYPE);
+
+       dbus_g_object_type_install_info (gc_iface_position_ext_get_type (),
+                                        &dbus_glib_gc_iface_position_ext_object_info);
+}
+
+GType
+gc_iface_position_ext_get_type (void)
+{
+       static GType type = 0;
+
+       if (!type) {
+               const GTypeInfo info = {
+                       sizeof (GcIfacePositionExtClass),
+                       gc_iface_position_ext_base_init,
+                       NULL,
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                                              "GcIfacePositionExt", &info, 0);
+       }
+
+       return type;
+}
+
+static gboolean
+gc_iface_position_ext_get_position (GcIfacePositionExt *gc,
+                                                 int                           *fields,
+                                                 int                           *timestamp,
+                                                 double                        *latitude,
+                                                 double                        *longitude,
+                                                 double                        *altitude,
+                                                 double                        *speed,
+                                                 double                        *direction,
+                                                 double                        *climb,
+                                                 GeoclueAccuracy               **accuracy,
+                                                 GError                        **error)
+{
+       return GC_IFACE_POSITION_EXT_GET_CLASS (gc)->get_position
+               (gc, (GeocluePositionExtFields *) fields, timestamp,
+                latitude, longitude, altitude, speed, direction, climb, accuracy, error);
+}
+
+static gboolean
+gc_iface_position_ext_get_last_position (GcIfacePositionExt    *gc,
+                                                      int                      *fields,
+                                                      int                      *timestamp,
+                                                      double                   *latitude,
+                                                      double                   *longitude,
+                                                      double                   *altitude,
+                                                      double                   *speed,
+                                                      double                   *direction,
+                                                      double                   *climb,
+                                                      GeoclueAccuracy          **accuracy,
+                                                      GError                   **error)
+{
+       return GC_IFACE_POSITION_EXT_GET_CLASS (gc)->get_last_position
+               (gc, (GeocluePositionExtFields *) fields, timestamp,
+                latitude, longitude, altitude, speed, direction, climb, accuracy, error);
+}
+
+void
+gc_iface_position_ext_emit_position_changed (GcIfacePositionExt        *gc,
+                                                          GeocluePositionExtFields     fields,
+                                                          int                          timestamp,
+                                                          double                       latitude,
+                                                          double                       longitude,
+                                                          double                       altitude,
+                                                          double                       speed,
+                                                          double                       direction,
+                                                          double                       climb,
+                                                          GeoclueAccuracy      *accuracy)
+{
+       g_signal_emit (gc, signals[POSITION_CHANGED], 0, fields, timestamp,
+                      latitude, longitude, altitude, speed, direction, climb, accuracy);
+}
diff --git a/geoclue/gc-iface-position-ext.h b/geoclue/gc-iface-position-ext.h
new file mode 100644 (file)
index 0000000..d28c3d9
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Geoclue
+ * gc-iface-position-ext.h - GInterface for org.freedesktop.Geoclue.PositionExt
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GC_IFACE_POSITION_EXT_H
+#define _GC_IFACE_POSITION_EXT_H
+
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_IFACE_POSITION_EXT (gc_iface_position_ext_get_type ())
+#define GC_IFACE_POSITION_EXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_IFACE_POSITION_EXT, GcIfacePositionExt))
+#define GC_IFACE_POSITION_EXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GC_TYPE_IFACE_POSITION_EXT, GcIfacePositionExtClass))
+#define GC_IS_IFACE_POSITION_EXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GC_TYPE_IFACE_POSITION_VELOCITY))
+#define GC_IS_IFACE_POSITION_EXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GC_TYPE_IFACE_POSITION_EXT))
+#define GC_IFACE_POSITION_EXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GC_TYPE_IFACE_POSITION_EXT, GcIfacePositionExtClass))
+
+typedef struct _GcIfacePositionExt GcIfacePositionExt; /* Dummy typedef */
+typedef struct _GcIfacePositionExtClass GcIfacePositionExtClass;
+
+struct _GcIfacePositionExtClass {
+        GTypeInterface base_iface;
+
+       /* signals */
+       void (* position_changed) (GcIfacePositionExt      *gc,
+                                  GeocluePositionExtFields fields,
+                                  int                   timestamp,
+                                  double                latitude,
+                                  double                longitude,
+                                  double                altitude,
+                                  double                speed,
+                                  double                direction,
+                                  double                climb,
+                                  GeoclueAccuracy      *accuracy);
+
+       /* vtable */
+       gboolean (* get_position) (GcIfacePositionExt       *gc,
+                                  GeocluePositionExtFields *fields,
+                                  int                   *timestamp,
+                                  double                *latitude,
+                                  double                *longitude,
+                                  double                *altitude,
+                                  double                *speed,
+                                  double                *direction,
+                                  double                *climb,
+                                  GeoclueAccuracy      **accuracy,
+                                  GError               **error);
+
+       /* vtable */
+       gboolean (* get_last_position) (GcIfacePositionExt      *gc,
+                                       GeocluePositionExtFields        *fields,
+                                       int                     *timestamp,
+                                       double                  *latitude,
+                                       double                  *longitude,
+                                       double                  *altitude,
+                                       double                  *speed,
+                                       double                  *direction,
+                                       double                  *climb,
+                                       GeoclueAccuracy         **accuracy,
+                                       GError                  **error);
+};
+
+GType gc_iface_position_ext_get_type (void);
+
+void gc_iface_position_ext_emit_position_changed (GcIfacePositionExt      *gc,
+                                             GeocluePositionExtFields fields,
+                                             int                   timestamp,
+                                             double                latitude,
+                                             double                longitude,
+                                             double                altitude,
+                                             double                speed,
+                                             double                direction,
+                                             double                climb,
+                                             GeoclueAccuracy      *accuracy);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/gc-iface-position.c b/geoclue/gc-iface-position.c
new file mode 100644 (file)
index 0000000..f6cb430
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Geoclue
+ * gc-iface-position.c - GInterface for org.freedesktop.Geoclue.Position
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <glib.h>
+
+#include <dbus/dbus-glib.h>
+#include <geoclue/gc-iface-position.h>
+#include <geoclue/geoclue-marshal.h>
+#include <geoclue/geoclue-accuracy.h>
+
+enum {
+       POSITION_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+static gboolean
+gc_iface_position_get_position (GcIfacePosition       *position,
+                               int                   *fields,
+                               int                   *timestamp,
+                               double                *latitude,
+                               double                *longitude,
+                               double                *altitude,
+                               GeoclueAccuracy      **accuracy,
+                               GError               **error);
+
+static gboolean
+gc_iface_position_get_last_position (GcIfacePosition   *position,
+                                    int                *fields,
+                                    int                *timestamp,
+                                    double             *latitude,
+                                    double             *longitude,
+                                    double             *altitude,
+                                    GeoclueAccuracy    **accuracy,
+                                    GError             **error);
+
+#include "gc-iface-position-glue.h"
+
+static void
+gc_iface_position_base_init (gpointer klass)
+{
+       static gboolean initialized = FALSE;
+
+       if (initialized) {
+               return;
+       }
+       initialized = TRUE;
+
+       signals[POSITION_CHANGED] = g_signal_new ("position-changed",
+                                                 G_OBJECT_CLASS_TYPE (klass),
+                                                 G_SIGNAL_RUN_LAST, 0,
+                                                 NULL, NULL,
+                                                 geoclue_marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE_BOXED,
+                                                 G_TYPE_NONE, 6,
+                                                 G_TYPE_INT,
+                                                 G_TYPE_INT,
+                                                 G_TYPE_DOUBLE,
+                                                 G_TYPE_DOUBLE,
+                                                 G_TYPE_DOUBLE,
+                                                 GEOCLUE_ACCURACY_TYPE);
+
+       dbus_g_object_type_install_info (gc_iface_position_get_type (),
+                                        &dbus_glib_gc_iface_position_object_info);
+}
+
+GType
+gc_iface_position_get_type (void)
+{
+       static GType type = 0;
+
+       if (!type) {
+               const GTypeInfo info = {
+                       sizeof (GcIfacePositionClass),
+                       gc_iface_position_base_init,
+                       NULL,
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                                              "GcIfacePosition", &info, 0);
+       }
+
+       return type;
+}
+
+static gboolean
+gc_iface_position_get_position (GcIfacePosition  *gc,
+                               int              *fields,
+                               int              *timestamp,
+                               double           *latitude,
+                               double           *longitude,
+                               double           *altitude,
+                               GeoclueAccuracy **accuracy,
+                               GError          **error)
+{
+       return GC_IFACE_POSITION_GET_CLASS (gc)->get_position
+               (gc, (GeocluePositionFields *) fields, timestamp,
+                latitude, longitude, altitude, accuracy, error);
+}
+
+static gboolean
+gc_iface_position_get_last_position (GcIfacePosition   *gc,
+                                    int                *fields,
+                                    int                *timestamp,
+                                    double             *latitude,
+                                    double             *longitude,
+                                    double             *altitude,
+                                    GeoclueAccuracy    **accuracy,
+                                    GError             **error)
+{
+       return GC_IFACE_POSITION_GET_CLASS (gc)->get_last_position
+               (gc, (GeocluePositionFields *) fields, timestamp,
+                latitude, longitude, altitude, accuracy, error);
+}
+
+void
+gc_iface_position_emit_position_changed (GcIfacePosition      *gc,
+                                        GeocluePositionFields fields,
+                                        int                   timestamp,
+                                        double                latitude,
+                                        double                longitude,
+                                        double                altitude,
+                                        GeoclueAccuracy      *accuracy)
+{
+       g_signal_emit (gc, signals[POSITION_CHANGED], 0, fields, timestamp,
+                      latitude, longitude, altitude, accuracy);
+}
diff --git a/geoclue/gc-iface-position.h b/geoclue/gc-iface-position.h
new file mode 100644 (file)
index 0000000..451f19c
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Geoclue
+ * gc-iface-position.h - GInterface for org.freedesktop.Geoclue.Position
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GC_IFACE_POSITION_H
+#define _GC_IFACE_POSITION_H
+
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_IFACE_POSITION (gc_iface_position_get_type ())
+#define GC_IFACE_POSITION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_IFACE_POSITION, GcIfacePosition))
+#define GC_IFACE_POSITION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GC_TYPE_IFACE_POSITION, GcIfacePositionClass))
+#define GC_IS_IFACE_POSITION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GC_TYPE_IFACE_POSITION))
+#define GC_IS_IFACE_POSITION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GC_TYPE_IFACE_POSITION))
+#define GC_IFACE_POSITION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GC_TYPE_IFACE_POSITION, GcIfacePositionClass))
+
+typedef struct _GcIfacePosition GcIfacePosition; /* Dummy typedef */
+typedef struct _GcIfacePositionClass GcIfacePositionClass;
+
+struct _GcIfacePositionClass {
+        GTypeInterface base_iface;
+
+       /* signals */
+       void (* position_changed) (GcIfacePosition      *gc,
+                                  GeocluePositionFields fields,
+                                  int                   timestamp,
+                                  double                latitude,
+                                  double                longitude,
+                                  double                altitude,
+                                  GeoclueAccuracy      *accuracy);
+
+       /* vtable */
+       gboolean (* get_position) (GcIfacePosition       *gc,
+                                  GeocluePositionFields *fields,
+                                  int                   *timestamp,
+                                  double                *latitude,
+                                  double                *longitude,
+                                  double                *altitude,
+                                  GeoclueAccuracy      **accuracy,
+                                  GError               **error);
+
+       /* vtable */
+       gboolean (* get_last_position) (GcIfacePosition         *gc,
+                                       GeocluePositionFields   *fields,
+                                       int                     *timestamp,
+                                       double                  *latitude,
+                                       double                  *longitude,
+                                       double                  *altitude,
+                                       GeoclueAccuracy         **accuracy,
+                                       GError                  **error);
+};
+
+GType gc_iface_position_get_type (void);
+
+void gc_iface_position_emit_position_changed (GcIfacePosition      *gc,
+                                             GeocluePositionFields fields,
+                                             int                   timestamp,
+                                             double                latitude,
+                                             double                longitude,
+                                             double                altitude,
+                                             GeoclueAccuracy      *accuracy);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/gc-iface-reverse-geocode.c b/geoclue/gc-iface-reverse-geocode.c
new file mode 100644 (file)
index 0000000..517d903
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Geoclue
+ * gc-iface-reverse-geocode.c - GInterface for org.freedesktop.ReverseGeocode
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <glib.h>
+
+#include <dbus/dbus-glib.h>
+
+#include <geoclue/geoclue-accuracy.h>
+#include <geoclue/gc-iface-reverse-geocode.h>
+
+static gboolean
+gc_iface_reverse_geocode_position_to_address (GcIfaceReverseGeocode  *gc,
+                                             double                  latitude,
+                                             double                  longitude,
+                                             GeoclueAccuracy        *position_accuracy,
+                                             GHashTable            **address,
+                                             GeoclueAccuracy       **address_accuracy,
+                                             GError                **error);
+#include "gc-iface-reverse-geocode-glue.h"
+
+static void
+gc_iface_reverse_geocode_base_init (gpointer klass)
+{
+       static gboolean initialized = FALSE;
+
+       if (initialized) {
+               return;
+       }
+       initialized = TRUE;
+
+       dbus_g_object_type_install_info (gc_iface_reverse_geocode_get_type (),
+                                        &dbus_glib_gc_iface_reverse_geocode_object_info);
+}
+
+GType
+gc_iface_reverse_geocode_get_type (void)
+{
+       static GType type = 0;
+
+       if (!type) {
+               const GTypeInfo info = {
+                       sizeof (GcIfaceReverseGeocodeClass),
+                       gc_iface_reverse_geocode_base_init,
+                       NULL,
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                                              "GcIfaceReverseGeocode", &info, 0);
+       }
+
+       return type;
+}
+
+static gboolean
+gc_iface_reverse_geocode_position_to_address (GcIfaceReverseGeocode  *gc,
+                                             double                  latitude,
+                                             double                  longitude,
+                                             GeoclueAccuracy        *position_accuracy,
+                                             GHashTable            **address,
+                                             GeoclueAccuracy       **address_accuracy,
+                                             GError                **error)
+{
+       return GC_IFACE_REVERSE_GEOCODE_GET_CLASS (gc)->position_to_address
+               (gc, latitude, longitude, position_accuracy,
+                address, address_accuracy, error);
+}
diff --git a/geoclue/gc-iface-reverse-geocode.h b/geoclue/gc-iface-reverse-geocode.h
new file mode 100644 (file)
index 0000000..835225a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Geoclue
+ * gc-iface-reverse_geocode.h - GInterface for org.freedesktop.Reverse_Geocode
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GC_IFACE_REVERSE_GEOCODE_H
+#define _GC_IFACE_REVERSE_GEOCODE_H
+
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_IFACE_REVERSE_GEOCODE (gc_iface_reverse_geocode_get_type ())
+#define GC_IFACE_REVERSE_GEOCODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_IFACE_REVERSE_GEOCODE, GcIfaceReverseGeocode))
+#define GC_IFACE_REVERSE_GEOCODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GC_TYPE_IFACE_REVERSE_GEOCODE, GcIfaceReverseGeocodeClass))
+#define GC_IS_IFACE_REVERSE_GEOCODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GC_TYPE_IFACE_REVERSE_GEOCODE))
+#define GC_IS_IFACE_REVERSE_GEOCODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GC_TYPE_IFACE_REVERSE_GEOCODE))
+#define GC_IFACE_REVERSE_GEOCODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GC_TYPE_IFACE_REVERSE_GEOCODE, GcIfaceReverseGeocodeClass))
+
+typedef struct _GcIfaceReverseGeocode GcIfaceReverseGeocode; /* Dummy typedef */
+typedef struct _GcIfaceReverseGeocodeClass GcIfaceReverseGeocodeClass;
+
+struct _GcIfaceReverseGeocodeClass {
+       GTypeInterface base_iface;
+
+       /* vtable */
+       gboolean (*position_to_address) (GcIfaceReverseGeocode  *gc,
+                                        double                  latitude,
+                                        double                  longitude,
+                                        GeoclueAccuracy        *position_accuracy,
+                                        GHashTable            **address,
+                                        GeoclueAccuracy       **address_accuracy,
+                                        GError                **error);
+};
+
+GType gc_iface_reverse_geocode_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/gc-iface-satellite.c b/geoclue/gc-iface-satellite.c
new file mode 100644 (file)
index 0000000..cab30a1
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Geoclue
+ * gc-iface-satellite.c - GInterface for org.freedesktop.Geoclue.Satellite
+ *
+ * Author: Sagnho Park <sangho.g.park@samsung.com>, Youngae Kang <youngae.kang@samsung.com>,
+ *         Yunhan Kim <yhan.kim@samsung.com>, Genie Kim <daejins.kim@samsung.com>
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <glib.h>
+
+#include <dbus/dbus-glib.h>
+#include <geoclue/gc-iface-satellite.h>
+#include <geoclue/geoclue-marshal.h>
+
+enum {
+       SATELLITE_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+static gboolean
+gc_iface_satellite_get_satellite (GcIfaceSatellite *satellite,
+                                 int              *timestamp,
+                                 int              *satellite_used,
+                                 int              *satellite_visible,
+                                 GArray          **used_prn,
+                                 GPtrArray       **sat_info,
+                                 GError          **error);
+
+static gboolean
+gc_iface_satellite_get_last_satellite (GcIfaceSatellite *satellite,
+                                      int              *timestamp,
+                                      int              *satellite_used,
+                                      int              *satellite_visible,
+                                      GArray           **used_prn,
+                                      GPtrArray        **sat_info,
+                                      GError           **error);
+
+#include "gc-iface-satellite-glue.h"
+
+static void
+gc_iface_satellite_base_init (gpointer klass)
+{
+       static gboolean initialized = FALSE;
+
+       if (initialized) {
+               return;
+       }
+       initialized = TRUE;
+
+       signals[SATELLITE_CHANGED] = g_signal_new ("satellite-changed",
+                                                  G_OBJECT_CLASS_TYPE (klass),
+                                                  G_SIGNAL_RUN_LAST, 0,
+                                                  NULL, NULL,
+                                                  geoclue_marshal_VOID__INT_INT_INT_POINTER_POINTER,
+                                                  G_TYPE_NONE, 5,
+                                                  G_TYPE_INT,
+                                                  G_TYPE_INT,
+                                                  G_TYPE_INT,
+                                                  DBUS_TYPE_G_INT_ARRAY,
+                                                  GEOCLUE_SATELLITE_INFO_ARRAY);
+       dbus_g_object_type_install_info (gc_iface_satellite_get_type (),
+                                        &dbus_glib_gc_iface_satellite_object_info);
+}
+
+GType
+gc_iface_satellite_get_type (void)
+{
+       static GType type = 0;
+
+       if (!type) {
+               const GTypeInfo info = {
+                       sizeof (GcIfaceSatelliteClass),
+                       gc_iface_satellite_base_init,
+                       NULL,
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                                              "GcIfaceSatellite", &info, 0);
+       }
+
+       return type;
+}
+
+static gboolean
+gc_iface_satellite_get_satellite (GcIfaceSatellite *gc,
+                                 int              *timestamp,
+                                 int              *satellite_used,
+                                 int              *satellite_visible,
+                                 GArray          **used_prn,
+                                 GPtrArray       **sat_info,
+                                 GError          **error)
+{
+       return GC_IFACE_SATELLITE_GET_CLASS (gc)->get_satellite (gc,
+                                                                timestamp,
+                                                                satellite_used,
+                                                                satellite_visible,
+                                                                used_prn,
+                                                                sat_info,
+                                                                error);
+}
+
+static gboolean
+gc_iface_satellite_get_last_satellite (GcIfaceSatellite *gc,
+                                      int              *timestamp,
+                                      int              *satellite_used,
+                                      int              *satellite_visible,
+                                      GArray          **used_prn,
+                                      GPtrArray       **sat_info,
+                                      GError          **error)
+{
+       return GC_IFACE_SATELLITE_GET_CLASS (gc)->get_last_satellite (gc,
+                                                                     timestamp,
+                                                                     satellite_used,
+                                                                     satellite_visible,
+                                                                     used_prn,
+                                                                     sat_info,
+                                                                     error);
+}
+
+void
+gc_iface_satellite_emit_satellite_changed (GcIfaceSatellite *gc,
+                                          int               timestamp,
+                                          int               satellite_used,
+                                          int               satellite_visible,
+                                          GArray           *used_prn,
+                                          GPtrArray        *sat_info)
+{
+       g_signal_emit (gc, signals[SATELLITE_CHANGED], 0,
+                      timestamp, satellite_used, satellite_visible,
+                      used_prn, sat_info);
+}
diff --git a/geoclue/gc-iface-satellite.h b/geoclue/gc-iface-satellite.h
new file mode 100644 (file)
index 0000000..dffb0ea
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Geoclue
+ * gc-iface-satellite.c - GInterface for org.freedesktop.Geoclue.Satellite
+ *
+ * Author: Sagnho Park <sangho.g.park@samsung.com>, Youngae Kang <youngae.kang@samsung.com>,
+ *         Yunhan Kim <yhan.kim@samsung.com>, Genie Kim <daejins.kim@samsung.com>
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GC_IFACE_SATELLITE_H
+#define _GC_IFACE_SATELLITE_H
+
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-satellite-info.h>
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_IFACE_SATELLITE (gc_iface_satellite_get_type ())
+#define GC_IFACE_SATELLITE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_IFACE_SATELLITE, GcIfaceSatellite))
+#define GC_IFACE_SATELLITE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GC_TYPE_IFACE_SATELLITE, GcIfaceSatelliteClass))
+#define GC_IS_IFACE_SATELLITE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GC_TYPE_IFACE_SATELLITE))
+#define GC_IS_IFACE_SATELLITE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GC_TYPE_IFACE_SATELLITE))
+#define GC_IFACE_SATELLITE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GC_TYPE_IFACE_SATELLITE, GcIfaceSatelliteClass))
+
+typedef struct _GcIfaceSatellite GcIfaceSatellite; /* Dummy typedef */
+typedef struct _GcIfaceSatelliteClass GcIfaceSatelliteClass;
+
+struct _GcIfaceSatelliteClass {
+        GTypeInterface base_iface;
+
+       /* signals */
+       void (* satellite_changed) (GcIfaceSatellite *gc,
+                                   int               timestamp,
+                                   int               satellite_used,
+                                   int               satellite_visible,
+                                   GArray           *used_prn,
+                                   GPtrArray        *sat_info);
+
+       /* vtable */
+       gboolean (* get_satellite) (GcIfaceSatellite *gc,
+                                   int              *timestamp,
+                                   int              *satellite_used,
+                                   int              *satellite_visible,
+                                   GArray          **used_prn,
+                                   GPtrArray       **sat_info,
+                                   GError          **error);
+
+       /* vtable */
+       gboolean (* get_last_satellite) (GcIfaceSatellite *gc,
+                                        int              *timestamp,
+                                        int              *satellite_used,
+                                        int              *satellite_visible,
+                                        GArray          **used_prn,
+                                        GPtrArray       **sat_info,
+                                        GError          **error);
+};
+
+GType gc_iface_satellite_get_type (void);
+
+void gc_iface_satellite_emit_satellite_changed (GcIfaceSatellite *gc,
+                                               int               timestamp,
+                                               int               satellite_used,
+                                               int               satellite_visible,
+                                               GArray           *used_prn,
+                                               GPtrArray        *sat_info);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/gc-iface-velocity.c b/geoclue/gc-iface-velocity.c
new file mode 100644 (file)
index 0000000..ba15b45
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Geoclue
+ * gc-iface-velocity.c - GInterface for org.freedesktop.Geoclue.Velocity
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <glib.h>
+
+#include <dbus/dbus-glib.h>
+#include <geoclue/gc-iface-velocity.h>
+#include <geoclue/geoclue-marshal.h>
+
+enum {
+       VELOCITY_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+static gboolean
+gc_iface_velocity_get_velocity (GcIfaceVelocity       *velocity,
+                               int                   *fields,
+                               int                   *timestamp,
+                               double                *latitude,
+                               double                *longitude,
+                               double                *altitude,
+                               GError               **error);
+
+static gboolean
+gc_iface_velocity_get_last_velocity (GcIfaceVelocity       *velocity,
+                                    int                   *fields,
+                                    int                   *timestamp,
+                                    double                *latitude,
+                                    double                *longitude,
+                                    double                *altitude,
+                                    GError               **error);
+
+#include "gc-iface-velocity-glue.h"
+
+static void
+gc_iface_velocity_base_init (gpointer klass)
+{
+       static gboolean initialized = FALSE;
+
+       if (initialized) {
+               return;
+       }
+       initialized = TRUE;
+
+       signals[VELOCITY_CHANGED] = g_signal_new ("velocity-changed",
+                                                 G_OBJECT_CLASS_TYPE (klass),
+                                                 G_SIGNAL_RUN_LAST, 0,
+                                                 NULL, NULL,
+                                                 geoclue_marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE,
+                                                 G_TYPE_NONE, 5,
+                                                 G_TYPE_INT,
+                                                 G_TYPE_INT,
+                                                 G_TYPE_DOUBLE,
+                                                 G_TYPE_DOUBLE,
+                                                 G_TYPE_DOUBLE);
+       dbus_g_object_type_install_info (gc_iface_velocity_get_type (),
+                                        &dbus_glib_gc_iface_velocity_object_info);
+}
+
+GType
+gc_iface_velocity_get_type (void)
+{
+       static GType type = 0;
+
+       if (!type) {
+               const GTypeInfo info = {
+                       sizeof (GcIfaceVelocityClass),
+                       gc_iface_velocity_base_init,
+                       NULL,
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                                              "GcIfaceVelocity", &info, 0);
+       }
+
+       return type;
+}
+
+static gboolean
+gc_iface_velocity_get_velocity (GcIfaceVelocity *gc,
+                               int             *fields,
+                               int             *timestamp,
+                               double          *speed,
+                               double          *direction,
+                               double          *climb,
+                               GError         **error)
+{
+       return GC_IFACE_VELOCITY_GET_CLASS (gc)->get_velocity
+               (gc, (GeoclueVelocityFields *) fields, timestamp,
+                speed, direction, climb, error);
+}
+
+static gboolean
+gc_iface_velocity_get_last_velocity (GcIfaceVelocity *gc,
+                                    int             *fields,
+                                    int             *timestamp,
+                                    double          *speed,
+                                    double          *direction,
+                                    double          *climb,
+                                    GError         **error)
+{
+       return GC_IFACE_VELOCITY_GET_CLASS (gc)->get_last_velocity
+               (gc, (GeoclueVelocityFields *) fields, timestamp,
+                speed, direction, climb, error);
+}
+
+void
+gc_iface_velocity_emit_velocity_changed (GcIfaceVelocity      *gc,
+                                        GeoclueVelocityFields fields,
+                                        int                   timestamp,
+                                        double                speed,
+                                        double                direction,
+                                        double                climb)
+{
+       g_signal_emit (gc, signals[VELOCITY_CHANGED], 0, fields, timestamp,
+                      speed, direction, climb);
+}
diff --git a/geoclue/gc-iface-velocity.h b/geoclue/gc-iface-velocity.h
new file mode 100644 (file)
index 0000000..94c55ac
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Geoclue
+ * gc-iface-velocity.h - GInterface for org.freedesktop.Geoclue.Velocity
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GC_IFACE_VELOCITY_H
+#define _GC_IFACE_VELOCITY_H
+
+#include <geoclue/geoclue-types.h>
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_IFACE_VELOCITY (gc_iface_velocity_get_type ())
+#define GC_IFACE_VELOCITY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_IFACE_VELOCITY, GcIfaceVelocity))
+#define GC_IFACE_VELOCITY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GC_TYPE_IFACE_VELOCITY, GcIfaceVelocityClass))
+#define GC_IS_IFACE_VELOCITY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GC_TYPE_IFACE_VELOCITY))
+#define GC_IS_IFACE_VELOCITY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GC_TYPE_IFACE_VELOCITY))
+#define GC_IFACE_VELOCITY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GC_TYPE_IFACE_VELOCITY, GcIfaceVelocityClass))
+
+typedef struct _GcIfaceVelocity GcIfaceVelocity; /* Dummy typedef */
+typedef struct _GcIfaceVelocityClass GcIfaceVelocityClass;
+
+struct _GcIfaceVelocityClass {
+       GTypeInterface base_iface;
+
+       /* signals */
+       void (* velocity_changed) (GcIfaceVelocity      *gc,
+                                  GeoclueVelocityFields fields,
+                                  int                   timestamp,
+                                  double                speed,
+                                  double                direction,
+                                  double                climb);
+
+       /* vtable */
+       gboolean (* get_velocity) (GcIfaceVelocity       *gc,
+                                  GeoclueVelocityFields *fields,
+                                  int                   *timestamp,
+                                  double                *speed,
+                                  double                *direction,
+                                  double                *climb,
+                                  GError               **error);
+
+       /* vtable */
+       gboolean (* get_last_velocity) (GcIfaceVelocity         *gc,
+                                       GeoclueVelocityFields   *fields,
+                                       int                     *timestamp,
+                                       double                  *speed,
+                                       double                  *direction,
+                                       double                  *climb,
+                                       GError                  **error);
+};
+
+GType gc_iface_velocity_get_type (void);
+
+void gc_iface_velocity_emit_velocity_changed (GcIfaceVelocity      *gc,
+                                             GeoclueVelocityFields fields,
+                                             int                   timestamp,
+                                             double                speed,
+                                             double                direction,
+                                             double                climb);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/gc-provider.c b/geoclue/gc-provider.c
new file mode 100644 (file)
index 0000000..8330953
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * Geoclue
+ * gc-provider.c - A provider object that handles the basic D-Bus required for
+ *                 a provider.
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:gc-provider
+ * @short_description: Abstract class to derive Geoclue providers from.
+ *
+ * #GcProvider is an abstract class that all Geoclue providers should
+ * derive from. It takes care of setting up the provider D-Bus service,
+ * and also implements #GcIfaceGeoclue interface (derived classes still
+ * need to implement the functionality).
+ *
+ * Derived classes should define the #GcIfaceGeoclue methods in their
+ * class_init() and call gc_provider_set_details() in init()
+ *
+ */
+#include <config.h>
+
+#include <string.h>
+#include <glib-object.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-bindings.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <geoclue/geoclue-error.h>
+#include <geoclue/gc-provider.h>
+
+
+typedef struct {
+       char *name;
+       char *description;
+
+       GHashTable *connections;
+} GcProviderPrivate;
+
+#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GC_TYPE_PROVIDER, GcProviderPrivate))
+
+static void gc_provider_geoclue_init (GcIfaceGeoclueClass *iface);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GcProvider, gc_provider, G_TYPE_OBJECT,
+                                 G_IMPLEMENT_INTERFACE(GC_TYPE_IFACE_GEOCLUE,
+                                                       gc_provider_geoclue_init))
+
+static void
+finalize (GObject *object)
+{
+       GcProviderPrivate *priv = GET_PRIVATE (object);
+
+       g_free (priv->name);
+       g_free (priv->description);
+
+       ((GObjectClass *) gc_provider_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       GcProviderPrivate *priv = GET_PRIVATE (object);
+
+       g_hash_table_destroy (priv->connections);
+
+       ((GObjectClass *) gc_provider_parent_class)->dispose (object);
+}
+
+static void
+gc_provider_class_init (GcProviderClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+
+       klass->shutdown = NULL;
+
+       g_type_class_add_private (klass, sizeof (GcProviderPrivate));
+}
+
+static void
+gc_provider_init (GcProvider *provider)
+{
+       GError *error = NULL;
+       GcProviderPrivate *priv = GET_PRIVATE (provider);
+
+       provider->connection = dbus_g_bus_get (GEOCLUE_DBUS_BUS, &error);
+       if (provider->connection == NULL) {
+               g_warning ("%s was unable to create a connection to D-Bus: %s",
+                          G_OBJECT_TYPE_NAME (provider), error->message);
+               g_error_free (error);
+       }
+
+       priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+}
+
+
+static void
+gc_provider_shutdown (GcProvider *provider)
+{
+       GC_PROVIDER_GET_CLASS (provider)->shutdown (provider);
+}
+
+
+static gboolean
+get_provider_info (GcIfaceGeoclue *geoclue,
+                  gchar          **name,
+                  gchar          **description,
+                  GError        **error)
+{
+       GcProvider *provider = GC_PROVIDER (geoclue);
+       GcProviderPrivate *priv = GET_PRIVATE (provider);
+
+       if (name) {
+               *name = g_strdup (priv->name);
+       }
+       if (description) {
+               *description = g_strdup (priv->description);
+       }
+
+       return TRUE;
+}
+
+static gboolean
+get_status (GcIfaceGeoclue *geoclue,
+           GeoclueStatus  *status,
+           GError        **error)
+{
+       GcProviderClass *klass;
+
+       klass = GC_PROVIDER_GET_CLASS (geoclue);
+       if (klass->get_status) {
+               return klass->get_status (geoclue, status, error);
+       } else {
+               *error = g_error_new (GEOCLUE_ERROR,
+                                     GEOCLUE_ERROR_NOT_IMPLEMENTED,
+                                     "get_status is not implemented");
+               return FALSE;
+       }
+}
+
+static gboolean
+set_options (GcIfaceGeoclue *geoclue,
+             GHashTable     *options,
+             GError        **error)
+{
+       GcProviderClass *klass;
+
+       klass = GC_PROVIDER_GET_CLASS (geoclue);
+       if (klass->set_options) {
+               return klass->set_options (geoclue, options, error);
+       }
+
+        /* It is not an error to not have a SetOptions implementation */
+        return TRUE;
+}
+
+static gboolean
+gc_provider_remove_client (GcProvider *provider, const char *client)
+{
+       int *pcount;
+       GcProviderPrivate *priv = GET_PRIVATE (provider);
+
+       pcount = g_hash_table_lookup (priv->connections, client);
+       if (!pcount) {
+               g_debug("Client[%s] is already removed", client);
+               return FALSE;
+       }
+       (*pcount)--;
+       g_debug("Client[%s] has reference count[%d]", client, *pcount);
+       if (*pcount == 0) {
+               g_debug("Reference count is zero, Now remove client[%s] in hash table", client);
+               g_hash_table_remove (priv->connections, client);
+       }
+       if (g_hash_table_size (priv->connections) == 0) {
+               g_debug("Hash table size is zero, Now we shutdown provider[%s]", priv->name);
+               gc_provider_shutdown (provider);
+       }
+       return TRUE;
+}
+
+static gboolean
+gc_provider_remove_client_by_force(GcProvider *provider, const char *client)
+{
+       int *pcount;
+       GcProviderPrivate *priv = GET_PRIVATE (provider);
+
+       pcount = g_hash_table_lookup (priv->connections, client);
+       if(!pcount){
+               g_debug("Client(%s) is already removed", client);
+               return FALSE;
+       }
+
+       (*pcount)--;
+       g_debug("Client(%s) has reference count[%d]. Anway, we will remove it by force!", client, *pcount);
+       g_hash_table_remove (priv->connections, client);
+       if (g_hash_table_size (priv->connections) == 0) {
+               g_debug("Hash table size is zero, Now we shutdown provider[%s]", priv->name);
+               gc_provider_shutdown (provider);
+       }
+       return TRUE;
+}
+
+
+static void
+add_reference (GcIfaceGeoclue *geoclue,
+               DBusGMethodInvocation *context)
+{
+       GcProviderPrivate *priv = GET_PRIVATE (geoclue);
+       char *sender;
+       int *pcount;
+
+       /* Update the hash of open connections */
+       sender = dbus_g_method_get_sender (context);
+       pcount = g_hash_table_lookup (priv->connections, sender);
+       if (!pcount) {
+               pcount = g_malloc0 (sizeof (int));
+               g_hash_table_insert (priv->connections, sender, pcount);
+       }
+       (*pcount)++;
+
+       dbus_g_method_return (context);
+}
+
+static void
+remove_reference (GcIfaceGeoclue *geoclue,
+                  DBusGMethodInvocation *context)
+{
+       GcProvider *provider = GC_PROVIDER (geoclue);
+       char *sender;
+
+       sender = dbus_g_method_get_sender (context);
+       if (!gc_provider_remove_client (provider, sender)) {
+               g_warning ("Unreffed by client that has not been referenced");
+       }
+
+       g_free (sender);
+
+       dbus_g_method_return (context);
+}
+
+static void
+name_owner_changed (DBusGProxy  *proxy,
+                   const char  *name,
+                   const char  *prev_owner,
+                   const char  *new_owner,
+                   GcProvider  *provider)
+{
+       g_debug("name_owner_changed, name:%s, prev_owner:%s, new_owner:%s", name, prev_owner, new_owner);
+       if (strcmp (new_owner, "") == 0 && strcmp (name, prev_owner) == 0) {
+               if (gc_provider_remove_client_by_force (provider, prev_owner)) {
+                       g_warning ("Impolite client %s disconnected without unreferencing\n", prev_owner);
+               }
+       }
+}
+
+static void
+gc_provider_geoclue_init (GcIfaceGeoclueClass *iface)
+{
+       iface->get_provider_info = get_provider_info;
+       iface->get_status = get_status;
+       iface->set_options = set_options;
+       iface->add_reference = add_reference;
+       iface->remove_reference = remove_reference;
+}
+
+
+/**
+ * gc_provider_set_details:
+ * @provider: A #GcProvider object
+ * @service: The service name to be requested
+ * @path: The path the object should be registered at
+ * @name: The provider name
+ * @description: The description of the provider
+ *
+ * Requests ownership of the @service name, and if that succeeds registers
+ * @provider at @path. @name should be the name of the provider (e.g.
+ * "Hostip"), @description should be a short description of the provider
+ * (e.g. "Web service based Position & Address provider (http://hostip.info)").
+ */
+void
+gc_provider_set_details (GcProvider *provider,
+                        const char *service,
+                        const char *path,
+                        const char *name,
+                        const char *description)
+{
+       GcProviderPrivate *priv = GET_PRIVATE (provider);
+       GError *error = NULL;
+       DBusGProxy *driver;
+       guint request_ret;
+
+       g_return_if_fail (GC_IS_PROVIDER (provider));
+       g_return_if_fail (provider->connection != NULL);
+       g_return_if_fail (service != NULL);
+       g_return_if_fail (path != NULL);
+
+       driver = dbus_g_proxy_new_for_name (provider->connection,
+                                           DBUS_SERVICE_DBUS,
+                                           DBUS_PATH_DBUS,
+                                           DBUS_INTERFACE_DBUS);
+
+       if (!org_freedesktop_DBus_request_name (driver, service, 0,
+                                               &request_ret, &error)) {
+               g_warning ("%s was unable to register service %s: %s",
+                          G_OBJECT_TYPE_NAME (provider), service,
+                          error->message);
+               g_error_free (error);
+               return;
+       }
+
+       dbus_g_proxy_add_signal (driver, "NameOwnerChanged",
+                                G_TYPE_STRING, G_TYPE_STRING,
+                                G_TYPE_STRING, G_TYPE_INVALID);
+       dbus_g_proxy_connect_signal (driver, "NameOwnerChanged",
+                                    G_CALLBACK (name_owner_changed),
+                                    provider, NULL);
+
+       dbus_g_connection_register_g_object (provider->connection,
+                                            path, G_OBJECT (provider));
+
+       priv->name = g_strdup (name);
+       priv->description = g_strdup (description);
+}
diff --git a/geoclue/gc-provider.h b/geoclue/gc-provider.h
new file mode 100644 (file)
index 0000000..e7484b0
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Geoclue
+ * gc-provider.h - A provider object that handles the basic D-Bus required for
+ *                 a provider.
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GC_PROVIDER
+#define _GC_PROVIDER
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+#include <geoclue/gc-iface-geoclue.h>
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_PROVIDER (gc_provider_get_type ())
+
+#define GC_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_PROVIDER, GcProvider))
+#define GC_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GC_TYPE_PROVIDER, GcProviderClass))
+#define GC_IS_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GC_TYPE_PROVIDER))
+#define GC_IS_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GC_TYPE_PROVIDER))
+#define GC_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GC_TYPE_PROVIDER, GcProviderClass))
+
+typedef struct _GcProvider {
+       GObject parent_class;
+
+       DBusGConnection *connection;
+} GcProvider;
+
+typedef struct _GcProviderClass {
+       GObjectClass parent_class;
+
+       void (*shutdown) (GcProvider *provider);
+
+       /* Implements the GcIfaceGeoclue interface */
+       gboolean (*get_status) (GcIfaceGeoclue *geoclue,
+                               GeoclueStatus  *status,
+                               GError        **error);
+        gboolean (*set_options) (GcIfaceGeoclue *geoclue,
+                                 GHashTable     *options,
+                                 GError        **error);
+} GcProviderClass;
+
+GType gc_provider_get_type (void);
+
+void gc_provider_set_details (GcProvider *provider,
+                             const char *service,
+                             const char *path,
+                             const char *name,
+                             const char *description);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/gc-web-service.c b/geoclue/gc-web-service.c
new file mode 100644 (file)
index 0000000..e6dff05
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * Geoclue
+ * gc-web-service.c - A web service helper object for geoclue providers
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ *
+ * Copyright 2007 Jussi Kukkonen (from old geoclue_web_service.c)
+ * Copyright 2007, 2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:gc-web-service
+ * @short_description: Web service helper object for Geoclue providers.
+ *
+ * #GcWebService is a web service abstraction for Geoclue provider
+ * implementations. It handles basic http stuff and xml parsing
+ * (although the raw data is available through
+ * gc_web_service_get_response() as well).
+ *
+ * At the moment xml parsing functions only exist for double and
+ * char-array data types. Adding new functions is trivial, though.
+ * <informalexample>
+ * <programlisting>
+ * . . .
+ *
+ * #GcWebService *web_service;
+ * web_service = g_object_new (GC_TYPE_WEB_SERVICE, NULL);
+ * gc_web_service_set_base_url (web_service, "http://example.org");
+ *
+ * / * Add namespaces if needed * /
+ * gc_web_service_add_namespace (web_service,
+ *                               "ns_name", "http://example.org/ns");
+ *
+ * . . .
+ *
+ * / * Fetch document "http://api.example.org?key1=val1&key2=val2" * /
+ * if (!gc_web_service_query (web_service,
+ *                            "key1", "val1"
+ *                            "key2", val2"
+ *                            (char *)0)) {
+ *     / * error * /
+ *     return;
+ * }
+ *
+ * / * Use XPath expressions to parse the xml in fetched document * /
+ * gchar *str;
+ * if (gc_web_service_get_string (web_service,
+ *                                &str, "//path/to/element")) {
+ *     g_debug("got string: %s", str);
+ * }
+ *
+ * gdouble number;
+ * if (gc_web_service_get_double (web_service,
+ *                                &number, "//path/to/another/element")) {
+ *     g_debug("got double: %f", number);
+ * }
+ *
+ * . . .
+ *
+ * g_object_unref (G_OBJECT (web_service));
+ * </programlisting>
+ * </informalexample>
+ */
+
+#include <stdarg.h>
+#include <glib-object.h>
+#include <string.h>
+
+#include <libxml/nanohttp.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/uri.h>      /* for xmlURIEscapeStr */
+
+#include "gc-web-service.h"
+#include "geoclue-error.h"
+
+G_DEFINE_TYPE (GcWebService, gc_web_service, G_TYPE_OBJECT)
+
+typedef struct _XmlNamespace {
+       gchar *name;
+       gchar *uri;
+}XmlNamespace;
+
+/* GFunc, use with g_list_foreach */
+static void
+gc_web_service_register_ns (gpointer data, gpointer user_data)
+{
+       GcWebService *self = (GcWebService *)user_data;
+       XmlNamespace *ns = (XmlNamespace *)data;
+
+       xmlXPathRegisterNs (self->xpath_ctx,
+                           (xmlChar*)ns->name, (xmlChar*)ns->uri);
+}
+
+/* GFunc, use with g_list_foreach */
+static void
+gc_web_service_free_ns (gpointer data, gpointer user_data)
+{
+       XmlNamespace *ns = (XmlNamespace *)data;
+
+       g_free (ns->name);
+       g_free (ns->uri);
+       g_free (ns);
+}
+
+
+/* Register namespaces listed in self->namespaces */
+static void
+gc_web_service_register_namespaces (GcWebService *self)
+{
+       g_assert (self->xpath_ctx);
+       g_list_foreach (self->namespaces, (GFunc)gc_web_service_register_ns, self);
+}
+
+static void
+gc_web_service_reset (GcWebService *self)
+{
+       g_free (self->response);
+       self->response = NULL;
+       self->response_length = 0;
+
+       if (self->xpath_ctx) {
+               if (self->xpath_ctx->doc) {
+                       xmlFreeDoc (self->xpath_ctx->doc);
+               }
+               xmlXPathFreeContext (self->xpath_ctx);
+               self->xpath_ctx = NULL;
+       }
+}
+
+/* Parse data (self->response), build xpath context and register
+ * namespaces. Nothing will be done if xpath context exists already. */
+static gboolean
+gc_web_service_build_xpath_context (GcWebService *self)
+{
+       xmlDocPtr doc;
+       xmlChar *tmp;
+
+       /* don't rebuild if there's no need */
+       if (self->xpath_ctx) {
+               return TRUE;
+       }
+
+       /* make sure response is NULL-terminated */
+       tmp = xmlStrndup(self->response, self->response_length);
+       doc = xmlParseDoc (tmp);
+       if (!doc) {
+               /* TODO: error handling */
+               g_free (tmp);
+               return FALSE;
+       }
+       xmlFree (tmp);
+
+       self->xpath_ctx = xmlXPathNewContext(doc);
+       if (!self->xpath_ctx) {
+               /* TODO: error handling */
+               return FALSE;
+       }
+       gc_web_service_register_namespaces (self);
+       return TRUE;
+}
+
+/* fetch data from url, save into self->response */
+static gboolean
+gc_web_service_fetch (GcWebService *self, gchar *url, GError **error)
+{
+       void* ctxt = NULL;
+       gint len;
+       xmlChar buf[1024];
+       xmlBuffer *output;
+       char *system_http_proxy = NULL;
+       char http_proxy[128] = {0,};
+
+       g_assert (url);
+
+       gc_web_service_reset (self);
+
+       xmlNanoHTTPInit();
+
+       system_http_proxy = getenv("http_proxy");
+       if (system_http_proxy != NULL) {
+               if (strncmp(system_http_proxy, "http://", 7)) {
+                       snprintf(http_proxy, sizeof(http_proxy), "http://%s", system_http_proxy);
+               } else {
+                       snprintf(http_proxy, sizeof(http_proxy), "%s", system_http_proxy);
+               }
+               xmlNanoHTTPScanProxy(http_proxy);
+       }
+
+       ctxt = xmlNanoHTTPMethod (url, "GET", NULL, NULL, NULL, 0);
+       if (!ctxt) {
+               *error = g_error_new (GEOCLUE_ERROR,
+                                     GEOCLUE_ERROR_NOT_AVAILABLE,
+                                     g_strdup_printf ("xmlNanoHTTPMethod did not get a response from %s\n", url));
+               return FALSE;
+       }
+
+       output = xmlBufferCreate ();
+       while ((len = xmlNanoHTTPRead (ctxt, buf, sizeof(buf))) > 0) {
+               if (xmlBufferAdd (output, buf, len) != 0) {
+                       xmlNanoHTTPClose(ctxt);
+                       xmlBufferFree (output);
+
+                       *error = g_error_new (GEOCLUE_ERROR,
+                                             GEOCLUE_ERROR_FAILED,
+                                             g_strdup_printf ("libxml error (xmlBufferAdd failed)"));
+
+                       return FALSE;
+               }
+       }
+       xmlNanoHTTPClose(ctxt);
+
+       self->response_length = xmlBufferLength (output);
+       self->response = g_memdup (xmlBufferContent (output), self->response_length);
+       xmlBufferFree (output);
+
+       return TRUE;
+}
+
+static xmlXPathObject*
+gc_web_service_get_xpath_object (GcWebService *self, gchar* xpath)
+{
+       xmlXPathObject *obj = NULL;
+
+       g_return_val_if_fail (xpath, FALSE);
+
+       /* parse the doc if not parsed yet and register namespaces */
+       if (!gc_web_service_build_xpath_context (self)) {
+               return FALSE;
+       }
+       g_assert (self->xpath_ctx);
+
+       obj = xmlXPathEvalExpression ((xmlChar*)xpath, self->xpath_ctx);
+       if (obj &&
+           (!obj->nodesetval || xmlXPathNodeSetIsEmpty (obj->nodesetval))) {
+               xmlXPathFreeObject (obj);
+               obj = NULL;
+       }
+       return obj;
+}
+
+static void
+gc_web_service_init (GcWebService *self)
+{
+       self->response = NULL;
+       self->response_length = 0;
+       self->xpath_ctx = NULL;
+       self->namespaces = NULL;
+       self->base_url = NULL;
+}
+
+
+static void
+gc_web_service_finalize (GObject *obj)
+{
+       GcWebService *self = (GcWebService *) obj;
+
+       gc_web_service_reset (self);
+
+       g_free (self->base_url);
+
+       g_list_foreach (self->namespaces, (GFunc)gc_web_service_free_ns, NULL);
+       g_list_free (self->namespaces);
+
+       ((GObjectClass *) gc_web_service_parent_class)->finalize (obj);
+}
+
+static void
+gc_web_service_class_init (GcWebServiceClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+       o_class->finalize = gc_web_service_finalize;
+}
+
+/**
+ * gc_web_service_set_base_url:
+ * @self: The #GcWebService object
+ * @url: base url
+ *
+ * Sets base url for the web service. Must be called before calls to
+ * gc_web_service_get_* -methods.
+ */
+void
+gc_web_service_set_base_url (GcWebService *self, gchar *url)
+{
+       g_assert (url);
+
+       gc_web_service_reset (self);
+
+       g_free (self->base_url);
+       self->base_url = g_strdup (url);
+}
+
+/**
+ * gc_web_service_add_namespace:
+ * @self: The #GcWebService object
+ * @namespace: Namespace name
+ * @uri: Namespace uri
+ *
+ * Adds an xml namespace that will be used in all following calls to
+ * gc_web_service_get_*-functions.
+ *
+ * Return value: %TRUE on success.
+ */
+gboolean
+gc_web_service_add_namespace (GcWebService *self, gchar *namespace, gchar *uri)
+{
+       XmlNamespace *ns;
+
+       g_return_val_if_fail (self->base_url, FALSE);
+
+       ns = g_new0 (XmlNamespace,1);
+       ns->name = g_strdup (namespace);
+       ns->uri = g_strdup (uri);
+       self->namespaces = g_list_prepend (self->namespaces, ns);
+       return TRUE;
+}
+
+/**
+ * gc_web_service_query:
+ * @self: A #GcWebService object
+ * @Varargs: NULL-terminated list of key-value gchar* pairs
+ *
+ * Fetches data from the web. The url is constructed using the
+ * optional arguments as GET parameters (see example in the
+ * Description-section). Data should be read using
+ * gc_web_service_get_* -functions.
+ *
+ * Return value: %TRUE on success.
+ */
+gboolean
+gc_web_service_query (GcWebService *self, GError **error, ...)
+{
+       va_list list;
+       gchar *key, *value, *esc_value, *tmp, *url;
+       gboolean first_pair = TRUE;
+
+       g_return_val_if_fail (self->base_url, FALSE);
+
+       url = g_strdup (self->base_url);
+
+       /* read the arguments one key-value pair at a time,
+          add the pairs to url as "?key1=value1&key2=value2&..." */
+       va_start (list, error);
+       key = va_arg (list, char*);
+       while (key) {
+               value = va_arg (list, char*);
+               esc_value = (gchar *)xmlURIEscapeStr ((xmlChar *)value, NULL);
+
+               if (first_pair) {
+                       tmp = g_strdup_printf ("%s?%s=%s",  url, key, esc_value);
+                       first_pair = FALSE;
+               } else {
+                       tmp = g_strdup_printf ("%s&%s=%s",  url, key, esc_value);
+               }
+               g_free (esc_value);
+               g_free (url);
+               url = tmp;
+               key = va_arg (list, char*);
+       }
+       va_end (list);
+
+       if (!gc_web_service_fetch (self, url, error)) {
+               g_free (url);
+               return FALSE;
+       }
+       g_free (url);
+
+       return TRUE;
+}
+
+/**
+ * gc_web_service_get_double:
+ * @self: A #GcWebService object
+ * @value: Pointer to returned value
+ * @xpath: XPath expression to find the value
+ *
+ * Extracts a @value from the data that was fetched in the last call
+ * to gc_web_service_query() using XPath expression @xpath. Returned
+ * value is the first match.
+ *
+ * Return value: %TRUE if a value was found.
+ */
+gboolean
+gc_web_service_get_double (GcWebService *self, gdouble *value, gchar *xpath)
+{
+       xmlXPathObject *obj;
+
+       obj = gc_web_service_get_xpath_object (self, xpath);
+       if (!obj) {
+               return FALSE;
+       }
+       *value = xmlXPathCastNodeSetToNumber (obj->nodesetval);
+       xmlXPathFreeObject (obj);
+       return TRUE;
+}
+
+/**
+ * gc_web_service_get_string:
+ * @self: The #GcWebService object
+ * @value: pointer to newly allocated string
+ * @xpath: XPath expression used to find the value
+ *
+ * Extracts a @value from the data that was fetched in the last call
+ * to gc_web_service_query() using XPath expression @xpath (returned
+ * value is the first match).
+ *
+ * Return value: %TRUE if a value was found.
+ */
+gboolean
+gc_web_service_get_string (GcWebService *self, gchar **value, gchar* xpath)
+{
+       xmlXPathObject *obj;
+
+       obj = gc_web_service_get_xpath_object (self, xpath);
+       if (!obj) {
+               return FALSE;
+       }
+       *value = (char*)xmlXPathCastNodeSetToString (obj->nodesetval);
+       xmlXPathFreeObject (obj);
+       return TRUE;
+}
+
+/**
+ * gc_web_service_get_response:
+ * @self: The #GcWebService object
+ * @response: returned guchar array
+ * @response_length: length of the returned array
+ *
+ * Returns the raw data fetched with the last call to
+ * gc_web_service_query(). Data may be unterminated.
+ *
+ * Return value: %TRUE on success.
+ */
+gboolean
+gc_web_service_get_response (GcWebService *self, guchar **response, gint *response_length)
+{
+       *response = g_memdup (self->response, self->response_length);
+       *response_length = self->response_length;
+       return TRUE;
+}
diff --git a/geoclue/gc-web-service.h b/geoclue/gc-web-service.h
new file mode 100644 (file)
index 0000000..c281b2f
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Geoclue
+ * gc-web-service.h
+ *
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+#ifndef GC_WEB_SERVICE_H
+#define GC_WEB_SERVICE_H
+
+#include <glib-object.h>
+#include <libxml/xpath.h> /* TODO: could move privates to .c-file and get rid of this*/
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_WEB_SERVICE (gc_web_service_get_type ())
+
+#define GC_WEB_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_WEB_SERVICE, GcWebService))
+#define GC_WEB_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GC_TYPE_WEB_SERVICE, GcWebServiceClass))
+#define GC_IS_WEB_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GC_TYPE_WEB_SERVICE))
+#define GC_IS_WEB_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GC_TYPE_WEB_SERVICE))
+#define GC_WEB_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GC_TYPE_WEB_SERVICE, GcWebServiceClass))
+
+
+typedef struct _GcWebService {
+       GObject parent;
+
+       /* private */
+       gchar *base_url;
+       guchar *response;
+       gint response_length;
+       GList *namespaces;
+       xmlXPathContext *xpath_ctx;
+} GcWebService;
+
+typedef struct _GcWebServiceClass {
+       GObjectClass parent_class;
+} GcWebServiceClass;
+
+GType gc_web_service_get_type (void);
+
+void gc_web_service_set_base_url (GcWebService *self, gchar *url);
+gboolean gc_web_service_add_namespace (GcWebService *self, gchar *namespace, gchar *uri);
+
+gboolean gc_web_service_query (GcWebService *self, GError **error, ...);
+gboolean gc_web_service_get_string (GcWebService *self, gchar **value, gchar *xpath);
+gboolean gc_web_service_get_double (GcWebService *self, gdouble *value, gchar *xpath);
+
+gboolean gc_web_service_get_response (GcWebService *self, guchar **response, gint *response_length);
+
+G_END_DECLS
+
+#endif /* GC_WEB_SERVICE_H */
diff --git a/geoclue/geoclue-accuracy.c b/geoclue/geoclue-accuracy.c
new file mode 100644 (file)
index 0000000..0259ceb
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Geoclue
+ * geoclue-accuracy.c - Code for manipulating the GeoclueAccuracy structure
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:geoclue-accuracy
+ * @short_description: Methods for manipulating #GeoclueAccuracy structure
+ *
+ * A #GeoclueAccuracy holds accuracy information: a
+ * #GeoclueAccuracyLevel and metric values for horizontal and vertical
+ * accuracy. The last two will only be defined if #GeoclueAccuracyLevel is
+ * %GEOCLUE_ACCURACY_LEVEL_DETAILED. These values should be set and queried
+ * using provided functions.
+ **/
+
+#include <glib-object.h>
+
+#include <geoclue/geoclue-accuracy.h>
+
+/**
+ * geoclue_accuracy_new:
+ * @level: A #GeoclueAccuracyLevel
+ * @horizontal_accuracy: Horizontal accuracy in meters
+ * @vertical_accuracy: Vertical accuracy in meters
+ *
+ * Creates a new #GeoclueAccuracy with given values. Use 0 for
+ * horizontal_accuracy and vertical_accuracy if @level is not
+ * %GEOCLUE_ACCURACY_LEVEL_DETAILED.
+ *
+ * Return value: New #GeoclueAccuracy.
+ */
+GeoclueAccuracy *
+geoclue_accuracy_new (GeoclueAccuracyLevel level,
+                     double               horizontal_accuracy,
+                     double               vertical_accuracy)
+{
+       GValue accuracy_struct = {0, };
+
+       g_value_init (&accuracy_struct, GEOCLUE_ACCURACY_TYPE);
+       g_value_take_boxed (&accuracy_struct,
+                           dbus_g_type_specialized_construct
+                           (GEOCLUE_ACCURACY_TYPE));
+
+       dbus_g_type_struct_set (&accuracy_struct,
+                               0, level,
+                               1, horizontal_accuracy,
+                               2, vertical_accuracy,
+                               G_MAXUINT);
+
+       return (GeoclueAccuracy *) g_value_get_boxed (&accuracy_struct);
+}
+
+/**
+ * geoclue_accuracy_free:
+ * @accuracy: A #GeoclueAccuracy
+ *
+ * Frees the #GeoclueAccuracy.
+ */
+void
+geoclue_accuracy_free (GeoclueAccuracy *accuracy)
+{
+       if (!accuracy) {
+               return;
+       }
+
+        g_boxed_free (GEOCLUE_ACCURACY_TYPE, accuracy);
+}
+
+/**
+ * geoclue_accuracy_get_details:
+ * @accuracy: A #GeoclueAccuracy
+ * @level: Pointer to returned #GeoclueAccuracyLevel or %NULL
+ * @horizontal_accuracy: Pointer to returned horizontal accuracy in meters or %NULL
+ * @vertical_accuracy: Pointer to returned vertical accuracy in meters or %NULL
+ *
+ * @horizontal_accuracy and @vertical_accuracy will only be defined
+ * if @level is %GEOCLUE_ACCURACY_LEVEL_DETAILED.
+ */
+void
+geoclue_accuracy_get_details (GeoclueAccuracy      *accuracy,
+                             GeoclueAccuracyLevel *level,
+                             double               *horizontal_accuracy,
+                             double               *vertical_accuracy)
+{
+       GValueArray *vals;
+
+       vals = accuracy;
+       if (level != NULL) {
+               *level = g_value_get_int (g_value_array_get_nth (vals, 0));
+       }
+       if (horizontal_accuracy != NULL) {
+               *horizontal_accuracy = g_value_get_double (g_value_array_get_nth (vals, 1));
+       }
+       if (vertical_accuracy != NULL) {
+               *vertical_accuracy = g_value_get_double (g_value_array_get_nth (vals, 2));
+       }
+}
+
+/**
+ * geoclue_accuracy_set_details:
+ * @accuracy: A #GeoclueAccuracy
+ * @level: A #GeoclueAccuracyLevel
+ * @horizontal_accuracy: Horizontal accuracy in meters
+ * @vertical_accuracy: Vertical accuracy in meters
+ *
+ * Replaces @accuracy values with given ones.
+ */
+void
+geoclue_accuracy_set_details (GeoclueAccuracy     *accuracy,
+                             GeoclueAccuracyLevel level,
+                             double               horizontal_accuracy,
+                             double               vertical_accuracy)
+{
+       GValueArray *vals = accuracy;
+
+       g_value_set_int (g_value_array_get_nth (vals, 0), level);
+       g_value_set_double (g_value_array_get_nth (vals, 1),
+                           horizontal_accuracy);
+       g_value_set_double (g_value_array_get_nth (vals, 2),
+                           vertical_accuracy);
+}
+
+/**
+ * geoclue_accuracy_copy:
+ * @accuracy: A #GeoclueAccuracy
+ *
+ * Creates a copy of @accuracy.
+ *
+ * Return value: A newly allocated #GeoclueAccuracy
+ */
+GeoclueAccuracy *
+geoclue_accuracy_copy (GeoclueAccuracy *accuracy)
+{
+       GeoclueAccuracyLevel level;
+       double hor, ver;
+
+       geoclue_accuracy_get_details (accuracy, &level, &hor, &ver);
+       return geoclue_accuracy_new (level, hor, ver);
+}
+
+/**
+ * geoclue_accuracy_comapre:
+ * @accuracy1: First GeoclueAccuracy
+ * @accuracy1: Second GeoclueAccuracy
+ *
+ * Compares two accuracies.
+ *
+ * Return value: 0 if accuracies are same, negative value if accuracy1 is more accurate than accuracy2, or positive value if accuracy1 is less accurate than accuracy2
+ */
+int
+geoclue_accuracy_compare (GeoclueAccuracy *accuracy1, GeoclueAccuracy *accuracy2)
+{
+       GeoclueAccuracyLevel level1, level2;
+       double hor1, hor2;
+
+       geoclue_accuracy_get_details (accuracy1, &level1, &hor1, NULL);
+       geoclue_accuracy_get_details (accuracy2, &level2, &hor2, NULL);
+
+       if (level1 == GEOCLUE_ACCURACY_LEVEL_DETAILED &&
+           level2 == GEOCLUE_ACCURACY_LEVEL_DETAILED) {
+               if (hor1 > hor2) {
+                       return 1;
+               } else if (hor1 < hor2) {
+                       return -1;
+               }
+               return 0;
+       }
+       return level1 -level2;
+
+}
diff --git a/geoclue/geoclue-accuracy.h b/geoclue/geoclue-accuracy.h
new file mode 100644 (file)
index 0000000..d0da699
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Geoclue
+ * geoclue-accuracy.h - Functions for manipulating GeoclueAccuracy structs
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_ACCURACY_H
+#define _GEOCLUE_ACCURACY_H
+
+#include <glib.h>
+#include <geoclue/geoclue-types.h>
+
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_ACCURACY_TYPE (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_INVALID))
+
+typedef GValueArray GeoclueAccuracy;
+
+GeoclueAccuracy *geoclue_accuracy_new (GeoclueAccuracyLevel level,
+                                      double               horizontal_accuracy,
+                                      double               vertical_accuracy);
+void geoclue_accuracy_free (GeoclueAccuracy *accuracy);
+void geoclue_accuracy_get_details (GeoclueAccuracy      *accuracy,
+                                  GeoclueAccuracyLevel *level,
+                                  double               *horizontal_accuracy,
+                                  double               *vertical_accuracy);
+void geoclue_accuracy_set_details (GeoclueAccuracy      *accuracy,
+                                  GeoclueAccuracyLevel  level,
+                                  double                horizontal_accuracy,
+                                  double                vertical_accuracy);
+
+GeoclueAccuracy *geoclue_accuracy_copy (GeoclueAccuracy *accuracy);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/geoclue-address-details.c b/geoclue/geoclue-address-details.c
new file mode 100644 (file)
index 0000000..c104eb2
--- /dev/null
@@ -0,0 +1,415 @@
+/*
+ * Geoclue
+ * geoclue-address-details.c - Helper functions for GeoclueAddress
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <glib.h>
+
+char *countries[][2] = {
+       {"AF", "Afghanistan"},
+       {"AX", "Aland Islands"},
+       {"AL", "Albania"},
+       {"DZ", "Algeria"},
+       {"AS", "American Samoa"},
+       {"AD", "Andorra"},
+       {"AO", "Angola"},
+       {"AI", "Anguilla"},
+       {"AQ", "Antarctica"},
+       {"AG", "Antigua and Barbuda"},
+       {"AR", "Argentina"},
+       {"AM", "Armenia"},
+       {"AW", "Aruba"},
+       {"AU", "Australia"},
+       {"AT", "Austria"},
+       {"AZ", "Azerbaijan"},
+       {"BS", "Bahamas"},
+       {"BH", "Bahrain"},
+       {"BD", "Bangladesh"},
+       {"BB", "Barbados"},
+       {"BY", "Belarus"},
+       {"BE", "Belgium"},
+       {"BZ", "Belize"},
+       {"BJ", "Benin"},
+       {"BM", "Bermuda"},
+       {"BT", "Bhutan"},
+       {"BO", "Bolivia"},
+       {"BA", "Bosnia and Herzegovina"},
+       {"BW", "Botswana"},
+       {"BV", "Bouvet Island"},
+       {"BR", "Brazil"},
+       {"IO", "British Indian Ocean Territory"},
+       {"BN", "Brunei Darussalam"},
+       {"BG", "Bulgaria"},
+       {"BF", "Burkina Faso"},
+       {"BI", "Burundi"},
+       {"KH", "Cambodia"},
+       {"CM", "Cameroon"},
+       {"CA", "Canada"},
+       {"CV", "Cape Verde"},
+       {"KY", "Cayman Islands"},
+       {"CF", "Central African Republic"},
+       {"TD", "Chad"},
+       {"CL", "Chile"},
+       {"CN", "China"},
+       {"CX", "Christmas Island"},
+       {"CC", "Cocos (Keeling) Islands"},
+       {"CO", "Colombia"},
+       {"KM", "Comoros"},
+       {"CG", "Congo"},
+       {"CD", "Democratic Republic of Congo"},
+       {"CK", "Cook Islands"},
+       {"CR", "Costa Rica"},
+       {"CI", "Cote d'Ivoire"},
+       {"HR", "Croatia"},
+       {"CU", "Cuba"},
+       {"CY", "Cyprus"},
+       {"CZ", "Czech"},
+       {"DK", "Denmark"},
+       {"DJ", "Djibouti"},
+       {"DM", "Dominica"},
+       {"DO", "Dominican"},
+       {"EC", "Ecuador"},
+       {"EG", "Egypt"},
+       {"SV", "El Salvador"},
+       {"GQ", "Equatorial Guinea"},
+       {"ER", "Eritrea"},
+       {"EE", "Estonia"},
+       {"ET", "Ethiopia"},
+       {"FK", "Falkland Islands"},
+       {"FO", "Faroe Islands"},
+       {"FJ", "Fiji"},
+       {"FI", "Finland"},
+       {"FR", "France"},
+       {"GF", "French Guiana"},
+       {"PF", "French Polynesia"},
+       {"TF", "French Southern Territories"},
+       {"GA", "Gabon"},
+       {"GM", "Gambia"},
+       {"GE", "Georgia"},
+       {"DE", "Germany"},
+       {"GH", "Ghana"},
+       {"GI", "Gibraltar"},
+       {"GR", "Greece"},
+       {"GL", "Greenland"},
+       {"GD", "Grenada"},
+       {"GP", "Guadeloupe"},
+       {"GU", "Guam"},
+       {"GT", "Guatemala"},
+       {"GG", "Guernsey"},
+       {"GN", "Guinea"},
+       {"GW", "Guinea-Bissau"},
+       {"GY", "Guyana"},
+       {"HT", "Haiti"},
+       {"HM", "Heard Island and McDonald Islands"},
+       {"VA", "Vatican"},
+       {"HN", "Honduras"},
+       {"HK", "Hong Kong"},
+       {"HU", "Hungary"},
+       {"IS", "Iceland"},
+       {"IN", "India"},
+       {"ID", "Indonesia"},
+       {"IR", "Iran"},
+       {"IQ", "Iraq"},
+       {"IE", "Ireland"},
+       {"IM", "Isle of Man"},
+       {"IL", "Israel"},
+       {"IT", "Italy"},
+       {"JM", "Jamaica"},
+       {"JP", "Japan"},
+       {"JE", "Jersey"},
+       {"JO", "Jordan"},
+       {"KZ", "Kazakhstan"},
+       {"KE", "Kenya"},
+       {"KI", "Kiribati"},
+       {"KP", "Democratic People's Republic of Korea"},
+       {"KR", "Korea"},
+       {"KW", "Kuwait"},
+       {"KG", "Kyrgyzstan"},
+       {"LA", "Lao"},
+       {"LV", "Latvia"},
+       {"LB", "Lebanon"},
+       {"LS", "Lesotho"},
+       {"LR", "Liberia"},
+       {"LY", "Libya"},
+       {"LI", "Liechtenstein"},
+       {"LT", "Lithuania"},
+       {"LU", "Luxembourg"},
+       {"MO", "Macao"},
+       {"MK", "Macedonia"},
+       {"MG", "Madagascar"},
+       {"MW", "Malawi"},
+       {"MY", "Malaysia"},
+       {"MV", "Maldives"},
+       {"ML", "Mali"},
+       {"MT", "Malta"},
+       {"MH", "Marshall Islands"},
+       {"MQ", "Martinique"},
+       {"MR", "Mauritania"},
+       {"MU", "Mauritius"},
+       {"YT", "Mayotte"},
+       {"MX", "Mexico"},
+       {"FM", "Micronesia"},
+       {"MD", "Moldova"},
+       {"MC", "Monaco"},
+       {"MN", "Mongolia"},
+       {"ME", "Montenegro"},
+       {"MS", "Montserrat"},
+       {"MA", "Morocco"},
+       {"MZ", "Mozambique"},
+       {"MM", "Myanmar"},
+       {"NA", "Namibia"},
+       {"NR", "Nauru"},
+       {"NP", "Nepal"},
+       {"NL", "Netherlands"},
+       {"AN", "Netherlands Antilles"},
+       {"NC", "New Caledonia"},
+       {"NZ", "New Zealand"},
+       {"NI", "Nicaragua"},
+       {"NE", "Niger"},
+       {"NG", "Nigeria"},
+       {"NU", "Niue"},
+       {"NF", "Norfolk Island"},
+       {"MP", "Northern Mariana Islands"},
+       {"NO", "Norway"},
+       {"OM", "Oman"},
+       {"PK", "Pakistan"},
+       {"PW", "Palau"},
+       {"PS", "Palestinian Territory"},
+       {"PA", "Panama"},
+       {"PG", "Papua New Guinea"},
+       {"PY", "Paraguay"},
+       {"PE", "Peru"},
+       {"PH", "Philippines"},
+       {"PN", "Pitcairn"},
+       {"PL", "Poland"},
+       {"PT", "Portugal"},
+       {"PR", "Puerto Rico"},
+       {"QA", "Qatar"},
+       {"RE", "Reunion"},
+       {"RO", "Romania"},
+       {"RU", "Russia"},
+       {"RW", "Rwanda"},
+       {"BL", "Saint Barthélemy"},
+       {"SH", "Saint Helena"},
+       {"KN", "Saint Kitts and Nevis"},
+       {"LC", "Saint Lucia"},
+       {"MF", "Saint Martin"},
+       {"PM", "Saint Pierre and Miquelon"},
+       {"VC", "Saint Vincent and the Grenadines"},
+       {"WS", "Samoa"},
+       {"SM", "San Marino"},
+       {"ST", "Sao Tome and Principe"},
+       {"SA", "Saudi Arabia"},
+       {"SN", "Senegal"},
+       {"RS", "Serbia"},
+       {"SC", "Seychelles"},
+       {"SL", "Sierra Leone"},
+       {"SG", "Singapore"},
+       {"SK", "Slovakia"},
+       {"SI", "Slovenia"},
+       {"SB", "Solomon Islands"},
+       {"SO", "Somalia"},
+       {"ZA", "South Africa"},
+       {"GS", "South Georgia and the South Sandwich Islands"},
+       {"ES", "Spain"},
+       {"LK", "Sri Lanka"},
+       {"SD", "Sudan"},
+       {"SR", "Suriname"},
+       {"SJ", "Svalbard and Jan Mayen"},
+       {"SZ", "Swaziland"},
+       {"SE", "Sweden"},
+       {"CH", "Switzerland"},
+       {"SY", "Syria"},
+       {"TW", "Taiwan"},
+       {"TJ", "Tajikistan"},
+       {"TZ", "Tanzania"},
+       {"TH", "Thailand"},
+       {"TL", "Timor-Leste"},
+       {"TG", "Togo"},
+       {"TK", "Tokelau"},
+       {"TO", "Tonga"},
+       {"TT", "Trinidad and Tobago"},
+       {"TN", "Tunisia"},
+       {"TR", "Turkey"},
+       {"TM", "Turkmenistan"},
+       {"TC", "Turks and Caicos Islands"},
+       {"TV", "Tuvalu"},
+       {"UG", "Uganda"},
+       {"UA", "Ukraine"},
+       {"AE", "United Arab Emirates"},
+       {"GB", "United Kingdom"},
+       {"US", "United States"},
+       {"UM", "United States"},  /* US Minor Outlying Islands */
+       {"UY", "Uruguay"},
+       {"UZ", "Uzbekistan"},
+       {"VU", "Vanuatu"},
+       {"VE", "Venezuela"},
+       {"VN", "Viet Nam"},
+       {"VG", "Virgin Islands"}, /* British */
+       {"VI", "Virgin Islands"}, /* US */
+       {"WF", "Wallis and Futuna"},
+       {"EH", "Western Sahara"},
+       {"YE", "Yemen"},
+       {"ZM", "Zambia"},
+       {"ZW", "Zimbabwe"},
+       {NULL, NULL},
+};
+
+
+/**
+ * SECTION:geoclue-address-details
+ * @short_description: Convenience functions for handling Geoclue address
+ * #GHashTables
+ */
+#include <geoclue/geoclue-types.h>
+#include "geoclue-address-details.h"
+
+/**
+ * geoclue_address_details_new:
+ *
+ * Creates a new #GHashTable suitable for Geoclue Address details.
+ * Both keys and values inserted to this #GHashTable will be freed
+ * on g_hash_table_destroy().
+ *
+ * Return value: New #GHashTable
+ */
+GHashTable *
+geoclue_address_details_new ()
+{
+       return g_hash_table_new_full (g_str_hash, g_str_equal,
+                                     g_free, g_free);
+}
+
+
+/**
+ * geoclue_address_details_insert:
+ * @address: #GHashTable to insert value in
+ * @key: the key to use, one of GEOCLUE_ADDRESS_KEY_*
+ * @value: value to insert into address
+ *
+ * Adds a address field into @address. Will take copies
+ * of the strings.
+ */
+void
+geoclue_address_details_insert (GHashTable *address,
+                                const char *key, const char *value)
+{
+       g_hash_table_insert (address, g_strdup (key), g_strdup (value));
+}
+
+static void
+copy_address_key_and_value (char *key, char *value, GHashTable *target)
+{
+       geoclue_address_details_insert (target, key, value);
+}
+
+
+/**
+ * geoclue_address_details_copy:
+ * @source: #GHashTable to copy
+ *
+ * Deep-copies a #GHashTable.
+ *
+ * Return value: New, deep copied #GHashTable
+ */
+GHashTable *
+geoclue_address_details_copy (GHashTable *source)
+{
+       GHashTable *target;
+
+       g_assert (source != NULL);
+
+       target = geoclue_address_details_new ();
+       g_hash_table_foreach (source,
+                             (GHFunc)copy_address_key_and_value,
+                             target);
+       return target;
+}
+
+
+/**
+ * geoclue_address_details_set_country_from_code:
+ * @address: #GHashTable with address data
+ *
+ * Uses the "ISO 3166-1 alpha-2" list to figure out the country name matching
+ * the country code in @details, and adds the country name to details.
+ *
+ * Using this function in providers is useful even when the data source includes
+ * country name: this way names are standardized.
+ */
+void
+geoclue_address_details_set_country_from_code (GHashTable *address)
+{
+       static GHashTable *country_table = NULL;
+       const char *code;
+       const char *country = NULL;
+
+       if (!country_table) {
+               int i;
+
+               country_table = g_hash_table_new (g_str_hash, g_str_equal);
+               for (i = 0; countries[i][0]; i++) {
+                       g_hash_table_insert (country_table, countries[i][0], countries[i][1]);
+               }
+       }
+
+       code = g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_COUNTRYCODE);
+       if (code) {
+               char *upper = g_ascii_strup (code, -1);
+               country = g_hash_table_lookup (country_table, upper);
+               g_free (upper);
+       }
+
+       if (country) {
+               geoclue_address_details_insert (
+                   address, GEOCLUE_ADDRESS_KEY_COUNTRY, country);
+       } else {
+               g_hash_table_remove (address, GEOCLUE_ADDRESS_KEY_COUNTRY);
+       }
+}
+
+/**
+ * geoclue_address_details_get_accuracy_level:
+ * @address: A #GHashTable with address hash values
+ *
+ * Returns a #GeoclueAccuracy that best describes the accuracy of @address
+ *
+ * Return value: #GeoclueAccuracy
+ */
+GeoclueAccuracyLevel
+geoclue_address_details_get_accuracy_level (GHashTable *address)
+{
+       if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_STREET)) {
+               return GEOCLUE_ACCURACY_LEVEL_STREET;
+       } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_POSTALCODE)) {
+               return GEOCLUE_ACCURACY_LEVEL_POSTALCODE;
+       } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_LOCALITY)) {
+               return GEOCLUE_ACCURACY_LEVEL_LOCALITY;
+       } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_REGION)) {
+               return GEOCLUE_ACCURACY_LEVEL_REGION;
+       } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_COUNTRY) ||
+                  g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_COUNTRYCODE)) {
+               return GEOCLUE_ACCURACY_LEVEL_COUNTRY;
+       }
+       return GEOCLUE_ACCURACY_LEVEL_NONE;
+}
diff --git a/geoclue/geoclue-address-details.h b/geoclue/geoclue-address-details.h
new file mode 100644 (file)
index 0000000..f00a897
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Geoclue
+ * geoclue-address-details.h -
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+#ifndef _GEOCLUE_ADDRESS_DETAILS_H
+#define _GEOCLUE_ADDRESS_DETAILS_H
+
+#include <glib.h>
+
+GHashTable *geoclue_address_details_new ();
+
+GHashTable *geoclue_address_details_copy (GHashTable *source);
+
+void geoclue_address_details_insert (GHashTable *address, const char *key, const char *value);
+
+void geoclue_address_details_set_country_from_code (GHashTable *address);
+
+GeoclueAccuracyLevel geoclue_address_details_get_accuracy_level (GHashTable *address);
+
+#endif
diff --git a/geoclue/geoclue-address.c b/geoclue/geoclue-address.c
new file mode 100644 (file)
index 0000000..62d63e7
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Geoclue
+ * geoclue-address.c - Client API for accessing GcIfaceAddress
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:geoclue-address
+ * @short_description: Geoclue address client API
+ *
+ * #GeoclueAddress contains Address-related methods and signals.
+ * It is part of the Geoclue public C client API which uses D-Bus
+ * to communicate with the actual provider.
+ *
+ * After a #GeoclueAddress is created with geoclue_address_new() or
+ * geoclue_master_client_create_address(), the
+ * geoclue_address_get_address() and geoclue_address_get_address_async() methods
+ * and the address-changed signal can be used to obtain the current address.
+ *
+ * Address #GHashTable keys are defined in
+ * <ulink url="geoclue-types.html">geoclue-types.h</ulink>. See also
+ * convenience functions in
+ * <ulink url="geoclue-address-details.html">geoclue-address-details.h</ulink>.
+ */
+
+#include <geoclue/geoclue-address.h>
+#include <geoclue/geoclue-marshal.h>
+
+#include "gc-iface-address-bindings.h"
+
+typedef struct _GeoclueAddressPrivate {
+       int dummy;
+} GeoclueAddressPrivate;
+
+enum {
+       ADDRESS_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_ADDRESS, GeoclueAddressPrivate))
+
+G_DEFINE_TYPE (GeoclueAddress, geoclue_address, GEOCLUE_TYPE_PROVIDER);
+
+static void
+finalize (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_address_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_address_parent_class)->dispose (object);
+}
+
+static void
+address_changed (DBusGProxy      *proxy,
+                int              timestamp,
+                GHashTable      *details,
+                GeoclueAccuracy *accuracy,
+                GeoclueAddress *address)
+{
+       g_signal_emit (address, signals[ADDRESS_CHANGED], 0,
+                      timestamp, details, accuracy);
+}
+
+static GObject *
+constructor (GType                  type,
+            guint                  n_props,
+            GObjectConstructParam *props)
+{
+       GObject *object;
+       GeoclueProvider *provider;
+
+       object = G_OBJECT_CLASS (geoclue_address_parent_class)->constructor
+               (type, n_props, props);
+       provider = GEOCLUE_PROVIDER (object);
+
+       dbus_g_proxy_add_signal (provider->proxy, "AddressChanged",
+                                G_TYPE_INT,
+                                DBUS_TYPE_G_STRING_STRING_HASHTABLE,
+                                GEOCLUE_ACCURACY_TYPE,
+                                G_TYPE_INVALID);
+       dbus_g_proxy_connect_signal (provider->proxy, "AddressChanged",
+                                    G_CALLBACK (address_changed),
+                                    object, NULL);
+
+       return object;
+}
+
+static void
+geoclue_address_class_init (GeoclueAddressClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+       o_class->constructor = constructor;
+
+       g_type_class_add_private (klass, sizeof (GeoclueAddressPrivate));
+
+       /**
+        * GeoclueAddress::address-changed:
+        * @address: the #GeoclueAddress object emitting the signal
+        * @timestamp: Time of address measurement (Unix timestamp)
+        * @details: Address details as #GHashTable.
+        * @accuracy: Accuracy of measurement as #GeoclueAccuracy
+        *
+        * The address-changed signal is emitted each time the address changes.
+        * See <ulink url="geoclue-types.html">geoclue-types.h</ulink> for the possible
+        * GEOCLUE_ADDRESS_KEY_* keys used in @details.
+        *
+        * Note that not all providers support signals.
+        */
+       signals[ADDRESS_CHANGED] = g_signal_new ("address-changed",
+                                                G_TYPE_FROM_CLASS (klass),
+                                                G_SIGNAL_RUN_FIRST |
+                                                G_SIGNAL_NO_RECURSE,
+                                                G_STRUCT_OFFSET (GeoclueAddressClass, address_changed),
+                                                NULL, NULL,
+                                                geoclue_marshal_VOID__INT_BOXED_BOXED,
+                                                G_TYPE_NONE, 3,
+                                                G_TYPE_INT,
+                                                G_TYPE_POINTER,
+                                                G_TYPE_POINTER);
+}
+
+static void
+geoclue_address_init (GeoclueAddress *address)
+{
+}
+
+/**
+ * geoclue_address_new:
+ * @service: D-Bus service name
+ * @path: D-Bus path name
+ *
+ * Creates a #GeoclueAddress with given D-Bus service name and path.
+ *
+ * Return value: Pointer to a new #GeoclueAddress
+ */
+GeoclueAddress *
+geoclue_address_new (const char *service,
+                    const char *path)
+{
+       return g_object_new (GEOCLUE_TYPE_ADDRESS,
+                            "service", service,
+                            "path", path,
+                            "interface", GEOCLUE_ADDRESS_INTERFACE_NAME,
+                            NULL);
+}
+
+/**
+ * geoclue_address_get_address:
+ * @address: A #GeoclueAddress object
+ * @timestamp: Pointer to returned time of address measurement (Unix timestamp) or %NULL
+ * @details: Pointer to returned #GHashTable with address details or %NULL
+ * @accuracy: Pointer to returned #GeoclueAccuracy or NULL
+ * @error: Pointer to returned #Gerror or %NULL
+ *
+ * Obtains the current address. @timestamp will contain the time of
+ * the actual address measurement. @accuracy is the estimated of the
+ * accuracy of the current address information (see #GeoclueAccuracy
+ * for more details). @details is a hashtable with the address data,
+ * see <ulink url="geoclue-types.html">geoclue-types.h</ulink> for the
+ * hashtable keys.
+ *
+ * If the caller is not interested in some values, the pointers can be
+ * left %NULL.
+ *
+ * Return value: %TRUE if there is no @error
+ */
+gboolean
+geoclue_address_get_address (GeoclueAddress   *address,
+                            int              *timestamp,
+                            GHashTable      **details,
+                            GeoclueAccuracy **accuracy,
+                            GError          **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (address);
+
+       if (!org_freedesktop_Geoclue_Address_get_address (provider->proxy,
+                                                         timestamp, details,
+                                                         accuracy, error)) {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+typedef struct _GeoclueAddressAsyncData {
+       GeoclueAddress *address;
+       GCallback callback;
+       gpointer userdata;
+} GeoclueAddressAsyncData;
+
+static void
+get_address_async_callback (DBusGProxy              *proxy,
+                           int                      timestamp,
+                           GHashTable              *details,
+                           GeoclueAccuracy         *accuracy,
+                           GError                  *error,
+                           GeoclueAddressAsyncData *data)
+{
+       (*(GeoclueAddressCallback)data->callback) (data->address,
+                                                  timestamp,
+                                                  details,
+                                                  accuracy,
+                                                  error,
+                                                  data->userdata);
+       g_free (data);
+}
+
+/**
+ * GeoclueAddressCallback:
+ * @address: the #GeoclueAddress object emitting the signal
+ * @timestamp: Time of address measurement (Unix timestamp)
+ * @details: Address details as #GHashTable.
+ * @accuracy: Accuracy of measurement as #GeoclueAccuracy
+ * @error: Error as #Gerror (may be %NULL)
+ * @userdata: User data pointer set in geoclue_position_get_position_async()
+ *
+ * Callback function for geoclue_address_get_address_async().
+ */
+
+/**
+ * geoclue_address_get_address_async:
+ * @address: A #GeoclueAddress object
+ * @callback: A #GeoclueAddressCallback function that should be called when return values are available
+ * @userdata: pointer for user specified data
+ *
+ * Function returns (essentially) immediately and calls @callback when current address
+ * is available or when D-Bus timeouts.
+ */
+void
+geoclue_address_get_address_async (GeoclueAddress         *address,
+                                  GeoclueAddressCallback  callback,
+                                  gpointer                userdata)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (address);
+       GeoclueAddressAsyncData *data;
+
+       data = g_new (GeoclueAddressAsyncData, 1);
+       data->address = address;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_Address_get_address_async
+                       (provider->proxy,
+                        (org_freedesktop_Geoclue_Address_get_address_reply) get_address_async_callback,
+                        data);
+}
diff --git a/geoclue/geoclue-address.h b/geoclue/geoclue-address.h
new file mode 100644 (file)
index 0000000..447c23a
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Geoclue
+ * geoclue-address.h -
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_ADDRESS_H
+#define _GEOCLUE_ADDRESS_H
+
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+#include <geoclue/geoclue-address-details.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_ADDRESS (geoclue_address_get_type ())
+#define GEOCLUE_ADDRESS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_ADDRESS, GeoclueAddress))
+#define GEOCLUE_IS_ADDRESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_ADDRESS))
+
+#define GEOCLUE_ADDRESS_INTERFACE_NAME "org.freedesktop.Geoclue.Address"
+
+typedef struct _GeoclueAddress {
+       GeoclueProvider provider;
+} GeoclueAddress;
+
+typedef struct _GeoclueAddressClass {
+       GeoclueProviderClass provider_class;
+
+       void (* address_changed) (GeoclueAddress  *address,
+                                 int              timestamp,
+                                 GHashTable      *details,
+                                 GeoclueAccuracy *accuracy);
+} GeoclueAddressClass;
+
+GType geoclue_address_get_type (void);
+
+GeoclueAddress *geoclue_address_new (const char *service,
+                                    const char *path);
+
+gboolean geoclue_address_get_address (GeoclueAddress   *address,
+                                     int              *timestamp,
+                                     GHashTable      **details,
+                                     GeoclueAccuracy **accuracy,
+                                     GError          **error);
+
+typedef void (*GeoclueAddressCallback) (GeoclueAddress   *address,
+                                       int               timestamp,
+                                       GHashTable       *details,
+                                       GeoclueAccuracy  *accuracy,
+                                       GError           *error,
+                                       gpointer          userdata);
+
+void geoclue_address_get_address_async (GeoclueAddress         *address,
+                                       GeoclueAddressCallback  callback,
+                                       gpointer                userdata);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/geoclue-error.c b/geoclue/geoclue-error.c
new file mode 100644 (file)
index 0000000..4334ec2
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Geoclue
+ * geoclue-error.c - Error handling
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <geoclue/geoclue-error.h>
+
+GQuark
+geoclue_error_quark (void)
+{
+       static GQuark quark = 0;
+
+       if (quark == 0) {
+               quark = g_quark_from_static_string ("geoclue-error-quark");
+       }
+
+       return quark;
+}
+
diff --git a/geoclue/geoclue-error.h b/geoclue/geoclue-error.h
new file mode 100644 (file)
index 0000000..1138578
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Geoclue
+ * geoclue-error.h - Error handling
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_ERROR_H
+#define _GEOCLUE_ERROR_H
+
+#include <glib-object.h>
+#include <geoclue/geoclue-enum-types.h>
+
+/**
+ * GeoclueError:
+ * @GEOCLUE_ERROR_NOT_IMPLEMENTED: Method is not implemented
+ * @GEOCLUE_ERROR_NOT_AVAILABLE: Needed information is not currently
+ * available (e.g. web service did not respond)
+ * @GEOCLUE_ERROR_FAILED: Generic fatal error
+ *
+ * Error values for providers.
+ **/
+typedef enum {
+       GEOCLUE_ERROR_NOT_IMPLEMENTED,
+       GEOCLUE_ERROR_NOT_AVAILABLE,
+       GEOCLUE_ERROR_FAILED,
+} GeoclueError;
+
+#define GEOCLUE_ERROR_DBUS_INTERFACE "org.freedesktop.Geoclue.Error"
+#define GEOCLUE_ERROR (geoclue_error_quark ())
+
+GQuark geoclue_error_quark (void);
+
+#endif
diff --git a/geoclue/geoclue-geocode.c b/geoclue/geoclue-geocode.c
new file mode 100644 (file)
index 0000000..645a9d5
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * Geoclue
+ * geoclue-geocode.c - Client API for accessing GcIfaceGeocode
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ *          Jussi Kukkonen <jku@linux.intel.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *           2010 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:geoclue-geocode
+ * @short_description: Geoclue geocode client API
+ *
+ * #GeoclueGeocode contains geocoding methods.
+ * It is part of the Geoclue public C client API which uses D-Bus
+ * to communicate with the actual provider.
+ *
+ * After a #GeoclueGeocode is created with geoclue_geocode_new(), the
+ * geoclue_geocode_address_to_position(),
+ * geoclue_geocode_freeform_address_to_position() methods and their
+ * asynchronous counterparts can be used to obtain the position (coordinates)
+ * of the given address.
+ *
+ * Address #GHashTable keys are defined in
+ * <ulink url="geoclue-types.html">geoclue-types.h</ulink>. See also
+ * convenience functions in
+ * <ulink url="geoclue-address-details.html">geoclue-address-details.h</ulink>.
+ */
+
+#include <geoclue/geoclue-geocode.h>
+#include <geoclue/geoclue-marshal.h>
+
+#include "gc-iface-geocode-bindings.h"
+
+typedef struct _GeoclueGeocodePrivate {
+       int dummy;
+} GeoclueGeocodePrivate;
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_GEOCODE, GeoclueGeocodePrivate))
+
+G_DEFINE_TYPE (GeoclueGeocode, geoclue_geocode, GEOCLUE_TYPE_PROVIDER);
+
+static void
+finalize (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_geocode_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_geocode_parent_class)->dispose (object);
+}
+
+static void
+geoclue_geocode_class_init (GeoclueGeocodeClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+
+       g_type_class_add_private (klass, sizeof (GeoclueGeocodePrivate));
+}
+
+static void
+geoclue_geocode_init (GeoclueGeocode *geocode)
+{
+}
+
+/**
+ * geoclue_geocode_new:
+ * @service: D-Bus service name
+ * @path: D-Bus path name
+ *
+ * Creates a #GeoclueGeocode with given D-Bus service name and path.
+ *
+ * Return value: Pointer to a new #GeoclueGeocode
+ */
+GeoclueGeocode *
+geoclue_geocode_new (const char *service,
+                    const char *path)
+{
+       return g_object_new (GEOCLUE_TYPE_GEOCODE,
+                            "service", service,
+                            "path", path,
+                            "interface", GEOCLUE_GEOCODE_INTERFACE_NAME,
+                            NULL);
+}
+
+/**
+ * geoclue_geocode_address_to_position:
+ * @geocode: A #GeoclueGeocode object
+ * @details: Hashtable with address data
+ * @latitude: Pointer to returned latitude in degrees or %NULL
+ * @longitude: Pointer to returned longitude in degrees or %NULL
+ * @altitude: Pointer to returned altitude in meters or %NULL
+ * @accuracy: Pointer to returned #GeoclueAccuracy or %NULL
+ * @error: Pointer to returned #Gerror or %NULL
+ *
+ * Geocodes given address to coordinates (@latitude, @longitude, @altitude).
+ * see <ulink url="geoclue-types.html">geoclue-types.h</ulink> for the
+ * hashtable keys usable in @details. @accuracy is a rough estimate of
+ * the accuracy of the returned position.
+ *
+ * If the caller is not interested in some values, the pointers can be
+ * left %NULL.
+ *
+ * Return value: A #GeocluePositionFields bitfield representing the
+ * validity of the returned coordinates.
+ */
+GeocluePositionFields
+geoclue_geocode_address_to_position (GeoclueGeocode   *geocode,
+                                    GHashTable       *details,
+                                    double           *latitude,
+                                    double           *longitude,
+                                    double           *altitude,
+                                    GeoclueAccuracy **accuracy,
+                                    GError          **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (geocode);
+       int fields;
+       double la, lo, al;
+       GeoclueAccuracy *acc;
+
+       if (!org_freedesktop_Geoclue_Geocode_address_to_position (provider->proxy,
+                                                                 details, &fields,
+                                                                 &la, &lo, &al,
+                                                                 &acc, error)){
+               return GEOCLUE_POSITION_FIELDS_NONE;
+       }
+
+       if (latitude != NULL && (fields & GEOCLUE_POSITION_FIELDS_LATITUDE)) {
+               *latitude = la;
+       }
+
+       if (longitude != NULL && (fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)) {
+               *longitude = lo;
+       }
+
+       if (altitude != NULL && (fields & GEOCLUE_POSITION_FIELDS_ALTITUDE)) {
+               *altitude = al;
+       }
+
+       if (accuracy != NULL) {
+               *accuracy = acc;
+       }
+
+       return fields;
+}
+
+typedef struct _GeoclueGeocodeAsyncData {
+       GeoclueGeocode *geocode;
+       GCallback callback;
+       gpointer userdata;
+} GeoclueGeocodeAsyncData;
+
+static void
+address_to_position_callback (DBusGProxy              *proxy,
+                             GeocluePositionFields    fields,
+                             double                   latitude,
+                             double                   longitude,
+                             double                   altitude,
+                             GeoclueAccuracy         *accuracy,
+                             GError                  *error,
+                             GeoclueGeocodeAsyncData *data)
+{
+       (*(GeoclueGeocodeCallback)data->callback) (data->geocode,
+                                                  fields,
+                                                  latitude,
+                                                  longitude,
+                                                  altitude,
+                                                  accuracy,
+                                                  error,
+                                                  data->userdata);
+       g_free (data);
+}
+
+/**
+ * GeoclueGeocodeCallback:
+ * @geocode: A #GeoclueGeocode object
+ * @fields: A #GeocluePositionFields bitfield representing the validity of the position values
+ * @latitude: Latitude in degrees
+ * @longitude: Longitude in degrees
+ * @altitude: Altitude in meters
+ * @accuracy: Accuracy of measurement as #GeoclueAccuracy
+ * @error: Error as #Gerror or %NULL
+ * @userdata: User data pointer
+ *
+ * Callback function for the asynchronous methods.
+ */
+
+/**
+ * geoclue_geocode_address_to_position_async:
+ * @geocode: A #Geocluegeocode object
+ * @details: A #GHashTable with address data
+ * @callback: A #GeoclueAddressCallback function that should be called when return values are available
+ * @userdata: pointer for user specified data
+ *
+ * Function returns (essentially) immediately and calls @callback when the geocoded
+ * position data is available or when D-Bus timeouts.
+ *
+ * see <ulink url="geoclue-types.html">geoclue-types.h</ulink> for the
+ * hashtable keys usable in @details.
+ *
+ */
+void
+geoclue_geocode_address_to_position_async (GeoclueGeocode         *geocode,
+                                          GHashTable             *details,
+                                          GeoclueGeocodeCallback  callback,
+                                          gpointer                userdata)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (geocode);
+       GeoclueGeocodeAsyncData *data;
+
+       data = g_new (GeoclueGeocodeAsyncData, 1);
+       data->geocode = geocode;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_Geocode_address_to_position_async
+                       (provider->proxy,
+                        details,
+                        (org_freedesktop_Geoclue_Geocode_address_to_position_reply)address_to_position_callback,
+                        data);
+}
+
+/**
+ * geoclue_geocode_freeform_address_to_position:
+ * @geocode: A #GeoclueGeocode object
+ * @address: freeform address
+ * @latitude: Pointer to returned latitude in degrees or %NULL
+ * @longitude: Pointer to returned longitude in degrees or %NULL
+ * @altitude: Pointer to returned altitude in meters or %NULL
+ * @accuracy: Pointer to returned #GeoclueAccuracy or %NULL
+ * @error: Pointer to returned #Gerror or %NULL
+ *
+ * Geocodes given address to coordinates (@latitude, @longitude, @altitude).
+ * @accuracy is a rough estimate of the accuracy of the returned position.
+ *
+ * If the caller is not interested in some values, the pointers can be
+ * left %NULL.
+ *
+ * Return value: A #GeocluePositionFields bitfield representing the
+ * validity of the returned coordinates.
+ */
+GeocluePositionFields
+geoclue_geocode_freeform_address_to_position (GeoclueGeocode   *geocode,
+                                              const char       *address,
+                                              double           *latitude,
+                                              double           *longitude,
+                                              double           *altitude,
+                                              GeoclueAccuracy **accuracy,
+                                              GError          **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (geocode);
+       int fields;
+       double la, lo, al;
+       GeoclueAccuracy *acc;
+
+       if (!org_freedesktop_Geoclue_Geocode_freeform_address_to_position
+                       (provider->proxy,
+                        address, &fields,
+                        &la, &lo, &al,
+                        &acc, error)) {
+               return GEOCLUE_POSITION_FIELDS_NONE;
+       }
+
+       if (latitude != NULL && (fields & GEOCLUE_POSITION_FIELDS_LATITUDE)) {
+               *latitude = la;
+       }
+
+       if (longitude != NULL && (fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)) {
+               *longitude = lo;
+       }
+
+       if (altitude != NULL && (fields & GEOCLUE_POSITION_FIELDS_ALTITUDE)) {
+               *altitude = al;
+       }
+
+       if (accuracy != NULL) {
+               *accuracy = acc;
+       }
+
+       return fields;
+}
+
+/**
+ * geoclue_geocode_freeform_address_to_position_async:
+ * @geocode: A #Geocluegeocode object
+ * @address: freeform address
+ * @callback: A #GeoclueAddressCallback function that should be called when return values are available
+ * @userdata: pointer for user specified data
+ *
+ * Function returns (essentially) immediately and calls @callback when the geocoded
+ * position data is available or when D-Bus timeouts.
+ */
+void
+geoclue_geocode_freeform_address_to_position_async (GeoclueGeocode         *geocode,
+                                                    const char             *address,
+                                                    GeoclueGeocodeCallback  callback,
+                                                    gpointer                userdata)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (geocode);
+       GeoclueGeocodeAsyncData *data;
+
+       data = g_new (GeoclueGeocodeAsyncData, 1);
+       data->geocode = geocode;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_Geocode_freeform_address_to_position_async
+                       (provider->proxy,
+                        address,
+                        (org_freedesktop_Geoclue_Geocode_address_to_position_reply)address_to_position_callback,
+                        data);
+}
+
diff --git a/geoclue/geoclue-geocode.h b/geoclue/geoclue-geocode.h
new file mode 100644 (file)
index 0000000..59aa15a
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Geoclue
+ * geoclue-geocode.h -
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ *          Jussi Kukkonen <jku@linux.intel.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *           2010 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_GEOCODE_H
+#define _GEOCLUE_GEOCODE_H
+
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+#include <geoclue/geoclue-address-details.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_GEOCODE (geoclue_geocode_get_type ())
+#define GEOCLUE_GEOCODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GEOCODE, GeoclueGeocode))
+#define GEOCLUE_IS_GEOCODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_GEOCODE))
+
+#define GEOCLUE_GEOCODE_INTERFACE_NAME "org.freedesktop.Geoclue.Geocode"
+
+typedef struct _GeoclueGeocode {
+       GeoclueProvider provider;
+} GeoclueGeocode;
+
+typedef struct _GeoclueGeocodeClass {
+       GeoclueProviderClass provider_class;
+} GeoclueGeocodeClass;
+
+GType geoclue_geocode_get_type (void);
+
+GeoclueGeocode *geoclue_geocode_new (const char *service,
+                                    const char *path);
+
+GeocluePositionFields
+geoclue_geocode_address_to_position (GeoclueGeocode   *geocode,
+                                    GHashTable       *details,
+                                    double           *latitude,
+                                    double           *longitude,
+                                    double           *altitude,
+                                    GeoclueAccuracy **accuracy,
+                                    GError          **error);
+
+typedef void (*GeoclueGeocodeCallback) (GeoclueGeocode       *geocode,
+                                       GeocluePositionFields fields,
+                                       double                latitude,
+                                       double                longitude,
+                                       double                altitude,
+                                       GeoclueAccuracy      *accuracy,
+                                       GError               *error,
+                                       gpointer              userdata);
+
+void geoclue_geocode_address_to_position_async (GeoclueGeocode         *geocode,
+                                               GHashTable             *details,
+                                               GeoclueGeocodeCallback  callback,
+                                               gpointer                userdata);
+
+GeocluePositionFields
+geoclue_geocode_freeform_address_to_position (GeoclueGeocode   *geocode,
+                                              const char       *address,
+                                              double           *latitude,
+                                              double           *longitude,
+                                              double           *altitude,
+                                              GeoclueAccuracy **accuracy,
+                                              GError          **error);
+
+void
+geoclue_geocode_freeform_address_to_position_async (GeoclueGeocode         *geocode,
+                                                    const char             *address,
+                                                    GeoclueGeocodeCallback  callback,
+                                                    gpointer                userdata);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/geoclue-landmark.h b/geoclue/geoclue-landmark.h
new file mode 100644 (file)
index 0000000..6feb4e2
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Geoclue
+ * geoclue-landmark.h
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+#ifndef _GEOCLUE_LANDMARK_H
+#define _GEOCLUE_LANDMARK_H
+
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-types.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_LANDMARK (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_INT, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID))
+
+#define GEOCLUE_LANDMARK_ARRAY (dbus_g_type_get_collection ("GPtrArray", GEOCLUE_LANDMARK))
+
+typedef struct _GeoclueLandmark {
+       gint id;
+       gint rank;
+       gdouble lat;
+       gdouble lon;
+       gdouble boundary_left;
+       gdouble boundary_top;
+       gdouble boundary_right;
+       gdouble boundary_bottom;
+       gchar *name;
+       gchar *icon;
+       gchar *house;
+       gchar *road;
+       gchar *village;
+       gchar *suburb;
+       gchar *postcode;
+       gchar *city;
+       gchar *county;
+       gchar *country;
+       gchar *country_code;
+} GeoclueLandmark;
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/geoclue-marshal.list b/geoclue/geoclue-marshal.list
new file mode 100644 (file)
index 0000000..5f65dc6
--- /dev/null
@@ -0,0 +1,10 @@
+VOID:INT,INT
+VOID:INT,INT,DOUBLE,DOUBLE,DOUBLE,BOXED
+VOID:INT,INT,DOUBLE,DOUBLE,DOUBLE,DOUBLE,DOUBLE,DOUBLE,BOXED
+VOID:INT,INT,DOUBLE,DOUBLE,DOUBLE
+VOID:INT,DOUBLE,DOUBLE
+VOID:INT,POINTER,BOXED
+VOID:INT,BOXED,BOXED
+VOID:STRING,STRING,STRING,STRING
+VOID:INT,STRING
+VOID:INT,INT,INT,POINTER,POINTER
diff --git a/geoclue/geoclue-master-client.c b/geoclue/geoclue-master-client.c
new file mode 100644 (file)
index 0000000..57b2d97
--- /dev/null
@@ -0,0 +1,724 @@
+/*
+ * Geoclue
+ * geoclue-master-client.c - Client API for accessing the Geoclue Master process
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:geoclue-master-client
+ * @short_description: Geoclue MasterClient API
+ *
+ * #GeoclueMasterClient is part of the Geoclue public C client API. It uses
+ * D-Bus to communicate with the actual Master service.
+ *
+ * #GeoclueMasterClient is used to control the client specific behaviour
+ * of Geoclue Master. Chapter "Master provider: simple example in C" contains a
+ * more complete example, but here are the main parts:
+ *
+ * <informalexample>
+ * <programlisting>
+ * GeoclueMaster *master;
+ * GeoclueMasterClient *client;
+ * GeoclueAddress *address;
+ *
+ * ...
+ *
+ * master = geoclue_master_get_default ();
+ * client = geoclue_master_create_client (master, NULL, NULL);
+ *
+ * if (!geoclue_master_client_set_requirements (client,
+ *                                              GEOCLUE_ACCURACY_LEVEL_NONE,
+ *                                              0, FALSE,
+ *                                              GEOCLUE_RESOURCE_NETWORK,
+ *                                              &error)) {
+ *     / * handle error * /
+ * }
+ *
+ * address = geoclue_master_client_create_address (client, error);
+ * if (!address) {
+ *     / * handle error * /
+ * }
+ *
+ * / * Now we can use address just like we'd use a normal address provider,
+ *     but GeoclueMasterClient makes sure that underneath the provider
+ *     that best matches our requirements is used * /
+ * </programlisting>
+ * </informalexample>
+ */
+
+#include <config.h>
+
+#include <glib-object.h>
+
+#include <geoclue/geoclue-marshal.h>
+#include <geoclue/geoclue-master.h>
+#include <geoclue/geoclue-master-client.h>
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+
+#include "gc-iface-master-client-bindings.h"
+
+typedef struct _GeoclueMasterClientPrivate {
+       DBusGProxy *proxy;
+       char *object_path;
+} GeoclueMasterClientPrivate;
+
+enum {
+       PROP_0,
+       PROP_PATH
+};
+
+enum {
+       ADDRESS_PROVIDER_CHANGED,
+       POSITION_PROVIDER_CHANGED,
+       INVALIDATED,
+       LAST_SIGNAL
+};
+
+
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_MASTER_CLIENT, GeoclueMasterClientPrivate))
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueMasterClient, geoclue_master_client, G_TYPE_OBJECT, geoclue_types_init (););
+
+
+typedef struct _GeoclueMasterClientAsyncData {
+       GeoclueMasterClient *client;
+       GCallback callback;
+       gpointer userdata;
+} GeoclueMasterClientAsyncData;
+
+
+static void
+finalize (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_master_client_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+
+       G_OBJECT_CLASS (geoclue_master_client_parent_class)->dispose (object);
+}
+
+static void
+set_property (GObject      *object,
+             guint         prop_id,
+             const GValue *value,
+             GParamSpec   *pspec)
+{
+       GeoclueMasterClientPrivate *priv;
+
+       priv = GET_PRIVATE (object);
+
+       switch (prop_id) {
+       case PROP_PATH:
+               priv->object_path = g_value_dup_string (value);
+               break;
+
+       default:
+               break;
+       }
+}
+
+static void
+get_property (GObject    *object,
+             guint       prop_id,
+             GValue     *value,
+             GParamSpec *pspec)
+{
+}
+
+static void
+address_provider_changed (DBusGProxy          *proxy,
+                          char                *name,
+                          char                *description,
+                          char                *service,
+                          char                *path,
+                          GeoclueMasterClient *client)
+{
+       g_signal_emit (client, signals[ADDRESS_PROVIDER_CHANGED], 0,
+                      name, description, service, path);
+}
+
+static void
+position_provider_changed (DBusGProxy          *proxy,
+                           char                *name,
+                           char                *description,
+                           char                *service,
+                           char                *path,
+                           GeoclueMasterClient *client)
+{
+       g_signal_emit (client, signals[POSITION_PROVIDER_CHANGED], 0,
+                      name, description, service, path);
+}
+
+static void
+proxy_destroyed (DBusGProxy *proxy,
+                gpointer    user_data)
+{
+       g_signal_emit (user_data, signals[INVALIDATED], 0);
+}
+
+static GObject *
+constructor (GType                  type,
+            guint                  n_props,
+            GObjectConstructParam *props)
+{
+       GeoclueMasterClient *client;
+       GeoclueMasterClientPrivate *priv;
+       DBusGConnection *connection;
+       GObject *object;
+       GError *error = NULL;
+
+       object = G_OBJECT_CLASS (geoclue_master_client_parent_class)->constructor (type, n_props, props);
+       client = GEOCLUE_MASTER_CLIENT (object);
+       priv = GET_PRIVATE (client);
+
+       connection = dbus_g_bus_get (GEOCLUE_DBUS_BUS, &error);
+       if (!connection) {
+               g_warning ("Failed to open connection to bus: %s",
+                          error->message);
+               g_error_free (error);
+
+               priv->proxy = NULL;
+               return object;
+       }
+
+       priv->proxy = dbus_g_proxy_new_for_name_owner (connection,
+                                                      GEOCLUE_MASTER_DBUS_SERVICE,
+                                                      priv->object_path,
+                                                      GEOCLUE_MASTER_CLIENT_DBUS_INTERFACE,
+                                                      &error);
+       if (!priv->proxy) {
+               g_warning ("Failed to create proxy to %s: %s",
+                          priv->object_path,
+                          error->message);
+               g_error_free (error);
+
+               return object;
+       }
+
+       g_signal_connect (priv->proxy, "destroy",
+                         G_CALLBACK (proxy_destroyed), object);
+
+       dbus_g_proxy_add_signal (priv->proxy, "AddressProviderChanged",
+                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+                                G_TYPE_INVALID);
+       dbus_g_proxy_connect_signal (priv->proxy, "AddressProviderChanged",
+                                    G_CALLBACK (address_provider_changed),
+                                    object, NULL);
+
+       dbus_g_proxy_add_signal (priv->proxy, "PositionProviderChanged",
+                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+                                G_TYPE_INVALID);
+       dbus_g_proxy_connect_signal (priv->proxy, "PositionProviderChanged",
+                                    G_CALLBACK (position_provider_changed),
+                                    object, NULL);
+       return object;
+}
+
+static void
+geoclue_master_client_class_init (GeoclueMasterClientClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+       o_class->constructor = constructor;
+       o_class->set_property = set_property;
+       o_class->get_property = get_property;
+
+       g_type_class_add_private (klass, sizeof (GeoclueMasterClientPrivate));
+
+       g_object_class_install_property
+               (o_class, PROP_PATH,
+                g_param_spec_string ("object-path",
+                                     "Object path",
+                                     "The DBus path to the object",
+                                     "",
+                                     G_PARAM_WRITABLE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_NICK |
+                                     G_PARAM_STATIC_BLURB |
+                                     G_PARAM_STATIC_NAME));
+
+       /**
+       * GeoclueMasterClient::address-provider-changed:
+       * @client: the #GeoclueMasterClient object emitting the signal
+       * @name: name of the new provider (e.g. "Hostip") or %NULL if there is no provider
+       * @description: a short description of the new provider or %NULL if there is no provider
+       * @service: D-Bus service name of the new provider or %NULL if there is no provider
+       * @path: D-Bus object path name of the new provider or %NULL if there is no provider
+       *
+       * The address-provider-changed signal is emitted each time the used address provider
+       * changes.
+       **/
+       signals[ADDRESS_PROVIDER_CHANGED] =
+               g_signal_new ("address-provider-changed",
+                             G_TYPE_FROM_CLASS (klass),
+                             G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+                             G_STRUCT_OFFSET (GeoclueMasterClientClass, address_provider_changed),
+                             NULL, NULL,
+                             geoclue_marshal_VOID__STRING_STRING_STRING_STRING,
+                             G_TYPE_NONE, 4,
+                             G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+       /**
+       * GeoclueMasterClient::position-provider-changed:
+       * @client: the #GeoclueMasterClient object emitting the signal
+       * @name: name of the new provider (e.g. "Hostip") or %NULL if there is no provider
+       * @description: a short description of the new provider or %NULL if there is no provider
+       * @service: D-Bus service name of the new provider or %NULL if there is no provider
+       * @path: D-Bus object path name of the new provider or %NULL if there is no provider
+       *
+       * The position-provider-changed signal is emitted each time the used position provider
+       * changes.
+       **/
+       signals[POSITION_PROVIDER_CHANGED] =
+               g_signal_new ("position-provider-changed",
+                             G_TYPE_FROM_CLASS (klass),
+                             G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+                             G_STRUCT_OFFSET (GeoclueMasterClientClass, position_provider_changed),
+                             NULL, NULL,
+                             geoclue_marshal_VOID__STRING_STRING_STRING_STRING,
+                             G_TYPE_NONE, 4,
+                             G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+       /**
+       * GeoclueMasterClient::invalidated:
+       * @client: the #GeoclueMasterClient object emitting the signal
+       *
+       * The client has been invalidated.  This is emitted when Geoclue Dbus
+       * services disappear unexpectedly (possibly due to a crash).  Upon
+       * receiving this signal, you should unref your client and create a new
+       * one.
+       **/
+       signals[INVALIDATED] =
+               g_signal_new ("invalidated",
+                             G_TYPE_FROM_CLASS (klass),
+                             G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+                             G_STRUCT_OFFSET (GeoclueMasterClientClass, invalidated),
+                             NULL, NULL,
+                             g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+}
+
+static void
+geoclue_master_client_init (GeoclueMasterClient *client)
+{
+}
+
+/**
+ * geoclue_master_client_set_requirements:
+ * @client: A #GeoclueMasterClient
+ * @min_accuracy: The required minimum accuracy as a #GeoclueAccuracyLevel.
+ * @min_time: The minimum time between update signals (currently not implemented)
+ * @require_updates: Whether the updates (signals) are required. Only applies to interfaces with signals
+ * @allowed_resources: The resources that are allowed to be used as a #GeoclueResourceFlags
+ * @error: A pointer to returned #GError or %NULL.
+ *
+ * Sets the criteria that should be used when selecting the used provider
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+geoclue_master_client_set_requirements (GeoclueMasterClient   *client,
+                                       GeoclueAccuracyLevel   min_accuracy,
+                                       int                    min_time,
+                                       gboolean               require_updates,
+                                       GeoclueResourceFlags   allowed_resources,
+                                       GError               **error)
+{
+       GeoclueMasterClientPrivate *priv;
+
+       priv = GET_PRIVATE (client);
+       if (!org_freedesktop_Geoclue_MasterClient_set_requirements
+           (priv->proxy, min_accuracy, min_time, require_updates, allowed_resources, error)) {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static void
+set_requirements_callback (DBusGProxy                   *proxy,
+                          GError                       *error,
+                          GeoclueMasterClientAsyncData *data)
+{
+       (*(GeoclueSetRequirementsCallback)data->callback) (data->client,
+                                                          error,
+                                                          data->userdata);
+       g_free (data);
+}
+
+/**
+ * GeoclueSetRequirementsCallback:
+ * @client: A #GeoclueMasterClient object
+ * @error: Error as #Gerror (may be %NULL)
+ * @userdata: User data pointer set in geoclue_master_client_set_requirements_async()
+ *
+ * Callback function for geoclue_master_client_set_requirements_async().
+ */
+
+/**
+ * geoclue_master_client_set_requirements_async:
+ * @client: A #GeoclueMasterClient
+ * @min_accuracy: The required minimum accuracy as a #GeoclueAccuracyLevel.
+ * @min_time: The minimum time between update signals (currently not implemented)
+ * @require_updates: Whether the updates (signals) are required. Only applies to interfaces with signals
+ * @allowed_resources: The resources that are allowed to be used as a #GeoclueResourceFlags
+ * @callback: #GeoclueSetRequirementsCallback function to call when requirements have been set
+ * @userdata: User data pointer
+ *
+ * Asynchronous version of geoclue_master_client_set_requirements().
+ */
+void
+geoclue_master_client_set_requirements_async (GeoclueMasterClient           *client,
+                                             GeoclueAccuracyLevel           min_accuracy,
+                                             int                            min_time,
+                                             gboolean                       require_updates,
+                                             GeoclueResourceFlags           allowed_resources,
+                                             GeoclueSetRequirementsCallback callback,
+                                             gpointer                       userdata)
+{
+       GeoclueMasterClientPrivate *priv = GET_PRIVATE (client);
+       GeoclueMasterClientAsyncData *data;
+
+       data = g_new (GeoclueMasterClientAsyncData, 1);
+       data->client = client;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_MasterClient_set_requirements_async
+                       (priv->proxy,
+                        min_accuracy,
+                        min_time,
+                        require_updates,
+                        allowed_resources,
+                        (org_freedesktop_Geoclue_MasterClient_set_requirements_reply)set_requirements_callback,
+                        data);
+}
+
+/**
+ * geoclue_master_client_create_address:
+ * @client: A #GeoclueMasterClient
+ * @error: A pointer to returned #GError or %NULL.
+ *
+ * Starts the GeoclueMasterClient address provider and returns
+ * a #GeoclueAddress that uses the same D-Bus object as the #GeoclueMasterClient.
+ *
+ * Return value: New #GeoclueAddress or %NULL on error
+ */
+GeoclueAddress *
+geoclue_master_client_create_address (GeoclueMasterClient *client,
+                                      GError **error)
+{
+       GeoclueMasterClientPrivate *priv;
+
+       priv = GET_PRIVATE (client);
+
+       if (!org_freedesktop_Geoclue_MasterClient_address_start (priv->proxy, error)) {
+               return NULL;
+       }
+
+       return geoclue_address_new (GEOCLUE_MASTER_DBUS_SERVICE, priv->object_path);
+}
+
+static void
+address_start_async_callback (DBusGProxy                   *proxy,
+                             GError                       *error,
+                             GeoclueMasterClientAsyncData *data)
+{
+       GeoclueMasterClientPrivate *priv = GET_PRIVATE (data->client);
+       GeoclueAddress *address = NULL;
+
+       if (!error) {
+               address = geoclue_address_new (GEOCLUE_MASTER_DBUS_SERVICE, priv->object_path);
+       }
+
+       (*(CreateAddressCallback)data->callback) (data->client,
+                                                 address,
+                                                 error,
+                                                 data->userdata);
+       g_free (data);
+}
+
+/**
+ * CreateAddressCallback:
+ * @client: A #GeoclueMasterClient object
+ * @address: returned #GeoclueAddress
+ * @error: Error as #Gerror (may be %NULL)
+ * @userdata: User data pointer set in geoclue_master_client_create_address_async()
+ *
+ * Callback function for geoclue_master_client_create_address_async().
+ */
+
+/**
+ * geoclue_master_client_create_address_async:
+ * @client: A #GeoclueMasterClient object
+ * @callback: A #CreateAddressCallback function that should be called when return values are available
+ * @userdata: pointer for user specified data
+ *
+ * Function returns (essentially) immediately and calls @callback when it has started the address provider
+ * and a #GeoclueAddress is available.
+ */
+void
+geoclue_master_client_create_address_async (GeoclueMasterClient  *client,
+                                           CreateAddressCallback callback,
+                                           gpointer              userdata)
+{
+       GeoclueMasterClientPrivate *priv = GET_PRIVATE (client);
+       GeoclueMasterClientAsyncData *data;
+
+       data = g_new (GeoclueMasterClientAsyncData, 1);
+       data->client = client;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_MasterClient_address_start_async
+                       (priv->proxy,
+                        (org_freedesktop_Geoclue_MasterClient_address_start_reply)address_start_async_callback,
+                        data);
+}
+
+
+/**
+ * geoclue_master_client_create_position:
+ * @client: A #GeoclueMasterClient
+ * @error: A pointer to returned #GError or %NULL.
+ *
+ * Starts the GeoclueMasterClient position provider and returns
+ * a #GeocluePosition that uses the same D-Bus object as the #GeoclueMasterClient.
+ *
+ * Return value: New #GeocluePosition or %NULL on error
+ */
+GeocluePosition *
+geoclue_master_client_create_position (GeoclueMasterClient *client,
+                                       GError **error)
+{
+       GeoclueMasterClientPrivate *priv;
+
+       priv = GET_PRIVATE (client);
+
+       if (!org_freedesktop_Geoclue_MasterClient_position_start (priv->proxy, error)) {
+               return NULL;
+       }
+       return geoclue_position_new (GEOCLUE_MASTER_DBUS_SERVICE, priv->object_path);
+}
+
+
+static void
+position_start_async_callback (DBusGProxy                   *proxy,
+                              GError                       *error,
+                              GeoclueMasterClientAsyncData *data)
+{
+       GeoclueMasterClientPrivate *priv = GET_PRIVATE (data->client);
+       GeocluePosition *position = NULL;
+
+       if (!error) {
+               position = geoclue_position_new (GEOCLUE_MASTER_DBUS_SERVICE, priv->object_path);
+       }
+
+       (*(CreatePositionCallback)data->callback) (data->client,
+                                                 position,
+                                                 error,
+                                                 data->userdata);
+       g_free (data);
+}
+
+/**
+ * CreatePositionCallback:
+ * @client: A #GeoclueMasterClient object
+ * @position: returned #GeocluePosition
+ * @error: Error as #Gerror (may be %NULL)
+ * @userdata: User data pointer set in geoclue_master_client_create_position_async()
+ *
+ * Callback function for geoclue_master_client_create_position_async().
+ */
+
+/**
+ * geoclue_master_client_create_position_async:
+ * @client: A #GeoclueMasterClient object
+ * @callback: A #CreatePositionCallback function that should be called when return values are available
+ * @userdata: pointer for user specified data
+ *
+ * Function returns (essentially) immediately and calls @callback when it has started the position provider
+ * and a #GeocluePosition is available.
+ */
+void
+geoclue_master_client_create_position_async (GeoclueMasterClient    *client,
+                                            CreatePositionCallback  callback,
+                                            gpointer                userdata)
+{
+       GeoclueMasterClientPrivate *priv = GET_PRIVATE (client);
+       GeoclueMasterClientAsyncData *data;
+
+       data = g_new (GeoclueMasterClientAsyncData, 1);
+       data->client = client;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_MasterClient_position_start_async
+                       (priv->proxy,
+                        (org_freedesktop_Geoclue_MasterClient_position_start_reply)position_start_async_callback,
+                        data);
+}
+
+
+/**
+ * geoclue_master_client_get_address_provider:
+ * @client: A #GeoclueMasterClient
+ * @name: Pointer to returned provider name or %NULL
+ * @description: Pointer to returned provider description or %NULL
+ * @service: Pointer to returned D-Bus service name or %NULL
+ * @path: Pointer to returned D-Bus object path or %NULL
+ * @error: Pointer to returned #GError or %NULL
+ *
+ * Gets name and other information for the currently used address provider.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean geoclue_master_client_get_address_provider (GeoclueMasterClient  *client,
+                                                     char                **name,
+                                                     char                **description,
+                                                     char                **service,
+                                                     char                **path,
+                                                     GError              **error)
+{
+       GeoclueMasterClientPrivate *priv;
+
+       priv = GET_PRIVATE (client);
+       if (!org_freedesktop_Geoclue_MasterClient_get_address_provider
+           (priv->proxy, name, description, service, path, error)) {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static void
+get_provider_callback (DBusGProxy *proxy,
+                       char * name,
+                       char * description,
+                       char * service,
+                       char * path,
+                       GError *error,
+                       GeoclueMasterClientAsyncData *data)
+{
+
+       (*(GeoclueGetProviderCallback)data->callback) (data->client,
+                                                      name,
+                                                      description,
+                                                      service,
+                                                      path,
+                                                      error,
+                                                      data->userdata);
+       g_free (data);
+}
+
+/**
+ * geoclue_master_client_get_address_provider_async:
+ * @client: A #GeoclueMasterClient
+ * @callback: A #GeoclueGetProviderCallback function that will be called when return values are available
+ * @userdata: pointer for user specified data
+ *
+ * Gets name and other information for the currently used address provider asynchronously.
+ */
+void
+geoclue_master_client_get_address_provider_async (GeoclueMasterClient  *client,
+                                                  GeoclueGetProviderCallback  callback,
+                                                  gpointer userdata)
+{
+       GeoclueMasterClientPrivate *priv = GET_PRIVATE (client);
+       GeoclueMasterClientAsyncData *data;
+
+       data = g_new (GeoclueMasterClientAsyncData, 1);
+       data->client = client;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_MasterClient_get_address_provider_async
+                       (priv->proxy,
+                        (org_freedesktop_Geoclue_MasterClient_get_address_provider_reply)get_provider_callback,
+                        data);
+}
+
+
+/**
+ * geoclue_master_client_get_position_provider:
+ * @client: A #GeoclueMasterClient
+ * @name: Pointer to returned provider name or %NULL
+ * @description: Pointer to returned provider description or %NULL
+ * @service: Pointer to returned D-Bus service name or %NULL
+ * @path: Pointer to returned D-Bus object path or %NULL
+ * @error: Pointer to returned #GError or %NULL
+ *
+ * Gets name and other information for the currently used position provider.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean geoclue_master_client_get_position_provider (GeoclueMasterClient  *client,
+                                                      char                **name,
+                                                      char                **description,
+                                                      char                **service,
+                                                      char                **path,
+                                                      GError              **error)
+{
+       GeoclueMasterClientPrivate *priv;
+
+       priv = GET_PRIVATE (client);
+       if (!org_freedesktop_Geoclue_MasterClient_get_position_provider
+           (priv->proxy, name, description, service, path, error)) {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+/**
+ * geoclue_master_client_get_position_provider_async:
+ * @client: A #GeoclueMasterClient
+ * @callback: A #GeoclueGetProviderCallback function that will be called when return values are available
+ * @userdata: pointer for user specified data
+ *
+ * Gets name and other information for the currently used position provider asynchronously.
+ */
+void
+geoclue_master_client_get_position_provider_async (GeoclueMasterClient  *client,
+                                                   GeoclueGetProviderCallback  callback,
+                                                   gpointer userdata)
+{
+       GeoclueMasterClientPrivate *priv = GET_PRIVATE (client);
+       GeoclueMasterClientAsyncData *data;
+
+       data = g_new (GeoclueMasterClientAsyncData, 1);
+       data->client = client;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_MasterClient_get_position_provider_async
+                       (priv->proxy,
+                        (org_freedesktop_Geoclue_MasterClient_get_position_provider_reply)get_provider_callback,
+                        data);
+}
diff --git a/geoclue/geoclue-master-client.h b/geoclue/geoclue-master-client.h
new file mode 100644 (file)
index 0000000..043f26c
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Geoclue
+ * geoclue-master-client.c - Client API for accessing the Geoclue Master process
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_MASTER_CLIENT_H
+#define _GEOCLUE_MASTER_CLIENT_H
+
+#include <glib-object.h>
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+#include <geoclue/geoclue-position.h>
+#include <geoclue/geoclue-address.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_MASTER_CLIENT_DBUS_INTERFACE "org.freedesktop.Geoclue.MasterClient"
+
+#define GEOCLUE_TYPE_MASTER_CLIENT (geoclue_master_client_get_type ())
+#define GEOCLUE_MASTER_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_MASTER_CLIENT, GeoclueMasterClient))
+#define GEOCLUE_IS_MASTER_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_MASTER_CLIENT))
+
+typedef struct _GeoclueMasterClient {
+       GObject parent;
+} GeoclueMasterClient;
+
+typedef struct _GeoclueMasterClientClass {
+       GObjectClass parent_class;
+       void (* address_provider_changed) (GeoclueMasterClient  *client,
+                                          char                 *name,
+                                          char                 *description,
+                                          char                 *service,
+                                          char                 *path);
+       void (* position_provider_changed) (GeoclueMasterClient  *client,
+                                           char                 *name,
+                                           char                 *description,
+                                           char                 *service,
+                                           char                 *path);
+       void (* invalidated) (GeoclueMasterClient *client);
+} GeoclueMasterClientClass;
+
+GType geoclue_master_client_get_type (void);
+
+gboolean geoclue_master_client_set_requirements (GeoclueMasterClient   *client,
+                                                GeoclueAccuracyLevel   min_accuracy,
+                                                int                    min_time,
+                                                gboolean               require_updates,
+                                                GeoclueResourceFlags   allowed_resources,
+                                                GError               **error);
+typedef void (*GeoclueSetRequirementsCallback) (GeoclueMasterClient  *client,
+                                               GError               *error,
+                                               gpointer              userdata);
+void geoclue_master_client_set_requirements_async (GeoclueMasterClient           *client,
+                                                  GeoclueAccuracyLevel           min_accuracy,
+                                                  int                            min_time,
+                                                  gboolean                       require_updates,
+                                                  GeoclueResourceFlags           allowed_resources,
+                                                  GeoclueSetRequirementsCallback callback,
+                                                  gpointer                       userdata);
+
+GeoclueAddress *geoclue_master_client_create_address (GeoclueMasterClient *client, GError **error);
+typedef void (*CreateAddressCallback) (GeoclueMasterClient *client,
+                                      GeoclueAddress      *address,
+                                      GError              *error,
+                                      gpointer             userdata);
+void geoclue_master_client_create_address_async (GeoclueMasterClient   *client,
+                                                CreateAddressCallback  callback,
+                                                gpointer               userdata);
+
+
+GeocluePosition *geoclue_master_client_create_position (GeoclueMasterClient *client, GError **error);
+typedef void (*CreatePositionCallback) (GeoclueMasterClient *client,
+                                       GeocluePosition     *position,
+                                       GError              *error,
+                                       gpointer             userdata);
+void geoclue_master_client_create_position_async (GeoclueMasterClient   *client,
+                                                 CreatePositionCallback  callback,
+                                                 gpointer               userdata);
+
+gboolean geoclue_master_client_get_address_provider (GeoclueMasterClient  *client,
+                                                     char                **name,
+                                                     char                **description,
+                                                     char                **service,
+                                                     char                **path,
+                                                     GError              **error);
+typedef void (*GeoclueGetProviderCallback) (GeoclueMasterClient  *client,
+                                            char                 *name,
+                                            char                 *description,
+                                            char                 *service,
+                                            char                 *path,
+                                            GError               *error,
+                                            gpointer              userdata);
+void geoclue_master_client_get_address_provider_async (GeoclueMasterClient        *client,
+                                                       GeoclueGetProviderCallback  callback,
+                                                       gpointer                    userdata);
+
+gboolean geoclue_master_client_get_position_provider (GeoclueMasterClient  *client,
+                                                     char                **name,
+                                                     char                **description,
+                                                     char                **service,
+                                                     char                **path,
+                                                     GError              **error);
+void geoclue_master_client_get_position_provider_async (GeoclueMasterClient        *client,
+                                                       GeoclueGetProviderCallback  callback,
+                                                       gpointer userdata);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/geoclue-master.c b/geoclue/geoclue-master.c
new file mode 100644 (file)
index 0000000..efdb623
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Geoclue
+ * geoclue-master.c - Client API for accessing the Geoclue Master process
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:geoclue-master
+ * @short_description: Geoclue Master API
+ * @see_also: #GeoclueMasterClient
+ *
+ * #GeoclueMaster is part of the Geoclue public C client API. It uses
+ * D-Bus to communicate with the actual Master service.
+ *
+ * #GeoclueMaster is a singleton service, so it should not be created
+ * explicitly: instead one should use geoclue_master_get_default() to
+ * get a reference to it. It can be used to
+ * create a #GeoclueMasterClient object.
+ *
+ */
+
+#include <config.h>
+
+#include <geoclue/geoclue-master.h>
+#include <geoclue/geoclue-accuracy.h>
+
+#include "gc-iface-master-bindings.h"
+
+typedef struct _GeoclueMasterPrivate {
+       DBusGProxy *proxy;
+} GeoclueMasterPrivate;
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_MASTER, GeoclueMasterPrivate))
+
+G_DEFINE_TYPE (GeoclueMaster, geoclue_master, G_TYPE_OBJECT);
+
+
+typedef struct _GeoclueMasterAsyncData {
+       GeoclueMaster *master;
+       GCallback callback;
+       gpointer userdata;
+} GeoclueMasterAsyncData;
+
+
+static void
+finalize (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_master_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_master_parent_class)->dispose (object);
+}
+
+static void
+geoclue_master_class_init (GeoclueMasterClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+
+       g_type_class_add_private (klass, sizeof (GeoclueMasterPrivate));
+}
+
+static void
+geoclue_master_init (GeoclueMaster *master)
+{
+       GeoclueMasterPrivate *priv;
+       DBusGConnection *connection;
+       GError *error = NULL;
+
+       priv = GET_PRIVATE (master);
+
+       connection = dbus_g_bus_get (GEOCLUE_DBUS_BUS, &error);
+       if (!connection) {
+               g_warning ("Unable to get connection to Geoclue bus.\n%s",
+                          error->message);
+               g_error_free (error);
+               return;
+       }
+
+       priv->proxy = dbus_g_proxy_new_for_name (connection,
+                                                GEOCLUE_MASTER_DBUS_SERVICE,
+                                                GEOCLUE_MASTER_DBUS_PATH,
+                                                GEOCLUE_MASTER_DBUS_INTERFACE);
+}
+
+/**
+ * geoclue_master_get_default:
+ *
+ * Returns the default #GeoclueMaster object. Should be unreferenced once
+ * the client is finished with it.
+ *
+ * Return value: A reference to the default #GeoclueMaster object
+ */
+GeoclueMaster *
+geoclue_master_get_default (void)
+{
+       static GeoclueMaster *master = NULL;
+
+       if (G_UNLIKELY (master == NULL)) {
+               master = g_object_new (GEOCLUE_TYPE_MASTER, NULL);
+               g_object_add_weak_pointer (G_OBJECT (master),
+                                          (gpointer) &master);
+               return master;
+       }
+
+       return g_object_ref (master);
+}
+
+/**
+ * geoclue_master_create_client:
+ * @master: A #GeoclueMaster object
+ * @object_path: Pointer to returned #GeoclueMasterClient D-Bus object path or %NULL
+ * @error: Pointer to returned #GError or %NULL
+ *
+ * Creates a #GeoclueMasterClient and puts the D-Bus object path in
+ * @object_path.
+ *
+ * Return Value: A new #GeoclueMasterClient or %NULL on error.
+ */
+
+GeoclueMasterClient *
+geoclue_master_create_client (GeoclueMaster *master,
+                             char         **object_path,
+                             GError       **error)
+{
+       GeoclueMasterPrivate *priv;
+       GeoclueMasterClient *client;
+       char *path;
+
+       g_return_val_if_fail (GEOCLUE_IS_MASTER (master), NULL);
+
+       priv = GET_PRIVATE (master);
+
+       if (!org_freedesktop_Geoclue_Master_create (priv->proxy,
+                                                   &path, error)){
+               return NULL;
+       }
+
+       client = g_object_new (GEOCLUE_TYPE_MASTER_CLIENT,
+                              "object-path", path,
+                              NULL);
+
+       if (object_path) {
+               *object_path = path;
+       } else {
+               g_free (path);
+       }
+
+       return client;
+}
+
+static void
+create_client_callback (DBusGProxy             *proxy,
+                       char                   *path,
+                       GError                 *error,
+                       GeoclueMasterAsyncData *data)
+{
+       GeoclueMasterClient *client;
+
+       client = NULL;
+
+       if (!error) {
+               client = g_object_new (GEOCLUE_TYPE_MASTER_CLIENT,
+                                      "object-path", path,
+                                      NULL);
+       }
+
+       (*(GeoclueCreateClientCallback)data->callback) (data->master,
+                                                       client,
+                                                       path,
+                                                       error,
+                                                       data->userdata);
+
+       g_free (data);
+}
+
+void
+geoclue_master_create_client_async (GeoclueMaster              *master,
+                                   GeoclueCreateClientCallback callback,
+                                   gpointer                    userdata)
+{
+       GeoclueMasterPrivate *priv;
+       GeoclueMasterAsyncData *data;
+
+       g_return_if_fail (GEOCLUE_IS_MASTER (master));
+
+       priv = GET_PRIVATE (master);
+       data = g_new (GeoclueMasterAsyncData, 1);
+       data->master = master;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_Master_create_async
+                       (priv->proxy,
+                        (org_freedesktop_Geoclue_Master_create_reply)create_client_callback,
+                        data);
+}
diff --git a/geoclue/geoclue-master.h b/geoclue/geoclue-master.h
new file mode 100644 (file)
index 0000000..8931adb
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Geoclue
+ * geoclue-master.h -
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_MASTER_H
+#define _GEOCLUE_MASTER_H
+
+#include <glib-object.h>
+#include <geoclue/geoclue-master-client.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_MASTER_DBUS_SERVICE "org.freedesktop.Geoclue.Master"
+#define GEOCLUE_MASTER_DBUS_PATH "/org/freedesktop/Geoclue/Master"
+#define GEOCLUE_MASTER_DBUS_INTERFACE "org.freedesktop.Geoclue.Master"
+
+#define GEOCLUE_TYPE_MASTER (geoclue_master_get_type ())
+#define GEOCLUE_MASTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_MASTER, GeoclueMaster))
+#define GEOCLUE_IS_MASTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_MASTER))
+
+typedef struct _GeoclueMaster {
+       GObject parent;
+} GeoclueMaster;
+
+typedef struct _GeoclueMasterClass {
+       GObjectClass parent_class;
+} GeoclueMasterClass;
+
+GType geoclue_master_get_type (void);
+
+GeoclueMaster *geoclue_master_get_default (void);
+
+GeoclueMasterClient *geoclue_master_create_client (GeoclueMaster *master,
+                                                  char         **object_path,
+                                                  GError       **error);
+typedef void (*GeoclueCreateClientCallback) (GeoclueMaster       *master,
+                                            GeoclueMasterClient *client,
+                                            char                *object_path,
+                                            GError              *error,
+                                            gpointer             userdata);
+void geoclue_master_create_client_async (GeoclueMaster              *master,
+                                        GeoclueCreateClientCallback callback,
+                                        gpointer                    userdata);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/geoclue-nmea.c b/geoclue/geoclue-nmea.c
new file mode 100644 (file)
index 0000000..a63f696
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Geoclue
+ * geoclue-nmea.c - Client API for accessing GcIfaceNmea
+ *
+ * Author: Tae-Hwan Kim <the81.kim@samsung.com>, Youngae Kang <youngae.kang@samsung.com>,
+ *         Yunhan Kim <yhan.kim@samsung.com>, Genie Kim <daejins.kim@samsung.com>
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:geoclue-nmea
+ * @short_description: Geoclue nmea client API
+ *
+ * #GeoclueNmea contains nmea-related methods and signals.
+ * It is part of the Geoclue public C client API which uses D-Bus
+ * to communicate with the actual provider.
+ *
+ * After a #GeoclueNmea is created with geoclue_nmea_new() or
+ * using geoclye_master_client_create_nmea(), the
+ * geoclue_nmea_get_nmea() and geoclue_nmea_get_nmea_async()
+ * method and the nmea-changed signal can be used to obtain the current nmea.
+ */
+
+#include <geoclue/geoclue-nmea.h>
+#include <geoclue/geoclue-marshal.h>
+
+#include "gc-iface-nmea-bindings.h"
+
+//#include <glib.h>
+#include <string.h>
+
+typedef struct _GeoclueNmeaPrivate {
+       int dummy;
+} GeoclueNmeaPrivate;
+
+enum {
+       NMEA_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_NMEA, GeoclueNmeaPrivate))
+
+G_DEFINE_TYPE (GeoclueNmea, geoclue_nmea, GEOCLUE_TYPE_PROVIDER);
+
+static void
+finalize (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_nmea_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_nmea_parent_class)->dispose (object);
+}
+
+static void
+nmea_changed (DBusGProxy      *proxy,
+             int              timestamp,
+             char             *nmea_data,
+             GeoclueNmea *nmea)
+{
+       g_signal_emit (nmea, signals[NMEA_CHANGED], 0,
+                      timestamp, nmea_data);
+}
+
+static GObject *
+constructor (GType                  type,
+            guint                  n_props,
+            GObjectConstructParam *props)
+{
+       GObject *object;
+       GeoclueProvider *provider;
+
+       object = G_OBJECT_CLASS (geoclue_nmea_parent_class)->constructor (type, n_props, props);
+       provider = GEOCLUE_PROVIDER (object);
+
+       dbus_g_proxy_add_signal (provider->proxy, "NmeaChanged",
+                                G_TYPE_INT,
+                                G_TYPE_STRING,
+                                G_TYPE_INVALID);
+       dbus_g_proxy_connect_signal (provider->proxy, "NmeaChanged",
+                                    G_CALLBACK (nmea_changed),
+                                    object, NULL);
+
+       return object;
+}
+
+static void
+geoclue_nmea_class_init (GeoclueNmeaClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+       o_class->constructor = constructor;
+
+       g_type_class_add_private (klass, sizeof (GeoclueNmeaPrivate));
+
+       signals[NMEA_CHANGED] = g_signal_new ("nmea-changed",
+                                             G_TYPE_FROM_CLASS (klass),
+                                             G_SIGNAL_RUN_FIRST |
+                                             G_SIGNAL_NO_RECURSE,
+                                             G_STRUCT_OFFSET (GeoclueNmeaClass, nmea_changed),
+                                             NULL, NULL,
+                                             geoclue_marshal_VOID__INT_STRING,
+                                             G_TYPE_NONE, 2,
+                                             G_TYPE_INT,
+                                             G_TYPE_STRING);
+}
+
+static void
+geoclue_nmea_init (GeoclueNmea *nmea)
+{
+}
+
+/**
+ * geoclue_nmea_new:
+ * @service: D-Bus service name
+ * @path: D-Bus path name
+ *
+ * Creates a #GeoclueNmea with given D-Bus service name and path.
+ *
+ * Return value: Pointer to a new #GeoclueNmea
+ */
+GeoclueNmea *
+geoclue_nmea_new (const char *service,
+                     const char *path)
+{
+       return g_object_new (GEOCLUE_TYPE_NMEA,
+                            "service", service,
+                            "path", path,
+                            "interface", GEOCLUE_NMEA_INTERFACE_NAME,
+                            NULL);
+}
+
+gboolean
+geoclue_nmea_get_nmea (GeoclueNmea  *nmea,
+                      int          *timestamp,
+                      char        **nmea_data,
+                      GError      **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (nmea);
+
+       if (!org_freedesktop_Geoclue_Nmea_get_nmea (provider->proxy,
+                                                   timestamp,
+                                                   nmea_data,
+                                                   error)) {
+               return FALSE;
+       }
+       return TRUE;
+}
+
+
+typedef struct _GeoclueNmeaAsyncData {
+       GeoclueNmea *nmea;
+       GCallback callback;
+       gpointer userdata;
+} GeoclueNmeaAsyncData;
+
+static void
+get_nmea_async_callback (DBusGProxy           *proxy,
+                        int                   timestamp,
+                        char                 *nmea_data,
+                        GError               *error,
+                        GeoclueNmeaAsyncData *data)
+{
+       (*(GeoclueNmeaCallback)data->callback) (data->nmea,
+                                               timestamp,
+                                               nmea_data,
+                                               error,
+                                               data->userdata);
+       g_free (data);
+}
+
+void
+geoclue_nmea_get_nmea_async (GeoclueNmea         *nmea,
+                            GeoclueNmeaCallback  callback,
+                            gpointer             userdata)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (nmea);
+       GeoclueNmeaAsyncData *data;
+
+       data = g_new (GeoclueNmeaAsyncData, 1);
+       data->nmea = nmea;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_Nmea_get_nmea_async (
+                       provider->proxy,
+                       (org_freedesktop_Geoclue_Nmea_get_nmea_reply)get_nmea_async_callback,
+                       data);
+}
diff --git a/geoclue/geoclue-nmea.h b/geoclue/geoclue-nmea.h
new file mode 100644 (file)
index 0000000..aabd1da
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Geoclue
+ * geoclue-nmea.h -
+ *
+ * Author: Tae-Hwan Kim <the81.kim@samsung.com>, Youngae Kang <youngae.kang@samsung.com>,
+ *         Yunhan Kim <yhan.kim@samsung.com>, Genie Kim <daejins.kim@samsung.com>
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef _GEOCLUE_NMEA_H
+#define _GEOCLUE_NMEA_H
+
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-types.h>
+//#include <geoclue/geoclue-accuracy.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_NMEA (geoclue_nmea_get_type ())
+#define GEOCLUE_NMEA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_NMEA, GeoclueNmea))
+#define GEOCLUE_IS_NMEA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_NMEA))
+
+#define GEOCLUE_NMEA_INTERFACE_NAME "org.freedesktop.Geoclue.Nmea"
+
+#define GEOCLUE_MAX_NMEA_DATA_SIZE (1500)
+
+typedef struct _GeoclueNmea {
+       GeoclueProvider provider;
+} GeoclueNmea;
+
+typedef struct _GeoclueNmeaClass {
+       GeoclueProviderClass provider_class;
+
+       void (* nmea_changed) (GeoclueNmea *nmea,
+                              int          timestamp,
+                              char         nmea_data[GEOCLUE_MAX_NMEA_DATA_SIZE]);
+} GeoclueNmeaClass;
+
+GType geoclue_nmea_get_type (void);
+
+GeoclueNmea *geoclue_nmea_new (const char *service,
+                              const char *path);
+
+gboolean geoclue_nmea_get_nmea (GeoclueNmea *nmea,
+                               int         *timestamp,
+                               char       **nmea_data,
+                               GError     **error);
+
+typedef void (*GeoclueNmeaCallback) (GeoclueNmea *nmea,
+                                    int          timestamp,
+                                    char        *nmea_data,
+                                    GError      *error,
+                                    gpointer     userdata);
+
+void geoclue_nmea_get_nmea_async (GeoclueNmea         *nmea,
+                                 GeoclueNmeaCallback  callback,
+                                 gpointer             userdata);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/geoclue-poi.c b/geoclue/geoclue-poi.c
new file mode 100644 (file)
index 0000000..8a5a9f4
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Geoclue
+ * geoclue-poi.c - Client API for accessing GcIfacePoi
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ *          Jussi Kukkonen <jku@linux.intel.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *           2010 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:geoclue-poi
+ * @short_description: Geoclue poi client API
+ *
+ * #GeocluePoi contains geocoding methods.
+ * It is part of the Geoclue public C client API which uses D-Bus
+ * to communicate with the actual provider.
+ *
+ * After a #GeocluePoi is created with geoclue_poi_new(), the
+ * geoclue_poi_address_to_position(),
+ * geoclue_poi_freeform_address_to_position() methods and their
+ * asynchronous counterparts can be used to obtain the position (coordinates)
+ * of the given address.
+ *
+ * Address #GHashTable keys are defined in
+ * <ulink url="geoclue-types.html">geoclue-types.h</ulink>. See also
+ * convenience functions in
+ * <ulink url="geoclue-address-details.html">geoclue-address-details.h</ulink>.
+ */
+
+#include <geoclue/geoclue-poi.h>
+#include <geoclue/geoclue-marshal.h>
+#include <geoclue/geoclue-landmark.h>
+
+#include "gc-iface-poi-bindings.h"
+
+typedef struct _GeocluePoiPrivate {
+       int dummy;
+} GeocluePoiPrivate;
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_POI, GeocluePoiPrivate))
+
+G_DEFINE_TYPE (GeocluePoi, geoclue_poi, GEOCLUE_TYPE_PROVIDER);
+
+static void
+finalize (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_poi_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_poi_parent_class)->dispose (object);
+}
+
+static void
+geoclue_poi_class_init (GeocluePoiClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+
+       g_type_class_add_private (klass, sizeof (GeocluePoiPrivate));
+}
+
+static void
+geoclue_poi_init (GeocluePoi *poi)
+{
+}
+
+/**
+ * geoclue_poi_new:
+ * @service: D-Bus service name
+ * @path: D-Bus path name
+ *
+ * Creates a #GeocluePoi with given D-Bus service name and path.
+ *
+ * Return value: Pointer to a new #GeocluePoi
+ */
+GeocluePoi *
+geoclue_poi_new (const char *service,
+                    const char *path)
+{
+       return g_object_new (GEOCLUE_TYPE_POI,
+                            "service", service,
+                            "path", path,
+                            "interface", GEOCLUE_POI_INTERFACE_NAME,
+                            NULL);
+}
+
+/**
+ * geoclue_poi_address_to_position:
+ * @poi: A #GeocluePoi object
+ * @details: Hashtable with address data
+ * @latitude: Pointer to returned latitude in degrees or %NULL
+ * @longitude: Pointer to returned longitude in degrees or %NULL
+ * @altitude: Pointer to returned altitude in meters or %NULL
+ * @accuracy: Pointer to returned #GeoclueAccuracy or %NULL
+ * @error: Pointer to returned #Gerror or %NULL
+ *
+ * Pois given address to coordinates (@latitude, @longitude, @altitude).
+ * see <ulink url="geoclue-types.html">geoclue-types.h</ulink> for the
+ * hashtable keys usable in @details. @accuracy is a rough estimate of
+ * the accuracy of the returned position.
+ *
+ * If the caller is not interested in some values, the pointers can be
+ * left %NULL.
+ *
+ * Return value: A #GeocluePositionFields bitfield representing the
+ * validity of the returned coordinates.
+ */
+gboolean
+geoclue_poi_search_by_position (GeocluePoi             *poi,
+                                                                const char             *keyword,
+                                                                const char             *lang,
+                                                                const char             *country_code,
+                                                                int                            limit,
+                                                                double                 left,
+                                                                double                 top,
+                                                                double                 right,
+                                                                double                 bottom,
+                                                                int                    *count,
+                                                                GPtrArray              **landmark,
+                                                                GError                 **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (poi);
+       if (!org_freedesktop_Geoclue_Poi_search_by_position (provider->proxy,
+                                                                 keyword, lang, country_code, limit, left, top, right, bottom, count,
+                                                                 landmark, error)){
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+typedef struct _GeocluePoiAsyncData {
+       GeocluePoi *poi;
+       GCallback callback;
+       gpointer userdata;
+} GeocluePoiAsyncData;
+
+static void
+_geoclue_poi_callback (DBusGProxy              *proxy,
+                                int                    count,
+                                 GPtrArray                             *landmark,
+                             GError                                                *error,
+                             GeocluePoiAsyncData                                       *data)
+{
+
+       (*(GeocluePoiCallback)data->callback) (data->poi, count, landmark, error, data->userdata);
+       g_free (data);
+}
+
+/**
+ * GeocluePoiCallback:
+ * @poi: A #GeocluePoi object
+ * @fields: A #GeocluePositionFields bitfield representing the validity of the position values
+ * @latitude: Latitude in degrees
+ * @longitude: Longitude in degrees
+ * @altitude: Altitude in meters
+ * @accuracy: Accuracy of measurement as #GeoclueAccuracy
+ * @error: Error as #Gerror or %NULL
+ * @userdata: User data pointer
+ *
+ * Callback function for the asynchronous methods.
+ */
+
+/**
+ * geoclue_poi_address_to_position_async:
+ * @poi: A #GeocluePoi object
+ * @details: A #GHashTable with address data
+ * @callback: A #GeoclueAddressCallback function that should be called when return values are available
+ * @userdata: pointer for user specified data
+ *
+ * Function returns (essentially) immediately and calls @callback when the poid
+ * position data is available or when D-Bus timeouts.
+ *
+ * see <ulink url="geoclue-types.html">geoclue-types.h</ulink> for the
+ * hashtable keys usable in @details.
+ *
+ */
+void
+geoclue_poi_search_by_position_async (GeocluePoi        *poi,
+                               const char              *keyword,
+                               const char              *lang,
+                               const char              *country_code,
+                               int                     limit,
+                               double                  left,
+                               double                  top,
+                               double                  right,
+                               double                  bottom,
+                               GeocluePoiCallback      callback,
+                               gpointer                userdata)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (poi);
+       GeocluePoiAsyncData *data;
+
+       data = g_new (GeocluePoiAsyncData, 1);
+       data->poi = poi;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_Poi_search_by_position_async
+                       (provider->proxy,
+                        keyword, lang, country_code, limit, left, top, right, bottom,
+                        (org_freedesktop_Geoclue_Poi_search_by_position_reply)_geoclue_poi_callback,
+                        data);
+}
diff --git a/geoclue/geoclue-poi.h b/geoclue/geoclue-poi.h
new file mode 100644 (file)
index 0000000..11e2340
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Geoclue
+ * geoclue-poi.h -
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ *          Jussi Kukkonen <jku@linux.intel.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *           2010 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_POI_H
+#define _GEOCLUE_POI_H
+
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+#include <geoclue/geoclue-address-details.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_POI (geoclue_poi_get_type ())
+#define GEOCLUE_POI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_POI, GeocluePoi))
+#define GEOCLUE_IS_POI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_POI))
+
+#define GEOCLUE_POI_INTERFACE_NAME "org.freedesktop.Geoclue.Poi"
+
+typedef struct _GeocluePoi {
+       GeoclueProvider provider;
+} GeocluePoi;
+
+typedef struct _GeocluePoiClass {
+       GeoclueProviderClass provider_class;
+} GeocluePoiClass;
+
+GType geoclue_poi_get_type (void);
+
+GeocluePoi *geoclue_poi_new (const char *service,
+                                    const char *path);
+
+gboolean
+geoclue_poi_search_by_position (GeocluePoi     *poi,
+                               const char      *keyword,
+                               const char      *lang,
+                               const char      *country_code,
+                               int             limit,
+                               double          left,
+                               double          top,
+                               double          right,
+                               double          bottom,
+                               int             *count,
+                               GPtrArray       **landmark,
+                               GError          **error);
+
+typedef void (*GeocluePoiCallback) (GeocluePoi         *poi,
+                               int                             count,
+                               GPtrArray                               *landmark,
+                               GError                  *error,
+                               gpointer                userdata);
+
+void
+geoclue_poi_search_by_position_async (GeocluePoi        *poi,
+                               const char              *keyword,
+                               const char              *lang,
+                               const char              *country_code,
+                               int                     limit,
+                               double                  left,
+                               double                  top,
+                               double                  right,
+                               double                  bottom,
+                               GeocluePoiCallback      callback,
+                               gpointer                userdata);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/geoclue-position-ext.c b/geoclue/geoclue-position-ext.c
new file mode 100644 (file)
index 0000000..08d52fe
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * Geoclue
+ * geoclue-position-ext.c - Client API for accessing GcIfacePosition
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:geoclue-position-ext
+ * @short_description: Geoclue position & velocity client API
+ *
+ * #GeocluePositionVelocity contains position & velocity related methods and signals.
+ * It is part of the Geoclue public C client API which uses D-Bus
+ * to communicate with the actual provider.
+ *
+ * After a #GeocluePositionExt is created with geoclue_position_ext_new() or
+ * using geoclye_master_client_create_position_velocity(), the
+ * geoclue_position_ext_get_position() and geoclue_position_ext_get_position_async()
+ * method and the position-changed signal can be used to obtain the current position & velocity.
+ */
+
+#include <geoclue/geoclue-position-ext.h>
+#include <geoclue/geoclue-marshal.h>
+
+#include "gc-iface-position-ext-bindings.h"
+
+typedef struct _GeocluePositionExtPrivate {
+       int dummy;
+} GeocluePositionExtPrivate;
+
+enum {
+       POSITION_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_POSITION_EXT, GeocluePositionExtPrivate))
+
+G_DEFINE_TYPE (GeocluePositionExt, geoclue_position_ext, GEOCLUE_TYPE_PROVIDER);
+
+static void
+finalize (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_position_ext_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_position_ext_parent_class)->dispose (object);
+}
+
+static void
+position_changed (DBusGProxy      *proxy,
+                 int              fields,
+                 int              timestamp,
+                 double           latitude,
+                 double           longitude,
+                 double           altitude,
+                 double           speed,
+                 double           direction,
+                 double           velocity,
+                 GeoclueAccuracy *accuracy,
+                 GeocluePositionExt *position)
+{
+       g_signal_emit (position, signals[POSITION_CHANGED], 0, fields,
+                      timestamp, latitude, longitude, altitude, speed, direction, velocity, accuracy);
+}
+
+static GObject *
+constructor (GType                  type,
+            guint                  n_props,
+            GObjectConstructParam *props)
+{
+       GObject *object;
+       GeoclueProvider *provider;
+
+       object = G_OBJECT_CLASS (geoclue_position_ext_parent_class)->constructor
+               (type, n_props, props);
+       provider = GEOCLUE_PROVIDER (object);
+
+       dbus_g_proxy_add_signal (provider->proxy, "PositionChanged",
+                                G_TYPE_INT, G_TYPE_INT, G_TYPE_DOUBLE,
+                                G_TYPE_DOUBLE, G_TYPE_DOUBLE,
+                                G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE,
+                                 GEOCLUE_ACCURACY_TYPE,
+                                G_TYPE_INVALID);
+       dbus_g_proxy_connect_signal (provider->proxy, "PositionChanged",
+                                    G_CALLBACK (position_changed),
+                                    object, NULL);
+
+       return object;
+}
+
+static void
+geoclue_position_ext_class_init (GeocluePositionExtClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+       o_class->constructor = constructor;
+
+       g_type_class_add_private (klass, sizeof (GeocluePositionExtPrivate));
+
+       /**
+        * GeocluePosition::position--changed:
+        * @position: the #GeocluePositionExt object emitting the signal
+        * @fields: A #GeocluePositionExtFields bit field representing the validity of the position values
+        * @timestamp: Time of position measurement (Unix timestamp)
+        * @latitude: Latitude in degrees
+        * @longitude: Longitude in degrees
+        * @altitude: Altitude in meters
+        * @speed: Horizontal speed in m/s
+        * @direction: Horizontal direction in degrees
+        * @climb: Vertical speed
+        * @accuracy: Accuracy of measurement as #GeoclueAccuracy
+        *
+        * The position-changed signal is emitted each time the position changes. Clients should note
+        * that not all providers support signals.
+        */
+       signals[POSITION_CHANGED] = g_signal_new ("position-changed",
+                                                 G_TYPE_FROM_CLASS (klass),
+                                                 G_SIGNAL_RUN_FIRST |
+                                                 G_SIGNAL_NO_RECURSE,
+                                                 G_STRUCT_OFFSET (GeocluePositionExtClass, position_changed),
+                                                 NULL, NULL,
+                                                 geoclue_marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE_DOUBLE_DOUBLE_DOUBLE_BOXED,
+                                                 G_TYPE_NONE, 9,
+                                                 G_TYPE_INT, G_TYPE_INT,
+                                                 G_TYPE_DOUBLE, G_TYPE_DOUBLE,
+                                                 G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE,
+                                                 G_TYPE_DOUBLE, G_TYPE_POINTER);
+}
+
+static void
+geoclue_position_ext_init (GeocluePositionExt *position)
+{
+}
+
+/**
+ * geoclue_position_ext_new:
+ * @service: D-Bus service name
+ * @path: D-Bus path name
+ *
+ * Creates a #GeocluePositionExt with given D-Bus service name and path.
+ *
+ * Return value: Pointer to a new #GeocluePositionExt
+ */
+GeocluePositionExt *
+geoclue_position_ext_new (const char *service,
+                     const char *path)
+{
+       return g_object_new (GEOCLUE_TYPE_POSITION_EXT,
+                            "service", service,
+                            "path", path,
+                            "interface", GEOCLUE_POSITION_EXT_INTERFACE_NAME,
+                            NULL);
+}
+
+/**
+ * geoclue_position_ext_get_position:
+ * @position: A #GeocluePositionExt object
+ * @timestamp: Pointer to returned time of position measurement (Unix timestamp) or %NULL
+ * @latitude: Pointer to returned latitude in degrees or %NULL
+ * @longitude: Pointer to returned longitude in degrees or %NULL
+ * @altitude: Pointer to returned altitude in meters or %NULL
+ * @speed: Pointer to returned horizontal speed or %NULL
+ * @direction: Pointer to returned horizontal direction (bearing) or %NULL
+ * @climb: Pointer to returned vertical speed or %NULL
+ * @accuracy: Pointer to returned #GeoclueAccuracy or %NULL
+ * @error: Pointer to returned #Gerror or %NULL
+ *
+ * Obtains the current position & velocity. @timestamp will contain the time of
+ * the actual position & velocity measurement. @accuracy is a rough estimate of the
+ * accuracy of the current position & velocity.
+ *
+ * If the caller is not interested in some values, the pointers can be
+ * left %NULL.
+ *
+ * Return value: A #GeocluePositionExtFields bitfield representing the
+ * validity of the position & velocity values.
+ */
+GeocluePositionExtFields
+geoclue_position_ext_get_position (GeocluePositionExt  *position,
+                              int              *timestamp,
+                              double           *latitude,
+                              double           *longitude,
+                              double           *altitude,
+                              double           *speed,
+                              double           *direction,
+                              double           *climb,
+                              GeoclueAccuracy **accuracy,
+                              GError          **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (position);
+       double la, lo, al;
+       double sp, di, cl;
+       int ts, fields;
+       GeoclueAccuracy *acc;
+       if (!org_freedesktop_Geoclue_PositionExt_get_position (provider->proxy,
+                                                           &fields, &ts,
+                                                           &la, &lo, &al,
+                                                           &sp, &di, &cl,
+                                                           &acc, error)) {
+               return GEOCLUE_POSITION_EXT_FIELDS_NONE;
+       }
+
+       if (timestamp != NULL) {
+               *timestamp = ts;
+       }
+
+       if (latitude != NULL && (fields & GEOCLUE_POSITION_EXT_FIELDS_LATITUDE)) {
+               *latitude = la;
+       }
+
+       if (longitude != NULL && (fields & GEOCLUE_POSITION_EXT_FIELDS_LONGITUDE)) {
+               *longitude = lo;
+       }
+
+       if (altitude != NULL && (fields & GEOCLUE_POSITION_EXT_FIELDS_ALTITUDE)) {
+               *altitude = al;
+       }
+
+       if (speed != NULL && (fields & GEOCLUE_POSITION_EXT_FIELDS_SPEED)) {
+               *speed = sp;
+       }
+
+       if (direction != NULL && (fields & GEOCLUE_POSITION_EXT_FIELDS_DIRECTION)) {
+               *direction = di;
+       }
+
+       if (climb != NULL && (fields & GEOCLUE_POSITION_EXT_FIELDS_CLIMB)) {
+               *climb = cl;
+       }
+
+       if (accuracy != NULL) {
+               *accuracy = acc;
+       }
+
+       return fields;
+}
+
+/**
+ * geoclue_position_ext_get_last_position:
+ * @position: A #GeocluePositionExt object
+ * @timestamp: Pointer to returned time of position measurement (Unix timestamp) or %NULL
+ * @latitude: Pointer to returned latitude in degrees or %NULL
+ * @longitude: Pointer to returned longitude in degrees or %NULL
+ * @altitude: Pointer to returned altitude in meters or %NULL
+ * @accuracy: Pointer to returned #GeoclueAccuracy or %NULL
+ * @speed: Pointer to returned horizontal speed or %NULL
+ * @direction: Pointer to returned horizontal direction (bearing) or %NULL
+ * @climb: Pointer to returned vertical speed or %NULL
+ * @error: Pointer to returned #Gerror or %NULL
+ *
+ * Obtains the last position & velocity. @timestamp will contain the time of
+ * the actual position measurement. @accuracy is a rough estimate of the
+ * accuracy of the last position.
+ *
+ * If the caller is not interested in some values, the pointers can be
+ * left %NULL.
+ *
+ * Return value: A #GeocluePositionExtFields bitfield representing the
+ * validity of the position values.
+ */
+GeocluePositionExtFields
+geoclue_position_ext_get_last_position (GeocluePositionExt  *position,
+                                   int              *timestamp,
+                                   double           *latitude,
+                                   double           *longitude,
+                                   double           *altitude,
+                                   double           *speed,
+                                   double           *direction,
+                                   double           *climb,
+                                   GeoclueAccuracy **accuracy,
+                                   GError          **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (position);
+       double la, lo, al;
+       double sp, di, cl;
+       int ts, fields;
+       GeoclueAccuracy *acc;
+       if (!org_freedesktop_Geoclue_PositionExt_get_last_position (provider->proxy,
+                                                                &fields, &ts,
+                                                                &la, &lo, &al,
+                                                                &sp, &di, &cl,
+                                                                &acc, error)) {
+               return GEOCLUE_POSITION_FIELDS_NONE;
+       }
+
+       if (timestamp != NULL) {
+               *timestamp = ts;
+       }
+
+       if (latitude != NULL && (fields & GEOCLUE_POSITION_EXT_FIELDS_LATITUDE)) {
+               *latitude = la;
+       }
+
+       if (longitude != NULL && (fields & GEOCLUE_POSITION_EXT_FIELDS_LONGITUDE)) {
+               *longitude = lo;
+       }
+
+       if (altitude != NULL && (fields & GEOCLUE_POSITION_EXT_FIELDS_ALTITUDE)) {
+               *altitude = al;
+       }
+
+       if (speed != NULL && (fields & GEOCLUE_POSITION_EXT_FIELDS_SPEED)) {
+               *speed = sp;
+       }
+
+       if (direction != NULL && (fields & GEOCLUE_POSITION_EXT_FIELDS_DIRECTION)) {
+               *direction = di;
+       }
+
+       if (climb != NULL && (fields & GEOCLUE_POSITION_EXT_FIELDS_CLIMB)) {
+               *climb = cl;
+       }
+
+       if (accuracy != NULL) {
+               *accuracy = acc;
+       }
+
+       return fields;
+}
+
+typedef struct _GeocluePositionExtAsyncData {
+       GeocluePositionExt *position;
+       GCallback callback;
+       gpointer userdata;
+} GeocluePositionExtAsyncData;
+
+static void
+get_position_async_callback (DBusGProxy               *proxy,
+                            GeocluePositionExtFields     fields,
+                            int                       timestamp,
+                            double                    latitude,
+                            double                    longitude,
+                            double                    altitude,
+                            double                    speed,
+                            double                    direction,
+                            double                    climb,
+                            GeoclueAccuracy          *accuracy,
+                            GError                   *error,
+                            GeocluePositionExtAsyncData *data)
+{
+       (*(GeocluePositionExtCallback)data->callback) (data->position,
+                                                   fields,
+                                                   timestamp,
+                                                   latitude,
+                                                   longitude,
+                                                   altitude,
+                                                   speed,
+                                                   direction,
+                                                   climb,
+                                                   accuracy,
+                                                   error,
+                                                   data->userdata);
+       g_free (data);
+}
+
+/**
+ * GeocluePositionExtCallback:
+ * @position: A #GeocluePositionExt object
+ * @fields: A #GeocluePositionExtFields bitfield representing the validity of the position values
+ * @timestamp: Time of position measurement (Unix timestamp)
+ * @latitude: Latitude in degrees
+ * @longitude: Longitude in degrees
+ * @altitude: Altitude in meters
+ * @speed: Horizontal speed (m/s)
+ * @direction: Horizontal direction in degrees
+ * @climb: Vertical speed
+ * @accuracy: Accuracy of measurement as #GeoclueAccuracy
+ * @error: Error as #Gerror or %NULL
+ * @userdata: User data pointer set in geoclue_position_velocity_get_position_velocity_async()
+ *
+ * Callback function for geoclue_position_ext_get_position_async().
+ */
+
+/**
+ * geoclue_position_ext_get_position_async:
+ * @position: A #GeocluePositionExt object
+ * @callback: A #GeocluePositionExtCallback function that should be called when return values are available
+ * @userdata: pointer for user specified data
+ *
+ * Function returns (essentially) immediately and calls @callback when current position & velocity
+ * is available or when D-Bus timeouts.
+ */
+void
+geoclue_position_ext_get_position_async (GeocluePositionExt         *position,
+                                    GeocluePositionExtCallback  callback,
+                                    gpointer                 userdata)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (position);
+       GeocluePositionExtAsyncData *data;
+
+       data = g_new (GeocluePositionExtAsyncData, 1);
+       data->position = position;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_PositionExt_get_position_async
+                       (provider->proxy,
+                        (org_freedesktop_Geoclue_PositionExt_get_position_reply)get_position_async_callback,
+                        data);
+}
diff --git a/geoclue/geoclue-position-ext.h b/geoclue/geoclue-position-ext.h
new file mode 100644 (file)
index 0000000..cfec38b
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Geoclue
+ * geoclue-position-ext.h
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_POSITION_EXT_H
+#define _GEOCLUE_POSITION_EXT_H
+
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_POSITION_EXT (geoclue_position_ext_get_type ())
+#define GEOCLUE_POSITION_EXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_POSITION_EXT, GeocluePositionExt))
+#define GEOCLUE_IS_POSITION_EXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_POSITION_EXT))
+
+#define GEOCLUE_POSITION_EXT_INTERFACE_NAME "org.freedesktop.Geoclue.PositionExt"
+
+typedef struct _GeocluePositionExt {
+       GeoclueProvider provider;
+} GeocluePositionExt;
+
+typedef struct _GeocluePositionExtClass {
+       GeoclueProviderClass provider_class;
+
+       void (* position_changed) (GeocluePositionExt      *position,
+                                  GeocluePositionExtFields fields,
+                                  int                   timestamp,
+                                  double                latitude,
+                                  double                longitude,
+                                  double                altitude,
+                                  double                speed,
+                                  double                direction,
+                                  double                climb,
+                                  GeoclueAccuracy      *accuracy);
+} GeocluePositionExtClass;
+
+GType geoclue_position_ext_get_type (void);
+
+GeocluePositionExt *geoclue_position_ext_new (const char *service,
+                                      const char *path);
+
+GeocluePositionExtFields geoclue_position_ext_get_position (GeocluePositionExt  *position,
+                                                    int              *timestamp,
+                                                    double           *latitude,
+                                                    double           *longitude,
+                                                    double           *altitude,
+                                                    double           *speed,
+                                                    double           *direction,
+                                                    double           *climb,
+                                                    GeoclueAccuracy **accuracy,
+                                                    GError          **error);
+
+GeocluePositionExtFields geoclue_position_ext_get_last_position (GeocluePositionExt  *position,
+                                                         int              *timestamp,
+                                                         double           *latitude,
+                                                         double           *longitude,
+                                                         double           *altitude,
+                                                         double           *speed,
+                                                         double           *direction,
+                                                         double           *climb,
+                                                         GeoclueAccuracy **accuracy,
+                                                         GError          **error);
+
+typedef void (*GeocluePositionExtCallback) (GeocluePositionExt      *position,
+                                        GeocluePositionExtFields fields,
+                                        int                   timestamp,
+                                        double                latitude,
+                                        double                longitude,
+                                        double                altitude,
+                                        double                speed,
+                                        double                direction,
+                                        double                climb,
+                                        GeoclueAccuracy      *accuracy,
+                                        GError               *error,
+                                        gpointer              userdata);
+
+void geoclue_position_ext_get_position_async (GeocluePositionExt         *position,
+                                         GeocluePositionExtCallback  callback,
+                                         gpointer                 userdata);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/geoclue-position.c b/geoclue/geoclue-position.c
new file mode 100644 (file)
index 0000000..b47cd4c
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Geoclue
+ * geoclue-position.c - Client API for accessing GcIfacePosition
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:geoclue-position
+ * @short_description: Geoclue position client API
+ *
+ * #GeocluePosition contains position-related methods and signals.
+ * It is part of the Geoclue public C client API which uses D-Bus
+ * to communicate with the actual provider.
+ *
+ * After a #GeocluePosition is created with geoclue_position_new() or
+ * using geoclye_master_client_create_position(), the
+ * geoclue_position_get_position() and geoclue_position_get_position_async()
+ * method and the position-changed signal can be used to obtain the current position.
+ */
+
+#include <geoclue/geoclue-position.h>
+#include <geoclue/geoclue-marshal.h>
+
+#include "gc-iface-position-bindings.h"
+
+typedef struct _GeocluePositionPrivate {
+       int dummy;
+} GeocluePositionPrivate;
+
+enum {
+       POSITION_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_POSITION, GeocluePositionPrivate))
+
+G_DEFINE_TYPE (GeocluePosition, geoclue_position, GEOCLUE_TYPE_PROVIDER);
+
+static void
+finalize (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_position_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_position_parent_class)->dispose (object);
+}
+
+static void
+position_changed (DBusGProxy      *proxy,
+                 int              fields,
+                 int              timestamp,
+                 double           latitude,
+                 double           longitude,
+                 double           altitude,
+                 GeoclueAccuracy *accuracy,
+                 GeocluePosition *position)
+{
+       g_signal_emit (position, signals[POSITION_CHANGED], 0, fields,
+                      timestamp, latitude, longitude, altitude, accuracy);
+}
+
+static GObject *
+constructor (GType                  type,
+            guint                  n_props,
+            GObjectConstructParam *props)
+{
+       GObject *object;
+       GeoclueProvider *provider;
+
+       object = G_OBJECT_CLASS (geoclue_position_parent_class)->constructor
+               (type, n_props, props);
+       provider = GEOCLUE_PROVIDER (object);
+
+       dbus_g_proxy_add_signal (provider->proxy, "PositionChanged",
+                                G_TYPE_INT, G_TYPE_INT, G_TYPE_DOUBLE,
+                                G_TYPE_DOUBLE, G_TYPE_DOUBLE,
+                                 GEOCLUE_ACCURACY_TYPE,
+                                G_TYPE_INVALID);
+       dbus_g_proxy_connect_signal (provider->proxy, "PositionChanged",
+                                    G_CALLBACK (position_changed),
+                                    object, NULL);
+
+       return object;
+}
+
+static void
+geoclue_position_class_init (GeocluePositionClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+       o_class->constructor = constructor;
+
+       g_type_class_add_private (klass, sizeof (GeocluePositionPrivate));
+
+       /**
+        * GeocluePosition::position-changed:
+        * @position: the #GeocluePosition object emitting the signal
+        * @fields: A #GeocluePositionFields bitfield representing the validity of the position values
+        * @timestamp: Time of position measurement (Unix timestamp)
+        * @latitude: Latitude in degrees
+        * @longitude: Longitude in degrees
+        * @altitude: Altitude in meters
+        * @accuracy: Accuracy of measurement as #GeoclueAccuracy
+        *
+        * The position-changed signal is emitted each time the position changes. Clients should note
+        * that not all providers support signals.
+        */
+       signals[POSITION_CHANGED] = g_signal_new ("position-changed",
+                                                 G_TYPE_FROM_CLASS (klass),
+                                                 G_SIGNAL_RUN_FIRST |
+                                                 G_SIGNAL_NO_RECURSE,
+                                                 G_STRUCT_OFFSET (GeocluePositionClass, position_changed),
+                                                 NULL, NULL,
+                                                 geoclue_marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE_BOXED,
+                                                 G_TYPE_NONE, 6,
+                                                 G_TYPE_INT, G_TYPE_INT,
+                                                 G_TYPE_DOUBLE, G_TYPE_DOUBLE,
+                                                 G_TYPE_DOUBLE, G_TYPE_POINTER);
+}
+
+static void
+geoclue_position_init (GeocluePosition *position)
+{
+}
+
+/**
+ * geoclue_position_new:
+ * @service: D-Bus service name
+ * @path: D-Bus path name
+ *
+ * Creates a #GeocluePosition with given D-Bus service name and path.
+ *
+ * Return value: Pointer to a new #GeocluePosition
+ */
+GeocluePosition *
+geoclue_position_new (const char *service,
+                     const char *path)
+{
+       return g_object_new (GEOCLUE_TYPE_POSITION,
+                            "service", service,
+                            "path", path,
+                            "interface", GEOCLUE_POSITION_INTERFACE_NAME,
+                            NULL);
+}
+
+/**
+ * geoclue_position_get_position:
+ * @position: A #GeocluePosition object
+ * @timestamp: Pointer to returned time of position measurement (Unix timestamp) or %NULL
+ * @latitude: Pointer to returned latitude in degrees or %NULL
+ * @longitude: Pointer to returned longitude in degrees or %NULL
+ * @altitude: Pointer to returned altitude in meters or %NULL
+ * @accuracy: Pointer to returned #GeoclueAccuracy or %NULL
+ * @error: Pointer to returned #Gerror or %NULL
+ *
+ * Obtains the current position. @timestamp will contain the time of
+ * the actual position measurement. @accuracy is a rough estimate of the
+ * accuracy of the current position.
+ *
+ * If the caller is not interested in some values, the pointers can be
+ * left %NULL.
+ *
+ * Return value: A #GeocluePositionFields bitfield representing the
+ * validity of the position values.
+ */
+GeocluePositionFields
+geoclue_position_get_position (GeocluePosition  *position,
+                              int              *timestamp,
+                              double           *latitude,
+                              double           *longitude,
+                              double           *altitude,
+                              GeoclueAccuracy **accuracy,
+                              GError          **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (position);
+       double la, lo, al;
+       int ts, fields;
+       GeoclueAccuracy *acc;
+       if (!org_freedesktop_Geoclue_Position_get_position (provider->proxy,
+                                                           &fields, &ts,
+                                                           &la, &lo, &al,
+                                                           &acc, error)) {
+               return GEOCLUE_POSITION_FIELDS_NONE;
+       }
+
+       if (timestamp != NULL) {
+               *timestamp = ts;
+       }
+
+       if (latitude != NULL && (fields & GEOCLUE_POSITION_FIELDS_LATITUDE)) {
+               *latitude = la;
+       }
+
+       if (longitude != NULL && (fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)) {
+               *longitude = lo;
+       }
+
+       if (altitude != NULL && (fields & GEOCLUE_POSITION_FIELDS_ALTITUDE)) {
+               *altitude = al;
+       }
+
+       if (accuracy != NULL) {
+               *accuracy = acc;
+       }
+
+       return fields;
+}
+
+/**
+ * geoclue_position_get_last_position:
+ * @position: A #GeocluePosition object
+ * @timestamp: Pointer to returned time of position measurement (Unix timestamp) or %NULL
+ * @latitude: Pointer to returned latitude in degrees or %NULL
+ * @longitude: Pointer to returned longitude in degrees or %NULL
+ * @altitude: Pointer to returned altitude in meters or %NULL
+ * @accuracy: Pointer to returned #GeoclueAccuracy or %NULL
+ * @error: Pointer to returned #Gerror or %NULL
+ *
+ * Obtains the last position. @timestamp will contain the time of
+ * the actual position measurement. @accuracy is a rough estimate of the
+ * accuracy of the last position.
+ *
+ * If the caller is not interested in some values, the pointers can be
+ * left %NULL.
+ *
+ * Return value: A #GeocluePositionFields bitfield representing the
+ * validity of the position values.
+ */
+GeocluePositionFields
+geoclue_position_get_last_position (GeocluePosition  *position,
+                                   int              *timestamp,
+                                   double           *latitude,
+                                   double           *longitude,
+                                   double           *altitude,
+                                   GeoclueAccuracy **accuracy,
+                                   GError          **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (position);
+       double la, lo, al;
+       int ts, fields;
+       GeoclueAccuracy *acc;
+       if (!org_freedesktop_Geoclue_Position_get_last_position (provider->proxy,
+                                                                &fields, &ts,
+                                                                &la, &lo, &al,
+                                                                &acc, error)) {
+               return GEOCLUE_POSITION_FIELDS_NONE;
+       }
+
+       if (timestamp != NULL) {
+               *timestamp = ts;
+       }
+
+       if (latitude != NULL && (fields & GEOCLUE_POSITION_FIELDS_LATITUDE)) {
+               *latitude = la;
+       }
+
+       if (longitude != NULL && (fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)) {
+               *longitude = lo;
+       }
+
+       if (altitude != NULL && (fields & GEOCLUE_POSITION_FIELDS_ALTITUDE)) {
+               *altitude = al;
+       }
+
+       if (accuracy != NULL) {
+               *accuracy = acc;
+       }
+
+       return fields;
+}
+
+typedef struct _GeocluePositionAsyncData {
+       GeocluePosition *position;
+       GCallback callback;
+       gpointer userdata;
+} GeocluePositionAsyncData;
+
+static void
+get_position_async_callback (DBusGProxy               *proxy,
+                            GeocluePositionFields     fields,
+                            int                       timestamp,
+                            double                    latitude,
+                            double                    longitude,
+                            double                    altitude,
+                            GeoclueAccuracy          *accuracy,
+                            GError                   *error,
+                            GeocluePositionAsyncData *data)
+{
+       (*(GeocluePositionCallback)data->callback) (data->position,
+                                                   fields,
+                                                   timestamp,
+                                                   latitude,
+                                                   longitude,
+                                                   altitude,
+                                                   accuracy,
+                                                   error,
+                                                   data->userdata);
+       g_free (data);
+}
+
+/**
+ * GeocluePositionCallback:
+ * @position: A #GeocluePosition object
+ * @fields: A #GeocluePositionFields bitfield representing the validity of the position values
+ * @timestamp: Time of position measurement (Unix timestamp)
+ * @latitude: Latitude in degrees
+ * @longitude: Longitude in degrees
+ * @altitude: Altitude in meters
+ * @accuracy: Accuracy of measurement as #GeoclueAccuracy
+ * @error: Error as #Gerror or %NULL
+ * @userdata: User data pointer set in geoclue_position_get_position_async()
+ *
+ * Callback function for geoclue_position_get_position_async().
+ */
+
+/**
+ * geoclue_position_get_position_async:
+ * @position: A #GeocluePosition object
+ * @callback: A #GeocluePositionCallback function that should be called when return values are available
+ * @userdata: pointer for user specified data
+ *
+ * Function returns (essentially) immediately and calls @callback when current position
+ * is available or when D-Bus timeouts.
+ */
+void
+geoclue_position_get_position_async (GeocluePosition         *position,
+                                    GeocluePositionCallback  callback,
+                                    gpointer                 userdata)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (position);
+       GeocluePositionAsyncData *data;
+
+       data = g_new (GeocluePositionAsyncData, 1);
+       data->position = position;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_Position_get_position_async
+                       (provider->proxy,
+                        (org_freedesktop_Geoclue_Position_get_position_reply)get_position_async_callback,
+                        data);
+}
diff --git a/geoclue/geoclue-position.h b/geoclue/geoclue-position.h
new file mode 100644 (file)
index 0000000..9332190
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Geoclue
+ * geoclue-position.h -
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_POSITION_H
+#define _GEOCLUE_POSITION_H
+
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_POSITION (geoclue_position_get_type ())
+#define GEOCLUE_POSITION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_POSITION, GeocluePosition))
+#define GEOCLUE_IS_POSITION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_POSITION))
+
+#define GEOCLUE_POSITION_INTERFACE_NAME "org.freedesktop.Geoclue.Position"
+
+typedef struct _GeocluePosition {
+       GeoclueProvider provider;
+} GeocluePosition;
+
+typedef struct _GeocluePositionClass {
+       GeoclueProviderClass provider_class;
+
+       void (* position_changed) (GeocluePosition      *position,
+                                  GeocluePositionFields fields,
+                                  int                   timestamp,
+                                  double                latitude,
+                                  double                longitude,
+                                  double                altitude,
+                                  GeoclueAccuracy      *accuracy);
+} GeocluePositionClass;
+
+GType geoclue_position_get_type (void);
+
+GeocluePosition *geoclue_position_new (const char *service,
+                                      const char *path);
+
+GeocluePositionFields geoclue_position_get_position (GeocluePosition  *position,
+                                                    int              *timestamp,
+                                                    double           *latitude,
+                                                    double           *longitude,
+                                                    double           *altitude,
+                                                    GeoclueAccuracy **accuracy,
+                                                    GError          **error);
+
+GeocluePositionFields geoclue_position_get_last_position (GeocluePosition  *position,
+                                                         int              *timestamp,
+                                                         double           *latitude,
+                                                         double           *longitude,
+                                                         double           *altitude,
+                                                         GeoclueAccuracy **accuracy,
+                                                         GError          **error);
+
+typedef void (*GeocluePositionCallback) (GeocluePosition      *position,
+                                        GeocluePositionFields fields,
+                                        int                   timestamp,
+                                        double                latitude,
+                                        double                longitude,
+                                        double                altitude,
+                                        GeoclueAccuracy      *accuracy,
+                                        GError               *error,
+                                        gpointer              userdata);
+
+void geoclue_position_get_position_async (GeocluePosition         *position,
+                                         GeocluePositionCallback  callback,
+                                         gpointer                 userdata);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/geoclue-provider.c b/geoclue/geoclue-provider.c
new file mode 100644 (file)
index 0000000..4480e2f
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+ * Geoclue
+ * geoclue-provider.c - Client object for accessing Geoclue Providers
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ *          Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *           2008 OpenedHand Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:geoclue-provider
+ * @short_description: Common client API for Geoclue providers
+ *
+ * #GeoclueProvider contains the methods and signals common to all Geoclue
+ * providers. It is part of the public C client API which uses D-Bus
+ * to communicate with the actual provider.
+ *
+ * A #GeoclueProvider is not explicitly created. Instead any provider
+ * object can be cast to #GeoclueProvider. Using a #GeocluePosition as
+ * example here:
+ * <informalexample>
+ * <programlisting>
+ * GeocluePosition *pos;
+ * char *name;
+ * GError *error;
+ *
+ * pos = geoclue_position_new ("org.freedesktop.Geoclue.Providers.Example",
+ *                             "/org/freedesktop/Geoclue/Providers/Example");
+ *
+ * if (geoclue_provider_get_provider_info (GEOCLUE_PROVIDER (pos),
+ *                                         &name, NULL, &error)) {
+ *     g_print ("name = %s", name);
+ * }
+ * </programlisting>
+ * </informalexample>
+ *
+ * #GeoclueProvider can be used to obtain  generic
+ * information about the provider and to set provider
+ * options.
+ */
+
+#include <geoclue/geoclue-provider.h>
+#include "gc-iface-geoclue-bindings.h"
+
+typedef struct _GeoclueProviderAsyncData {
+       GeoclueProvider *provider;
+       GCallback callback;
+       gpointer userdata;
+} GeoclueProviderAsyncData;
+
+typedef struct _GeoclueProviderPrivate {
+       DBusGProxy *geoclue_proxy;
+
+       char *service;
+       char *path;
+       char *interface;
+} GeoclueProviderPrivate;
+
+enum {
+       PROP_0,
+       PROP_SERVICE,
+       PROP_PATH,
+       PROP_INTERFACE
+};
+
+enum {
+       STATUS_CHANGED,
+       LAST_SIGNAL
+};
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_PROVIDER, GeoclueProviderPrivate))
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GeoclueProvider, geoclue_provider, G_TYPE_OBJECT, geoclue_types_init (););
+
+#define GEOCLUE_INTERFACE_NAME "org.freedesktop.Geoclue"
+
+
+static void
+status_changed (DBusGProxy      *proxy,
+                GeoclueStatus    status,
+                GeoclueProvider *provider)
+{
+       g_signal_emit (provider, signals[STATUS_CHANGED], 0, status);
+}
+
+static void
+add_reference_callback (DBusGProxy *proxy, GError *error, gpointer userdata)
+{
+       if (error) {
+               g_printerr ("Could not reference provider: %s\n", error->message);
+               g_error_free (error);
+       }
+}
+
+static void
+remove_reference_callback (DBusGProxy *proxy, GError *error, gpointer userdata)
+{
+       if (error) {
+               g_printerr ("Could not unreference provider: %s\n", error->message);
+               g_error_free (error);
+       }
+}
+
+static void
+finalize (GObject *object)
+{
+       GeoclueProviderPrivate *priv = GET_PRIVATE (object);
+
+       g_free (priv->service);
+       g_free (priv->path);
+       g_free (priv->interface);
+
+       G_OBJECT_CLASS (geoclue_provider_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (object);
+       GeoclueProviderPrivate *priv = GET_PRIVATE (object);
+
+       org_freedesktop_Geoclue_remove_reference_async (priv->geoclue_proxy,
+                                                       remove_reference_callback,
+                                                       NULL);
+       if (priv->geoclue_proxy) {
+               g_object_unref (priv->geoclue_proxy);
+               priv->geoclue_proxy = NULL;
+       }
+
+       if (provider->proxy) {
+               g_object_unref (provider->proxy);
+               provider->proxy = NULL;
+       }
+
+       G_OBJECT_CLASS (geoclue_provider_parent_class)->dispose (object);
+}
+
+static GObject *
+constructor (GType                  type,
+             guint                  n_props,
+             GObjectConstructParam *props)
+{
+       GObject *object;
+       GeoclueProvider *provider;
+       GeoclueProviderPrivate *priv;
+       DBusGConnection *connection;
+       GError *error = NULL;
+
+       object = G_OBJECT_CLASS (geoclue_provider_parent_class)->constructor
+               (type, n_props, props);
+       provider = GEOCLUE_PROVIDER (object);
+       priv = GET_PRIVATE (provider);
+
+       // There is a crash due to DBUS_BUS_SESSION
+    //connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+    connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+
+       if (connection == NULL) {
+               g_printerr ("Failed to open connection to bus: %s\n",
+                           error->message);
+               g_error_free (error);
+               provider->proxy = NULL;
+               priv->geoclue_proxy = NULL;
+
+               return object;
+       }
+
+       /* proxy for the requested interface */
+       provider->proxy = dbus_g_proxy_new_for_name (connection,
+                                                  priv->service, priv->path,
+                                                  priv->interface);
+
+       /* proxy for org.freedesktop.Geoclue */
+       priv->geoclue_proxy = dbus_g_proxy_new_for_name (connection,
+                                                        priv->service, priv->path,
+                                                        GEOCLUE_INTERFACE_NAME);
+       org_freedesktop_Geoclue_add_reference_async (priv->geoclue_proxy,
+                                                    add_reference_callback,
+                                                    NULL);
+       dbus_g_proxy_add_signal (priv->geoclue_proxy, "StatusChanged",
+                                G_TYPE_INT, G_TYPE_INVALID);
+       dbus_g_proxy_connect_signal (priv->geoclue_proxy, "StatusChanged",
+                                    G_CALLBACK (status_changed),
+                                    object, NULL);
+
+       return object;
+}
+
+static void
+set_property (GObject      *object,
+              guint         prop_id,
+              const GValue *value,
+              GParamSpec   *pspec)
+{
+       GeoclueProviderPrivate *priv = GET_PRIVATE (object);
+
+       switch (prop_id) {
+       case PROP_SERVICE:
+               priv->service = g_value_dup_string (value);
+               break;
+
+       case PROP_PATH:
+               priv->path = g_value_dup_string (value);
+               break;
+
+       case PROP_INTERFACE:
+               priv->interface = g_value_dup_string (value);
+               break;
+
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+get_property (GObject    *object,
+              guint       prop_id,
+              GValue     *value,
+              GParamSpec *pspec)
+{
+       switch (prop_id) {
+       default:
+               break;
+       }
+}
+
+static void
+geoclue_provider_class_init (GeoclueProviderClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+       o_class->constructor = constructor;
+       o_class->set_property = set_property;
+       o_class->get_property = get_property;
+
+       g_type_class_add_private (klass, sizeof (GeoclueProviderPrivate));
+
+       g_object_class_install_property
+               (o_class, PROP_SERVICE,
+                g_param_spec_string ("service", "Service",
+                                     "The D-Bus service this object represents",
+                                     "", G_PARAM_WRITABLE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_NICK |
+                                     G_PARAM_STATIC_BLURB |
+                                     G_PARAM_STATIC_NAME));
+       g_object_class_install_property
+               (o_class, PROP_PATH,
+                g_param_spec_string ("path", "Path",
+                                     "The D-Bus path to this provider",
+                                     "", G_PARAM_WRITABLE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_NICK |
+                                     G_PARAM_STATIC_BLURB |
+                                     G_PARAM_STATIC_NAME));
+       g_object_class_install_property
+               (o_class, PROP_INTERFACE,
+                g_param_spec_string ("interface", "Interface",
+                                     "The D-Bus interface implemented by the object",
+                                     "", G_PARAM_WRITABLE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_NICK |
+                                     G_PARAM_STATIC_BLURB |
+                                     G_PARAM_STATIC_NAME));
+
+       /**
+       * GeoclueProvider::status-changed:
+       * @provider: the provider object emitting the signal
+       * @status: New provider status as #GeoclueStatus
+       *
+       * The status-changed signal is emitted each time the provider
+       * status changes
+       **/
+       signals[STATUS_CHANGED] = g_signal_new ("status-changed",
+                                               G_TYPE_FROM_CLASS (klass),
+                                               G_SIGNAL_RUN_FIRST |
+                                               G_SIGNAL_NO_RECURSE,
+                                               G_STRUCT_OFFSET (GeoclueProviderClass, status_changed),
+                                               NULL, NULL,
+                                               g_cclosure_marshal_VOID__INT,
+                                               G_TYPE_NONE, 1, G_TYPE_INT);
+
+}
+
+static void
+geoclue_provider_init (GeoclueProvider *provider)
+{
+       GeoclueProviderPrivate *priv = GET_PRIVATE (provider);
+
+       provider->proxy = NULL;
+       priv->geoclue_proxy = NULL;
+}
+
+/**
+ * geoclue_provider_get_status:
+ * @provider: A #GeoclueProvider object
+ * @status: Pointer for returned status as #GeoclueStatus
+ * @error:  Pointer for returned #GError or %NULL
+ *
+ * Obtains the current status of the provider.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+geoclue_provider_get_status (GeoclueProvider  *provider,
+                             GeoclueStatus    *status,
+                             GError          **error)
+{
+       GeoclueProviderPrivate *priv = GET_PRIVATE (provider);
+       int i;
+
+       if (status == NULL) {
+               return TRUE;
+       }
+
+       if (!org_freedesktop_Geoclue_get_status (priv->geoclue_proxy,
+                                                &i, error)) {
+               return FALSE;
+       }
+       *status = i;
+       return TRUE;
+}
+
+static void
+get_status_async_callback (DBusGProxy               *proxy,
+                           GeoclueStatus             status,
+                           GError                   *error,
+                           GeoclueProviderAsyncData *data)
+{
+       (*(GeoclueProviderStatusCallback)data->callback) (data->provider,
+                                                         status,
+                                                         error,
+                                                         data->userdata);
+       g_free (data);
+
+}
+
+/**
+ * GeoclueProviderStatusCallback:
+ * @provider: A #GeoclueProvider object
+ * @status: A #GeoclueStatus
+ * @error: Error as #GError or %NULL
+ * @userdata: User data pointer set in geoclue_provider_get_status_async()
+ *
+ * Callback function for geoclue_provider_get_status_async().
+ */
+
+/**
+ * geoclue_provider_get_status_async:
+ * @provider: A #GeoclueProvider object
+ * @callback: A #GeoclueProviderStatusCallback function that will be called when return values are available
+ * @userdata: pointer for user specified data
+ *
+ * Asynchronous version of geoclue_provider_get_status(). Function returns
+ * (essentially) immediately and calls @callback when status is available or
+ * when there is an error.
+ */
+void
+geoclue_provider_get_status_async (GeoclueProvider               *provider,
+                                   GeoclueProviderStatusCallback  callback,
+                                   gpointer                       userdata)
+{
+       GeoclueProviderPrivate *priv = GET_PRIVATE (provider);
+       GeoclueProviderAsyncData *data;
+
+       data = g_new (GeoclueProviderAsyncData, 1);
+       data->provider = provider;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_get_status_async
+                       (priv->geoclue_proxy,
+                        (org_freedesktop_Geoclue_get_status_reply)get_status_async_callback,
+                        data);
+}
+
+
+/**
+ * geoclue_provider_set_options:
+ * @provider: A #GeoclueProvider object
+ * @options: A #GHashTable containing the options
+ * @error: Pointer for returned #GError or %NULL
+ *
+ * Sets the options on the provider.
+ *
+ * Return value: %TRUE if setting options succeeded
+ */
+gboolean
+geoclue_provider_set_options (GeoclueProvider  *provider,
+                              GHashTable       *options,
+                              GError          **error)
+{
+       GeoclueProviderPrivate *priv = GET_PRIVATE (provider);
+
+       if (options == NULL) {
+               return TRUE;
+       }
+
+       return org_freedesktop_Geoclue_set_options (priv->geoclue_proxy,
+                                                   options, error);
+}
+
+static void
+set_options_async_callback (DBusGProxy               *proxy,
+                            GError                   *error,
+                            GeoclueProviderAsyncData *data)
+{
+       (*(GeoclueProviderOptionsCallback)data->callback) (data->provider,
+                                                         error,
+                                                         data->userdata);
+       g_free (data);
+}
+
+/**
+ * GeoclueProviderOptionsCallback:
+ * @provider: A #GeoclueProvider object
+ * @error: Error as #GError or %NULL
+ * @userdata: User data pointer set in geoclue_provider_set_options_async()
+ *
+ * Callback function for geoclue_provider_set_options_async().
+ */
+
+/**
+ * geoclue_provider_set_options_async:
+ * @provider: A #GeoclueProvider object
+ * @options: A #GHashTable of options
+ * @callback: A #GeoclueProviderOptionsCallback function that will be called when options are set
+ * @userdata: pointer for user specified data
+ *
+ * Asynchronous version of geoclue_provider_set_options(). Function returns
+ * (essentially) immediately and calls @callback when options have been set or
+ * when there is an error.
+ */
+void
+geoclue_provider_set_options_async (GeoclueProvider                *provider,
+                                    GHashTable                     *options,
+                                    GeoclueProviderOptionsCallback  callback,
+                                    gpointer                        userdata)
+{
+       GeoclueProviderPrivate *priv = GET_PRIVATE (provider);
+       GeoclueProviderAsyncData *data;
+
+       data = g_new (GeoclueProviderAsyncData, 1);
+       data->provider = provider;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_set_options_async
+                       (priv->geoclue_proxy,
+                        options,
+                        (org_freedesktop_Geoclue_set_options_reply)set_options_async_callback,
+                        data);
+}
+
+/**
+ * geoclue_provider_get_provider_info:
+ * @provider: A #GeoclueProvider object
+ * @name: Pointer for returned provider name or %NULL
+ * @description: Pointer for returned provider description or %NULL
+ * @error:  Pointer for returned #GError or %NULL
+ *
+ * Obtains name and a short description of the provider.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+geoclue_provider_get_provider_info (GeoclueProvider  *provider,
+                                    char            **name,
+                                    char            **description,
+                                    GError          **error)
+{
+       GeoclueProviderPrivate *priv = GET_PRIVATE (provider);
+
+       return org_freedesktop_Geoclue_get_provider_info (priv->geoclue_proxy,
+                                                         name, description,
+                                                         error);
+}
+
+static void
+get_provider_info_async_callback (DBusGProxy               *proxy,
+                                  char                     *name,
+                                  char                     *description,
+                                  GError                   *error,
+                                  GeoclueProviderAsyncData *data)
+{
+       (*(GeoclueProviderInfoCallback)data->callback) (data->provider,
+                                                       name,
+                                                       description,
+                                                       error,
+                                                       data->userdata);
+       g_free (data);
+}
+
+/**
+ * GeoclueProviderInfoCallback:
+ * @provider: A #GeoclueProvider object
+ * @name: Name of the provider
+ * @description: one-line description of the provider
+ * @error: Error as #GError or %NULL
+ * @userdata: User data pointer set in geoclue_provider_get_provider_info_async()
+ *
+ * Callback function for geoclue_provider_get_provider_info_async().
+ */
+
+/**
+ * geoclue_provider_get_provider_info_async:
+ * @provider: A #GeoclueProvider object
+ * @callback: A #GeoclueProviderInfoCallback function that will be called when info is available
+ * @userdata: pointer for user specified data
+ *
+ * Asynchronous version of geoclue_provider_get_provider_info(). Function returns
+ * (essentially) immediately and calls @callback when info is available or
+ * when there is an error.
+ */
+void
+geoclue_provider_get_provider_info_async (GeoclueProvider             *provider,
+                                          GeoclueProviderInfoCallback  callback,
+                                          gpointer                     userdata)
+{
+       GeoclueProviderPrivate *priv = GET_PRIVATE (provider);
+       GeoclueProviderAsyncData *data;
+
+       data = g_new (GeoclueProviderAsyncData, 1);
+       data->provider = provider;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_get_provider_info_async
+                       (priv->geoclue_proxy,
+                        (org_freedesktop_Geoclue_get_provider_info_reply)get_provider_info_async_callback,
+                        data);
+}
diff --git a/geoclue/geoclue-provider.h b/geoclue/geoclue-provider.h
new file mode 100644 (file)
index 0000000..65b7906
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Geoclue
+ * geoclue-provider.h - Client object for accessing Geoclue Providers
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ *          Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *           2008 OpenedHand Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_PROVIDER_H
+#define _GEOCLUE_PROVIDER_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+#include <geoclue/geoclue-types.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_PROVIDER (geoclue_provider_get_type ())
+#define GEOCLUE_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_PROVIDER, GeoclueProvider))
+#define GEOCLUE_IS_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_PROVIDER))
+
+typedef struct _GeoclueProvider {
+       GObject object;
+
+       DBusGProxy *proxy;
+} GeoclueProvider;
+
+typedef struct _GeoclueProviderClass {
+       GObjectClass object_class;
+
+       void (*status_changed) (GeoclueProvider *provider,
+                               GeoclueStatus    status);
+} GeoclueProviderClass;
+
+GType geoclue_provider_get_type (void);
+
+gboolean geoclue_provider_get_status (GeoclueProvider  *provider,
+                                      GeoclueStatus    *status,
+                                      GError          **error);
+typedef void (*GeoclueProviderStatusCallback) (GeoclueProvider *provider,
+                                               GeoclueStatus    status,
+                                               GError          *error,
+                                               gpointer         userdata);
+void geoclue_provider_get_status_async (GeoclueProvider               *provider,
+                                        GeoclueProviderStatusCallback  callback,
+                                        gpointer                       userdata);
+
+gboolean geoclue_provider_get_provider_info (GeoclueProvider  *provider,
+                                             char            **name,
+                                             char            **description,
+                                             GError          **error);
+typedef void (*GeoclueProviderInfoCallback) (GeoclueProvider *provider,
+                                             char            *name,
+                                             char            *description,
+                                             GError          *error,
+                                             gpointer         userdata);
+void geoclue_provider_get_provider_info_async (GeoclueProvider             *provider,
+                                               GeoclueProviderInfoCallback  callback,
+                                               gpointer                     userdata);
+
+gboolean geoclue_provider_set_options (GeoclueProvider  *provider,
+                                       GHashTable       *options,
+                                       GError          **error);
+typedef void (*GeoclueProviderOptionsCallback) (GeoclueProvider *provider,
+                                                GError          *error,
+                                                gpointer         userdata);
+void geoclue_provider_set_options_async (GeoclueProvider                *provider,
+                                         GHashTable                     *options,
+                                         GeoclueProviderOptionsCallback  callback,
+                                         gpointer                        userdata);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/geoclue-reverse-geocode.c b/geoclue/geoclue-reverse-geocode.c
new file mode 100644 (file)
index 0000000..345859a
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Geoclue
+ * geoclue-reverse-geocode.c - Client API for accessing GcIfaceReverseGeocode
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:geoclue-reverse-geocode
+ * @short_description: Geoclue reverse geocode client API
+ *
+ * #GeoclueReverseGeocode contains reverse geocoding methods.
+ * It is part of the Geoclue public C client API which uses D-Bus
+ * to communicate with the actual provider.
+ *
+ * After a #GeoclueReverseGeocode is created with
+ * geoclue_reverse_geocode_new(), the
+ * geoclue_reverse_geocode_position_to_address() and
+ * geoclue_reverse_geocode_position_to_address_async() method can be used to
+ * obtain the address of a known position.
+ */
+
+#include <geoclue/geoclue-reverse-geocode.h>
+#include <geoclue/geoclue-marshal.h>
+
+#include "gc-iface-reverse-geocode-bindings.h"
+
+typedef struct _GeoclueReverseGeocodePrivate {
+       int dummy;
+} GeoclueReverseGeocodePrivate;
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_REVERSE_GEOCODE, GeoclueReverseGeocodePrivate))
+
+G_DEFINE_TYPE (GeoclueReverseGeocode, geoclue_reverse_geocode, GEOCLUE_TYPE_PROVIDER);
+
+static void
+finalize (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_reverse_geocode_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_reverse_geocode_parent_class)->dispose (object);
+}
+
+static void
+geoclue_reverse_geocode_class_init (GeoclueReverseGeocodeClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+
+       g_type_class_add_private (klass, sizeof (GeoclueReverseGeocodePrivate));
+}
+
+static void
+geoclue_reverse_geocode_init (GeoclueReverseGeocode *geocode)
+{
+}
+
+/**
+ * geoclue_reverse_geocode_new:
+ * @service: D-Bus service name
+ * @path: D-Bus path name
+ *
+ * Creates a #GeoclueReverseGeocode with given D-Bus service name and path.
+ *
+ * Return value: Pointer to a new #GeoclueReverseGeocode
+ */
+GeoclueReverseGeocode *
+geoclue_reverse_geocode_new (const char *service,
+                            const char *path)
+{
+       return g_object_new (GEOCLUE_TYPE_REVERSE_GEOCODE,
+                            "service", service,
+                            "path", path,
+                            "interface", GEOCLUE_REVERSE_GEOCODE_INTERFACE_NAME,
+                            NULL);
+}
+
+/**
+ * geoclue_reverse_geocode_position_to_address:
+ * @geocode: A #GeoclueReverseGeocode object
+ * @latitude: latitude in degrees
+ * @longitude: longitude in degrees
+ * @position_accuracy: Accuracy of the given latitude and longitude
+ * @details: Pointer to returned #GHashTable with address details or %NULL
+ * @address_accuracy: Pointer to accuracy of the returned address or %NULL
+ * @error: Pointer to returned #Gerror or %NULL
+ *
+ * Obtains an address for the position defined by @latitude and @longitude.
+ * @details is a #GHashTable with the returned address data, see
+ * <ulink url="geoclue-types.html">geoclue-types.h</ulink> for the hashtable keys.
+ *
+ * If the caller is not interested in some values, the pointers can be
+ * left %NULL. If accuracy of the position is not known, an accuracy with
+ * GeoclueAccuracyLevel GEOCLUE_ACCURACY_DETAILED should be used.
+ *
+ * Return value: %TRUE if there is no @error
+ */
+gboolean
+geoclue_reverse_geocode_position_to_address (GeoclueReverseGeocode   *geocode,
+                                            double                   latitude,
+                                            double                   longitude,
+                                            GeoclueAccuracy         *position_accuracy,
+                                            GHashTable             **details,
+                                            GeoclueAccuracy        **address_accuracy,
+                                            GError                 **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (geocode);
+
+       return org_freedesktop_Geoclue_ReverseGeocode_position_to_address
+               (provider->proxy, latitude, longitude, position_accuracy,
+                details, address_accuracy, error);
+}
+
+
+typedef struct _GeoclueRevGeocodeAsyncData {
+       GeoclueReverseGeocode *revgeocode;
+       GCallback callback;
+       gpointer userdata;
+} GeoclueRevGeocodeAsyncData;
+
+static void
+position_to_address_callback (DBusGProxy                 *proxy,
+                             GHashTable                 *details,
+                             GeoclueAccuracy            *accuracy,
+                             GError                     *error,
+                             GeoclueRevGeocodeAsyncData *data)
+{
+       (*(GeoclueReverseGeocodeCallback)data->callback) (data->revgeocode,
+                                                         details,
+                                                         accuracy,
+                                                         error,
+                                                         data->userdata);
+       g_free (data);
+}
+
+/**
+ * GeoclueReverseGeocodeCallback:
+ * @revgeocode: A #GeoclueReverseGeocode object
+ * @details: Address details as #GHashTable.
+ * @accuracy: Accuracy of measurement as #GeoclueAccuracy
+ * @error: Error as #Gerror (may be %NULL)
+ * @userdata: User data pointer set in geoclue_reverse_geocode_position_to_address_async()
+ *
+ * Callback function for geoclue_reverse_geocode_position_to_address_async().
+ *
+ * see <ulink url="geoclue-types.html">geoclue-types.h</ulink> for the
+ * hashtable keys used in @details.
+ */
+
+/**
+ * geoclue_reverse_geocode_position_to_address_async:
+ * @geocode: A #GeoclueReverseGeocode object
+ * @latitude: Latitude in degrees
+ * @longitude: Longitude in degrees
+ * @accuracy: Accuracy of the given position as #GeoclueAccuracy
+ * @callback: A #GeoclueAddressCallback function that should be called when return values are available
+ * @userdata: pointer for user specified data
+ *
+ * Function returns (essentially) immediately and calls @callback when the reverse-geocoded
+ * address data is available or when D-Bus timeouts.
+ */
+void
+geoclue_reverse_geocode_position_to_address_async (GeoclueReverseGeocode        *revgeocode,
+                                                  double                        latitude,
+                                                  double                        longitude,
+                                                  GeoclueAccuracy              *accuracy,
+                                                  GeoclueReverseGeocodeCallback callback,
+                                                  gpointer                      userdata)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (revgeocode);
+       GeoclueRevGeocodeAsyncData *data;
+
+       data = g_new (GeoclueRevGeocodeAsyncData, 1);
+       data->revgeocode = revgeocode;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_ReverseGeocode_position_to_address_async
+                       (provider->proxy,
+                        latitude,
+                        longitude,
+                        accuracy,
+                        (org_freedesktop_Geoclue_ReverseGeocode_position_to_address_reply)position_to_address_callback,
+                        data);
+}
diff --git a/geoclue/geoclue-reverse-geocode.h b/geoclue/geoclue-reverse-geocode.h
new file mode 100644 (file)
index 0000000..cee34ec
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Geoclue
+ * geoclue-reverse-geocode.h -
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_REVERSE_GEOCODE_H
+#define _GEOCLUE_REVERSE_GEOCODE_H
+
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-accuracy.h>
+#include <geoclue/geoclue-types.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_REVERSE_GEOCODE (geoclue_reverse_geocode_get_type ())
+#define GEOCLUE_REVERSE_GEOCODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_REVERSE_GEOCODE, GeoclueReverseGeocode))
+#define GEOCLUE_IS_REVERSE_GEOCODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_GEOCODE_REVERSE))
+
+#define GEOCLUE_REVERSE_GEOCODE_INTERFACE_NAME "org.freedesktop.Geoclue.ReverseGeocode"
+
+typedef struct _GeoclueReverseGeocode {
+       GeoclueProvider provider;
+} GeoclueReverseGeocode;
+
+typedef struct _GeoclueReverseGeocodeClass {
+       GeoclueProviderClass provider_class;
+} GeoclueReverseGeocodeClass;
+
+GType geoclue_reverse_geocode_get_type (void);
+
+GeoclueReverseGeocode *geoclue_reverse_geocode_new (const char *service,
+                                                   const char *path);
+
+gboolean
+geoclue_reverse_geocode_position_to_address (GeoclueReverseGeocode   *revgeocode,
+                                            double                   latitude,
+                                            double                   longitude,
+                                            GeoclueAccuracy         *position_accuracy,
+                                            GHashTable             **details,
+                                            GeoclueAccuracy        **address_accuracy,
+                                            GError                 **error);
+
+typedef void (*GeoclueReverseGeocodeCallback) (GeoclueReverseGeocode *revgeocode,
+                                              GHashTable            *details,
+                                              GeoclueAccuracy       *accuracy,
+                                              GError                *error,
+                                              gpointer               userdata);
+
+void geoclue_reverse_geocode_position_to_address_async (GeoclueReverseGeocode        *revgeocode,
+                                                       double                        latitude,
+                                                       double                        longitude,
+                                                       GeoclueAccuracy              *accuracy,
+                                                       GeoclueReverseGeocodeCallback callback,
+                                                       gpointer                      userdata);
+
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/geoclue-satellite-info.h b/geoclue/geoclue-satellite-info.h
new file mode 100644 (file)
index 0000000..99818a3
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Geoclue
+ * gc-iface-satellite.c - GInterface for org.freedesktop.Geoclue.Satellite
+ *
+ * Author: Sagnho Park <sangho.g.park@samsung.com>, Youngae Kang <youngae.kang@samsung.com>,
+ *         Yunhan Kim <yhan.kim@samsung.com>, Genie Kim <daejins.kim@samsung.com>
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_SATELLITE_INFO_H
+#define _GEOCLUE_SATELLITE_INFO_H
+
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-types.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_SATELLITE_INFO (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID))
+#define GEOCLUE_SATELLITE_INFO_ARRAY (dbus_g_type_get_collection ("GPtrArray", GEOCLUE_SATELLITE_INFO))
+
+G_END_DECLS
+
+#endif
+
diff --git a/geoclue/geoclue-satellite.c b/geoclue/geoclue-satellite.c
new file mode 100644 (file)
index 0000000..c9f0cc7
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Geoclue
+ * geoclue-satellite.c - Client API for accessing GcIfaceSatellite
+ *
+ * Author: Sagnho Park <sangho.g.park@samsung.com>, Youngae Kang <youngae.kang@samsung.com>,
+ *         Yunhan Kim <yhan.kim@samsung.com>, Genie Kim <daejins.kim@samsung.com>
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <geoclue/geoclue-satellite.h>
+#include <geoclue/geoclue-marshal.h>
+
+#include "gc-iface-satellite-bindings.h"
+
+typedef struct _GeoclueSatellitePrivate {
+       int dummy;
+} GeoclueSatellitePrivate;
+
+enum {
+       SATELLITE_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_SATELLITE, GeoclueSatellitePrivate))
+
+G_DEFINE_TYPE (GeoclueSatellite, geoclue_satellite, GEOCLUE_TYPE_PROVIDER);
+
+static void
+finalize (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_satellite_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_satellite_parent_class)->dispose (object);
+}
+
+static void
+satellite_changed (DBusGProxy       *proxy,
+                  int               timestamp,
+                  int               satellite_used,
+                  int               satellite_visible,
+                  GArray           *used_prn,
+                  GPtrArray        *sat_info,
+                  GeoclueSatellite *satellite)
+{
+       g_signal_emit (satellite, signals[SATELLITE_CHANGED], 0, timestamp, satellite_used, satellite_visible,
+                      used_prn,sat_info);
+}
+
+static GObject *
+constructor (GType                  type,
+            guint                  n_props,
+            GObjectConstructParam *props)
+{
+       GObject *object;
+       GeoclueProvider *provider;
+
+       object = G_OBJECT_CLASS (geoclue_satellite_parent_class)->constructor (type, n_props, props);
+       provider = GEOCLUE_PROVIDER (object);
+
+       dbus_g_proxy_add_signal (provider->proxy, "SatelliteChanged",
+                                G_TYPE_INT,
+                                G_TYPE_INT,
+                                G_TYPE_INT,
+                                DBUS_TYPE_G_INT_ARRAY,
+                                GEOCLUE_SATELLITE_INFO_ARRAY,
+                                G_TYPE_INVALID);
+       dbus_g_proxy_connect_signal (provider->proxy, "SatelliteChanged",
+                                    G_CALLBACK (satellite_changed),
+                                    object, NULL);
+
+       return object;
+}
+
+static void
+geoclue_satellite_class_init (GeoclueSatelliteClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+       o_class->constructor = constructor;
+
+       g_type_class_add_private (klass, sizeof (GeoclueSatellitePrivate));
+
+       signals[SATELLITE_CHANGED] = g_signal_new ("satellite-changed",
+                                                  G_TYPE_FROM_CLASS (klass),
+                                                  G_SIGNAL_RUN_FIRST |
+                                                  G_SIGNAL_NO_RECURSE,
+                                                  G_STRUCT_OFFSET (GeoclueSatelliteClass, satellite_changed),
+                                                  NULL, NULL,
+                                                  geoclue_marshal_VOID__INT_INT_INT_POINTER_POINTER,
+                                                  G_TYPE_NONE, 5,
+                                                  G_TYPE_INT, G_TYPE_INT, G_TYPE_INT,
+                                                  G_TYPE_POINTER, G_TYPE_POINTER);
+}
+
+static void
+geoclue_satellite_init (GeoclueSatellite *satellite)
+{
+}
+
+GeoclueSatellite *
+geoclue_satellite_new (const char *service,
+                      const char *path)
+{
+       return g_object_new (GEOCLUE_TYPE_SATELLITE,
+                            "service", service,
+                            "path", path,
+                            "interface", GEOCLUE_SATELLITE_INTERFACE_NAME,
+                            NULL);
+}
+
+gboolean
+geoclue_satellite_get_satellite (GeoclueSatellite *satellite,
+                                int              *timestamp,
+                                int              *satellite_used,
+                                int              *satellite_visible,
+                                GArray          **used_prn,
+                                GPtrArray       **sat_info,
+                                GError          **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (satellite);
+       if (!org_freedesktop_Geoclue_Satellite_get_satellite (provider->proxy,
+                                                             timestamp, satellite_used, satellite_visible,
+                                                             used_prn, sat_info, error)) {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+gboolean
+geoclue_satellite_get_last_satellite (GeoclueSatellite *satellite,
+                                     int              *timestamp,
+                                     int              *satellite_used,
+                                     int              *satellite_visible,
+                                     GArray          **used_prn,
+                                     GPtrArray       **sat_info,
+                                     GError          **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (satellite);
+       if (!org_freedesktop_Geoclue_Satellite_get_last_satellite (provider->proxy,
+                                                                  timestamp, satellite_used, satellite_visible,
+                                                                  used_prn, sat_info, error)) {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+typedef struct _GeoclueSatelliteAsyncData {
+       GeoclueSatellite *satellite;
+       GCallback         callback;
+       gpointer          userdata;
+} GeoclueSatelliteAsyncData;
+
+static void
+get_satellite_async_callback (DBusGProxy                *proxy,
+                             int                        timestamp,
+                             int                        satellite_used,
+                             int                        satellite_visible,
+                             GArray                    *used_prn,
+                             GPtrArray                 *sat_info,
+                             GError                    *error,
+                             GeoclueSatelliteAsyncData *data)
+{
+       (*(GeoclueSatelliteCallback)data->callback) (data->satellite,
+                                                    timestamp,
+                                                    satellite_used,
+                                                    satellite_visible,
+                                                    used_prn,
+                                                    sat_info,
+                                                    error,
+                                                    data->userdata);
+
+       g_free (data);
+}
+
+void
+geoclue_satellite_get_satellite_async (GeoclueSatellite        *satellite,
+                                      GeoclueSatelliteCallback callback,
+                                      gpointer                 userdata)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (satellite);
+       GeoclueSatelliteAsyncData *data;
+
+       data = g_new (GeoclueSatelliteAsyncData, 1);
+       data->satellite = satellite;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_Satellite_get_satellite_async (provider->proxy,
+                       (org_freedesktop_Geoclue_Satellite_get_satellite_reply)get_satellite_async_callback,
+                       data);
+}
diff --git a/geoclue/geoclue-satellite.h b/geoclue/geoclue-satellite.h
new file mode 100644 (file)
index 0000000..a548315
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Geoclue
+ * geoclue-satellite.h -
+ *
+ * Author: Sagnho Park <sangho.g.park@samsung.com>, Youngae Kang <youngae.kang@samsung.com>,
+ *         Yunhan Kim <yhan.kim@samsung.com>, Genie Kim <daejins.kim@samsung.com>
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_SATELLITE_H
+#define _GEOCLUE_SATELLITE_H
+
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-satellite-info.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_SATELLITE (geoclue_satellite_get_type ())
+#define GEOCLUE_SATELLITE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_SATELLITE, GeoclueSatellite))
+#define GEOCLUE_IS_SATELLITE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_SATELLITE))
+
+#define GEOCLUE_SATELLITE_INTERFACE_NAME "org.freedesktop.Geoclue.Satellite"
+
+typedef struct _GeoclueSatellite {
+       GeoclueProvider provider;
+} GeoclueSatellite;
+
+typedef struct _GeoclueSatelliteClass {
+       GeoclueProviderClass provider_class;
+
+       void (* satellite_changed) (GeoclueSatellite *satellite,
+                                   int               timestamp,
+                                   int               satellite_used,
+                                   int               satellite_visible,
+                                   GArray           *used_prn,
+                                   GPtrArray        *sat_info);
+} GeoclueSatelliteClass;
+
+GType geoclue_satellite_get_type (void);
+
+GeoclueSatellite *geoclue_satellite_new (const char *service,
+                                        const char *path);
+
+gboolean geoclue_satellite_get_satellite (GeoclueSatellite *satellite,
+                                         int              *timestamp,
+                                         int              *satellite_used,
+                                         int              *satellite_visible,
+                                         GArray          **used_prn,
+                                         GPtrArray       **sat_info,
+                                         GError          **error);
+
+gboolean geoclue_satellite_get_last_satellite (GeoclueSatellite *satellite,
+                                              int              *timestamp,
+                                              int              *satellite_used,
+                                              int              *satellite_visible,
+                                              GArray          **used_prn,
+                                              GPtrArray       **sat_info,
+                                              GError          **error);
+
+typedef void (*GeoclueSatelliteCallback) (GeoclueSatellite *satellite,
+                                         int               timestamp,
+                                         int               satellite_used,
+                                         int               satellite_visible,
+                                         GArray           *used_prn,
+                                         GPtrArray        *sat_info,
+                                         GError           *error,
+                                         gpointer          userdata);
+
+void geoclue_satellite_get_satellite_async (GeoclueSatellite        *satellite,
+                                           GeoclueSatelliteCallback callback,
+                                           gpointer                 userdata);
+
+G_END_DECLS
+
+#endif
diff --git a/geoclue/geoclue-types.c b/geoclue/geoclue-types.c
new file mode 100644 (file)
index 0000000..2bfc549
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Geoclue
+ * geoclue-types.c -
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <geoclue/geoclue-marshal.h>
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+#include <geoclue/geoclue-satellite.h>
+#include <geoclue/geoclue-error.h>
+
+void
+geoclue_types_init (void)
+{
+       dbus_g_object_register_marshaller (geoclue_marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE,
+                                          G_TYPE_NONE,
+                                          G_TYPE_INT,
+                                          G_TYPE_INT,
+                                          G_TYPE_DOUBLE,
+                                          G_TYPE_DOUBLE,
+                                          G_TYPE_DOUBLE,
+                                          G_TYPE_INVALID);
+
+       dbus_g_object_register_marshaller (geoclue_marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE_BOXED,
+                                           G_TYPE_NONE,
+                                           G_TYPE_INT,
+                                          G_TYPE_INT,
+                                          G_TYPE_DOUBLE,
+                                          G_TYPE_DOUBLE,
+                                          G_TYPE_DOUBLE,
+                                           G_TYPE_BOXED,
+                                          G_TYPE_INVALID);
+
+       dbus_g_object_register_marshaller (geoclue_marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE_DOUBLE_DOUBLE_DOUBLE_BOXED,
+                                           G_TYPE_NONE,
+                                           G_TYPE_INT,
+                                          G_TYPE_INT,
+                                          G_TYPE_DOUBLE,
+                                          G_TYPE_DOUBLE,
+                                          G_TYPE_DOUBLE,
+                                          G_TYPE_DOUBLE,
+                                          G_TYPE_DOUBLE,
+                                          G_TYPE_DOUBLE,
+                                           G_TYPE_BOXED,
+                                          G_TYPE_INVALID);
+
+       dbus_g_object_register_marshaller (geoclue_marshal_VOID__INT_BOXED_BOXED,
+                                          G_TYPE_NONE,
+                                          G_TYPE_INT,
+                                          G_TYPE_BOXED,
+                                          G_TYPE_BOXED,
+                                          G_TYPE_INVALID);
+
+       dbus_g_object_register_marshaller (geoclue_marshal_VOID__STRING_STRING_STRING_STRING,
+                                          G_TYPE_NONE,
+                                          G_TYPE_STRING,
+                                          G_TYPE_STRING,
+                                          G_TYPE_STRING,
+                                          G_TYPE_STRING,
+                                          G_TYPE_INVALID);
+
+       dbus_g_object_register_marshaller (geoclue_marshal_VOID__INT_STRING,
+                                          G_TYPE_NONE,
+                                          G_TYPE_INT,
+                                          G_TYPE_STRING,
+                                          G_TYPE_INVALID);
+
+       dbus_g_object_register_marshaller (geoclue_marshal_VOID__INT_INT_INT_POINTER_POINTER,
+                                          G_TYPE_NONE,
+                                          G_TYPE_INT,
+                                          G_TYPE_INT,
+                                          G_TYPE_INT,
+                                          DBUS_TYPE_G_INT_ARRAY,
+                                          GEOCLUE_SATELLITE_INFO_ARRAY,
+                                          G_TYPE_INVALID);
+
+       dbus_g_error_domain_register (GEOCLUE_ERROR,
+                                     GEOCLUE_ERROR_DBUS_INTERFACE,
+                                     GEOCLUE_TYPE_ERROR);
+
+
+}
diff --git a/geoclue/geoclue-types.h b/geoclue/geoclue-types.h
new file mode 100644 (file)
index 0000000..73a2281
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ * Geoclue
+ * geoclue-types.h - Types for Geoclue
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_TYPES_H
+#define _GEOCLUE_TYPES_H
+
+#include <geoclue/geoclue-error.h>
+
+/**
+ * SECTION:geoclue-types
+ * @short_description: Type definitions and defines useful for Geoclue clients
+ **/
+
+
+/**
+ * GeoclueStatus
+ *
+ * defines the provider status
+ **/
+typedef enum {
+       GEOCLUE_STATUS_ERROR,
+       GEOCLUE_STATUS_UNAVAILABLE,
+       GEOCLUE_STATUS_ACQUIRING,
+       GEOCLUE_STATUS_AVAILABLE
+} GeoclueStatus;
+
+/**
+ * GeoclueAccuracyLevel:
+ *
+ * Enum values used to define the approximate accuracy of
+ * Position or Address information.
+ **/
+typedef enum {
+       GEOCLUE_ACCURACY_LEVEL_NONE = 0,
+       GEOCLUE_ACCURACY_LEVEL_COUNTRY,
+       GEOCLUE_ACCURACY_LEVEL_REGION,
+       GEOCLUE_ACCURACY_LEVEL_LOCALITY,
+       GEOCLUE_ACCURACY_LEVEL_POSTALCODE,
+       GEOCLUE_ACCURACY_LEVEL_STREET,
+       GEOCLUE_ACCURACY_LEVEL_DETAILED,
+} GeoclueAccuracyLevel;
+
+/**
+ * GeocluePositionFields:
+ *
+ * #GeocluePositionFields is a bitfield that defines the validity of
+ * Position values.
+ *
+ * Example:
+ * <informalexample>
+ * <programlisting>
+ * GeocluePositionFields fields;
+ * fields = geoclue_position_get_position (. . .);
+ *
+ * if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
+ *     fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) {
+ *     g_print("latitude and longitude are valid");
+ * }
+ * </programlisting>
+ * </informalexample>
+ **/
+typedef enum {
+       GEOCLUE_POSITION_FIELDS_NONE = 0,
+       GEOCLUE_POSITION_FIELDS_LATITUDE = 1 << 0,
+       GEOCLUE_POSITION_FIELDS_LONGITUDE = 1 << 1,
+       GEOCLUE_POSITION_FIELDS_ALTITUDE = 1 << 2
+} GeocluePositionFields;
+
+/**
+ * GeoclueVelocityFields:
+ *
+ * GeoclueVelocityFields is a bitfield that defines the validity of
+ * Velocity values.
+ **/
+typedef enum {
+       GEOCLUE_VELOCITY_FIELDS_NONE = 0,
+       GEOCLUE_VELOCITY_FIELDS_SPEED = 1 << 0,
+       GEOCLUE_VELOCITY_FIELDS_DIRECTION = 1 << 1,
+       GEOCLUE_VELOCITY_FIELDS_CLIMB = 1 << 2
+} GeoclueVelocityFields;
+
+/**
+ * GeocluePositionExtFields:
+ *
+ * GeocluePositionExtFields is a bitfield that defines the validity of
+ * Position & Velocity values.
+ **/
+typedef enum {
+       GEOCLUE_POSITION_EXT_FIELDS_NONE = 0,
+       GEOCLUE_POSITION_EXT_FIELDS_LATITUDE = 1 << 0,
+       GEOCLUE_POSITION_EXT_FIELDS_LONGITUDE = 1 << 1,
+       GEOCLUE_POSITION_EXT_FIELDS_ALTITUDE = 1 << 2,
+       GEOCLUE_POSITION_EXT_FIELDS_SPEED = 1 << 3,
+       GEOCLUE_POSITION_EXT_FIELDS_DIRECTION = 1 << 4,
+       GEOCLUE_POSITION_EXT_FIELDS_CLIMB = 1 << 5
+} GeocluePositionExtFields;
+
+/**
+ * GEOCLUE_ADDRESS_KEY_COUNTRYCODE:
+ *
+ * A key for address hashtables. The hash value should be a ISO 3166 two
+ * letter country code.
+ *
+ * The used hash keys match the elements of XEP-0080 (XMPP protocol
+ * extension for user location), see
+ * <ulink url="http://www.xmpp.org/extensions/xep-0080.html">
+ * http://www.xmpp.org/extensions/xep-0080.html</ulink>
+ */
+#define GEOCLUE_ADDRESS_KEY_COUNTRYCODE "countrycode"
+/**
+ * GEOCLUE_ADDRESS_KEY_COUNTRY:
+ *
+ * A key for address hashtables. The hash value should be a name of a country.
+ */
+#define GEOCLUE_ADDRESS_KEY_COUNTRY "country"
+/**
+ * GEOCLUE_ADDRESS_KEY_REGION:
+ *
+ * A key for address hashtables. The hash value should be a name of an
+ * administrative region of a nation, e.g. province or
+ * US state.
+ */
+#define GEOCLUE_ADDRESS_KEY_REGION "region"
+/**
+ * GEOCLUE_ADDRESS_KEY_LOCALITY:
+ *
+ * A key for address hashtables. The hash value should be a name of a town
+ * or city.
+ */
+#define GEOCLUE_ADDRESS_KEY_LOCALITY "locality"
+/**
+ * GEOCLUE_ADDRESS_KEY_AREA:
+ *
+ * A key for address hashtables. The hash value should be a name of an
+ * area, such as neighborhood or campus.
+ */
+#define GEOCLUE_ADDRESS_KEY_AREA "area"
+/**
+ * GEOCLUE_ADDRESS_KEY_POSTALCODE:
+ *
+ * A key for address hashtables. The hash value should be a code used for
+ * postal delivery.
+ */
+#define GEOCLUE_ADDRESS_KEY_POSTALCODE "postalcode"
+/**
+ * GEOCLUE_ADDRESS_KEY_STREET:
+ *
+ * A key for address hashtables. The hash value should be a partial or full street
+ * address.
+ */
+#define GEOCLUE_ADDRESS_KEY_STREET "street"
+
+/**
+ * GEOCLUE_LANDMARK_KEY_COUNTRYCODE:
+ *
+ * A key for landmark hashtables. The hash value should be a ISO 3166 two
+ * letter country code.
+ *
+ * The used hash keys match the elements of XEP-0080 (XMPP protocol
+ * extension for user location), see
+ * <ulink url="http://www.xmpp.org/extensions/xep-0080.html">
+ * http://www.xmpp.org/extensions/xep-0080.html</ulink>
+ */
+#define GEOCLUE_LANDMARK_KEY_COUNTRYCODE GEOCLUE_ADDRESS_KEY_COUNTRYCODE
+/**
+ * GEOCLUE_LANDMARK_KEY_ID:
+ *
+ * A key for landmark hashtables. The hash value should be an id of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_ID "id"
+/**
+ * GEOCLUE_LANDMARK_KEY_RANK:
+ *
+ * A key for landmark hashtables. The hash value should be a rank of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_RANK "rank"
+/**
+ * GEOCLUE_LANDMARK_KEY_LAT:
+ *
+ * A key for landmark hashtables. The hash value should be a latitude of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_LAT "lat"
+/**
+ * GEOCLUE_LANDMARK_KEY_LON:
+ *
+ * A key for landmark hashtables. The hash value should be a longitude of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_LON "lon"
+/**
+ * GEOCLUE_LANDMARK_KEY_BOUNDINGBOX:
+ *
+ * A key for landmark hashtables. The hash value should be a bounding box of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_BOUNDINGBOX "boundingbox"
+/**
+ * GEOCLUE_LANDMARK_KEY_NAME:
+ *
+ * A key for landmark hashtables. The hash value should be a display name of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_NAME "display_name"
+/**
+ * GEOCLUE_LANDMARK_KEY_HOUSE:
+ *
+ * A key for landmark hashtables. The hash value should be a house of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_HOUSE "house"
+/**
+ * GEOCLUE_LANDMARK_KEY_ROAD:
+ *
+ * A key for landmark hashtables. The hash value should be a road of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_ROAD "road"
+/**
+ * GEOCLUE_LANDMARK_KEY_VILLAGE:
+ *
+ * A key for landmark hashtables. The hash value should be a village of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_VILLAGE "village"
+/**
+ * GEOCLUE_LANDMARK_KEY_SUBURB:
+ *
+ * A key for landmark hashtables. The hash value should be a suburb of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_SUBURB "suburb"
+/**
+ * GEOCLUE_LANDMARK_KEY_POSTCODE:
+ *
+ * A key for landmark hashtables. The hash value should be a postcode of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_POSTCODE "postcode"
+/**
+ * GEOCLUE_LANDMARK_KEY_CITY:
+ *
+ * A key for landmark hashtables. The hash value should be a city of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_CITY "city"
+/**
+ * GEOCLUE_LANDMARK_KEY_COUNTY:
+ *
+ * A key for landmark hashtables. The hash value should be a county of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_COUNTY "county"
+/**
+ * GEOCLUE_LANDMARK_KEY_ICON:
+ *
+ * A key for landmark hashtables. The hash value should be an icon path of a landmark.
+ */
+#define GEOCLUE_LANDMARK_KEY_ICON "icon"
+/**
+ * GEOCLUE_LANDMARK_KEY_COUNTRY:
+ *
+ * A key for landmark hashtables. The hash value should be a name of a country.
+ */
+#define GEOCLUE_LANDMARK_KEY_COUNTRY GEOCLUE_ADDRESS_KEY_COUNTRY
+/**
+ * GEOCLUE_LANDMARK_KEY_REGION:
+ *
+ * A key for landmark hashtables. The hash value should be a name of an
+ * administrative region of a nation, e.g. province or
+ * US state.
+ */
+#define GEOCLUE_LANDMARK_KEY_REGION GEOCLUE_ADDRESS_KEY_REGION
+/**
+ * GEOCLUE_LANDMARK_KEY_LOCALITY:
+ *
+ * A key for landmark hashtables. The hash value should be a name of a town
+ * or city.
+ */
+#define GEOCLUE_LANDMARK_KEY_LOCALITY GEOCLUE_ADDRESS_KEY_LOCALITY
+/**
+ * GEOCLUE_LANDMARK_KEY_AREA:
+ *
+ * A key for landmark hashtables. The hash value should be a name of an
+ * area, such as neighborhood or campus.
+ */
+#define GEOCLUE_LANDMARK_KEY_AREA GEOCLUE_ADDRESS_KEY_AREA
+/**
+ * GEOCLUE_LANDMARK_KEY_POSTALCODE:
+ *
+ * A key for landmark hashtables. The hash value should be a code used for
+ * postal delivery.
+ */
+#define GEOCLUE_LANDMARK_KEY_POSTALCODE GEOCLUE_ADDRESS_KEY_POSTALCODE
+/**
+ * GEOCLUE_LANDMARK_KEY_STREET:
+ *
+ * A key for landmark hashtables. The hash value should be a partial or full street
+ * address.
+ */
+#define GEOCLUE_LANDMARK_KEY_STREET GEOCLUE_ADDRESS_KEY_STREET
+
+
+/**
+ * GeoclueResourceFlags:
+ *
+ * bitfield that represents a set of physical resources.
+ *
+ **/
+typedef enum _GeoclueResourceFlags {
+       GEOCLUE_RESOURCE_NONE = 0,
+       GEOCLUE_RESOURCE_NETWORK = 1 << 0,
+       GEOCLUE_RESOURCE_CELL = 1 << 1,
+       GEOCLUE_RESOURCE_GPS = 1 << 2,
+
+       GEOCLUE_RESOURCE_ALL = (1 << 10) - 1
+} GeoclueResourceFlags;
+
+
+/**
+ * GeoclueNetworkStatus:
+ *
+ * Enumeration for current network status.
+ *
+ **/
+typedef enum {
+       GEOCLUE_CONNECTIVITY_UNKNOWN,
+       GEOCLUE_CONNECTIVITY_OFFLINE,
+       GEOCLUE_CONNECTIVITY_ACQUIRING,
+       GEOCLUE_CONNECTIVITY_ONLINE,
+} GeoclueNetworkStatus;
+
+
+
+void geoclue_types_init (void);
+
+#endif
diff --git a/geoclue/geoclue-velocity.c b/geoclue/geoclue-velocity.c
new file mode 100644 (file)
index 0000000..acd9bf6
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ * Geoclue
+ * geoclue-velocity.c - Client API for accessing GcIfaceVelocity
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * SECTION:geoclue-velocity
+ * @short_description: Geoclue velocity client API
+ *
+ * #GeoclueVelocity contains velocity-related methods and signals.
+ * It is part of the Geoclue public C client API which uses D-Bus
+ * to communicate with the actual provider.
+ *
+ * After a #GeoclueVelocity is created with
+ * geoclue_velocity_new(), the
+ * geoclue_velocity_get_velocity() method and the VelocityChanged-signal
+ * can be used to obtain the current velocity.
+ */
+
+#include <geoclue/geoclue-velocity.h>
+#include <geoclue/geoclue-marshal.h>
+
+#include "gc-iface-velocity-bindings.h"
+
+typedef struct _GeoclueVelocityPrivate {
+       int dummy;
+} GeoclueVelocityPrivate;
+
+enum {
+       VELOCITY_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVASTE ((o), GEOCLUE_TYPE_VELOCITY, GeoclueVelocityPrivate))
+
+G_DEFINE_TYPE (GeoclueVelocity, geoclue_velocity, GEOCLUE_TYPE_PROVIDER);
+
+static void
+finalize (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_velocity_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       G_OBJECT_CLASS (geoclue_velocity_parent_class)->dispose (object);
+}
+
+static void
+velocity_changed (DBusGProxy      *proxy,
+                 int              fields,
+                 int              timestamp,
+                 double           speed,
+                 double           direction,
+                 double           climb,
+                 GeoclueVelocity *velocity)
+{
+       g_signal_emit (velocity, signals[VELOCITY_CHANGED], 0, fields,
+                      timestamp, speed, direction, climb);
+}
+
+static GObject *
+constructor (GType                  type,
+            guint                  n_props,
+            GObjectConstructParam *props)
+{
+       GObject *object;
+       GeoclueProvider *provider;
+
+       object = G_OBJECT_CLASS (geoclue_velocity_parent_class)->constructor
+               (type, n_props, props);
+       provider = GEOCLUE_PROVIDER (object);
+
+       dbus_g_proxy_add_signal (provider->proxy, "VelocityChanged",
+                                G_TYPE_INT, G_TYPE_INT, G_TYPE_DOUBLE,
+                                G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_INVALID);
+       dbus_g_proxy_connect_signal (provider->proxy, "VelocityChanged",
+                                    G_CALLBACK (velocity_changed),
+                                    object, NULL);
+
+       return object;
+}
+
+static void
+geoclue_velocity_class_init (GeoclueVelocityClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+       o_class->constructor = constructor;
+
+       g_type_class_add_private (klass, sizeof (GeoclueVelocityPrivate));
+
+       /**
+        * GeoclueVelocity::velocity-changed:
+        * @velocity: the #GeoclueVelocity object emitting the signal
+        * @fields: A #GeoclueVelocityFields bitfield representing the validity of the velocity values
+        * @timestamp: Time of velocity measurement (Unix timestamp)
+        * @speed: horizontal speed
+        * @direction: horizontal direction (bearing)
+        * @climb: vertical speed
+        *
+        * The geoclue-changed signal is emitted each time the velocity changes.
+        *
+        * Note that not all providers support signals.
+        */
+       signals[VELOCITY_CHANGED] = g_signal_new ("velocity-changed",
+                                                 G_TYPE_FROM_CLASS (klass),
+                                                 G_SIGNAL_RUN_FIRST |
+                                                 G_SIGNAL_NO_RECURSE,
+                                                 G_STRUCT_OFFSET (GeoclueVelocityClass, velocity_changed),
+                                                 NULL, NULL,
+                                                 geoclue_marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE,
+                                                 G_TYPE_NONE, 5,
+                                                 G_TYPE_INT, G_TYPE_INT,
+                                                 G_TYPE_DOUBLE, G_TYPE_DOUBLE,
+                                                 G_TYPE_DOUBLE);
+}
+
+/**
+ * geoclue_velocity_new:
+ * @service: D-Bus service name
+ * @path: D-Bus path name
+ *
+ * Creates a #GeoclueVelocity with given D-Bus service name and path.
+ *
+ * Return value: Pointer to a new #GeoclueVelocity
+ */
+static void
+geoclue_velocity_init (GeoclueVelocity *velocity)
+{
+}
+
+GeoclueVelocity *
+geoclue_velocity_new (const char *service,
+                     const char *path)
+{
+       return g_object_new (GEOCLUE_TYPE_VELOCITY,
+                            "service", service,
+                            "path", path,
+                            "interface", GEOCLUE_VELOCITY_INTERFACE_NAME,
+                            NULL);
+}
+
+/**
+ * geoclue_velocity_get_velocity:
+ * @velocity: A #GeoclueVelocity object
+ * @timestamp: Pointer to returned time of velocity measurement (unix timestamp) or %NULL
+ * @speed: Pointer to returned horizontal speed or %NULL
+ * @direction: Pointer to returned horizontal direction (bearing) or %NULL
+ * @climb: Pointer to returned vertical speed or %NULL
+ * @error: Pointer to returned #GError or %NULL
+ *
+ * Obtains the current velocity. @timestamp will contain the time of
+ * the actual velocity measurement.
+ *
+ * If the caller is not interested in some values, the pointers can be
+ * left %NULL.
+ *
+ * Return value: A #GeoclueVelocityFields bitfield representing the
+ * validity of the velocity values.
+ */
+GeoclueVelocityFields
+geoclue_velocity_get_velocity (GeoclueVelocity *velocity,
+                              int             *timestamp,
+                              double          *speed,
+                              double          *direction,
+                              double          *climb,
+                              GError         **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (velocity);
+       double sp, di, cl;
+       int ts, fields;
+
+       if (!org_freedesktop_Geoclue_Velocity_get_velocity (provider->proxy,
+                                                           &fields, &ts,
+                                                           &sp, &di, &cl,
+                                                           error)) {
+               return GEOCLUE_VELOCITY_FIELDS_NONE;
+       }
+
+       if (timestamp != NULL) {
+               *timestamp = ts;
+       }
+
+       if (speed != NULL && (fields & GEOCLUE_VELOCITY_FIELDS_SPEED)) {
+               *speed = sp;
+       }
+
+       if (direction != NULL && (fields & GEOCLUE_VELOCITY_FIELDS_DIRECTION)) {
+               *direction = di;
+       }
+
+       if (climb != NULL && (fields & GEOCLUE_VELOCITY_FIELDS_CLIMB)) {
+               *climb = cl;
+       }
+
+       return fields;
+}
+
+/**
+ * geoclue_velocity_get_last_velocity:
+ * @velocity: A #GeoclueVelocity object
+ * @timestamp: Pointer to returned time of velocity measurement (unix timestamp) or %NULL
+ * @speed: Pointer to returned horizontal speed or %NULL
+ * @direction: Pointer to returned horizontal direction (bearing) or %NULL
+ * @climb: Pointer to returned vertical speed or %NULL
+ * @error: Pointer to returned #GError or %NULL
+ *
+ * Obtains the last velocity. @timestamp will contain the time of
+ * the actual velocity measurement.
+ *
+ * If the caller is not interested in some values, the pointers can be
+ * left %NULL.
+ *
+ * Return value: A #GeoclueVelocityFields bitfield representing the
+ * validity of the velocity values.
+ */
+GeoclueVelocityFields
+geoclue_velocity_get_last_velocity (GeoclueVelocity *velocity,
+                                   int             *timestamp,
+                                   double          *speed,
+                                   double          *direction,
+                                   double          *climb,
+                                   GError         **error)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (velocity);
+       double sp, di, cl;
+       int ts, fields;
+
+       if (!org_freedesktop_Geoclue_Velocity_get_last_velocity (provider->proxy,
+                                                                &fields, &ts,
+                                                                &sp, &di, &cl,
+                                                                error)) {
+               return GEOCLUE_VELOCITY_FIELDS_NONE;
+       }
+
+       if (timestamp != NULL) {
+               *timestamp = ts;
+       }
+
+       if (speed != NULL && (fields & GEOCLUE_VELOCITY_FIELDS_SPEED)) {
+               *speed = sp;
+       }
+
+       if (direction != NULL && (fields & GEOCLUE_VELOCITY_FIELDS_DIRECTION)) {
+               *direction = di;
+       }
+
+       if (climb != NULL && (fields & GEOCLUE_VELOCITY_FIELDS_CLIMB)) {
+               *climb = cl;
+       }
+
+       return fields;
+}
+
+typedef struct _GeoclueVelocityAsyncData {
+       GeoclueVelocity *velocity;
+       GCallback callback;
+       gpointer userdata;
+} GeoclueVelocityAsyncData;
+
+static void
+get_velocity_async_callback (DBusGProxy               *proxy,
+                            GeoclueVelocityFields     fields,
+                            int                       timestamp,
+                            double                    speed,
+                            double                    direction,
+                            double                    climb,
+                            GError                   *error,
+                            GeoclueVelocityAsyncData *data)
+{
+       (*(GeoclueVelocityCallback)data->callback) (data->velocity,
+                                                   fields,
+                                                   timestamp,
+                                                   speed,
+                                                   direction,
+                                                   climb,
+                                                   error,
+                                                   data->userdata);
+       g_free (data);
+}
+
+/**
+ * GeoclueVelocityCallback:
+ * @velocity: A #GeoclueVelocity object
+ * @fields: A #GeoclueVelocityFields bitfield representing the validity of the velocity values
+ * @timestamp: Time of velocity measurement (unix timestamp)
+ * @speed: Horizontal speed
+ * @direction: Horizontal direction (bearing)
+ * @climb: Vertical speed
+ * @error: Error as #GError (may be %NULL)
+ * @userdata: User data pointer set in geoclue_velocity_get_velocity_async()
+ *
+ * Callback function for geoclue_velocity_get_velocity_async().
+ */
+
+/**
+ * geoclue_velocity_get_velocity_async:
+ * @velocity: A #GeoclueVelocity object
+ * @callback: A #GeoclueVelocityCallback function that should be called when return values are available
+ * @userdata: pointer for user specified data
+ *
+ * Function returns (essentially) immediately and calls @callback when current velocity
+ * is available or when D-Bus timeouts.
+ */
+void
+geoclue_velocity_get_velocity_async (GeoclueVelocity         *velocity,
+                                    GeoclueVelocityCallback  callback,
+                                    gpointer                 userdata)
+{
+       GeoclueProvider *provider = GEOCLUE_PROVIDER (velocity);
+       GeoclueVelocityAsyncData *data;
+
+       data = g_new (GeoclueVelocityAsyncData, 1);
+       data->velocity = velocity;
+       data->callback = G_CALLBACK (callback);
+       data->userdata = userdata;
+
+       org_freedesktop_Geoclue_Velocity_get_velocity_async
+                       (provider->proxy,
+                        (org_freedesktop_Geoclue_Velocity_get_velocity_reply)get_velocity_async_callback,
+                        data);
+}
diff --git a/geoclue/geoclue-velocity.h b/geoclue/geoclue-velocity.h
new file mode 100644 (file)
index 0000000..d1798cb
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Geoclue
+ * geoclue-velocity.h -
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_VELOCITY_H
+#define _GEOCLUE_VELOCITY_H
+
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_VELOCITY (geoclue_velocity_get_type ())
+#define GEOCLUE_VELOCITY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_VELOCITY, GeoclueVelocity))
+#define GEOCLUE_IS_VELOCITY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_VELOCITY))
+
+#define GEOCLUE_VELOCITY_INTERFACE_NAME "org.freedesktop.Geoclue.Velocity"
+
+typedef struct _GeoclueVelocity {
+       GeoclueProvider provider;
+} GeoclueVelocity;
+
+typedef struct _GeoclueVelocityClass {
+       GeoclueProviderClass provider_class;
+
+       void (* velocity_changed) (GeoclueVelocity      *velocity,
+                                  GeoclueVelocityFields fields,
+                                  int                   timestamp,
+                                  double                speed,
+                                  double                direction,
+                                  double                climb);
+} GeoclueVelocityClass;
+
+GType geoclue_velocity_get_type (void);
+
+GeoclueVelocity *geoclue_velocity_new (const char *service,
+                                      const char *path);
+
+GeoclueVelocityFields geoclue_velocity_get_velocity (GeoclueVelocity  *velocity,
+                                                    int              *timestamp,
+                                                    double           *speed,
+                                                    double           *direction,
+                                                    double           *climb,
+                                                    GError          **error);
+
+GeoclueVelocityFields geoclue_velocity_get_last_velocity (GeoclueVelocity  *velocity,
+                                                         int              *timestamp,
+                                                         double           *speed,
+                                                         double           *direction,
+                                                         double           *climb,
+                                                         GError          **error);
+
+typedef void (*GeoclueVelocityCallback) (GeoclueVelocity      *velocity,
+                                        GeoclueVelocityFields fields,
+                                        int                   timestamp,
+                                        double                speed,
+                                        double                direction,
+                                        double                climb,
+                                        GError               *error,
+                                        gpointer              userdata);
+
+void geoclue_velocity_get_velocity_async (GeoclueVelocity         *velocity,
+                                         GeoclueVelocityCallback  callback,
+                                         gpointer                 userdata);
+
+G_END_DECLS
+
+#endif
diff --git a/gtk-doc.make b/gtk-doc.make
new file mode 100644 (file)
index 0000000..63adaed
--- /dev/null
@@ -0,0 +1,224 @@
+# -*- mode: makefile -*-
+
+####################################
+# Everything below here is generic #
+####################################
+
+if GTK_DOC_USE_LIBTOOL
+GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
+GTKDOC_RUN = $(LIBTOOL) --mode=execute
+else
+GTKDOC_CC = $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+GTKDOC_LD = $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
+GTKDOC_RUN =
+endif
+
+# We set GPATH here; this gives us semantics for GNU make
+# which are more like other make's VPATH, when it comes to
+# whether a source that is a target of one rule is then
+# searched for in VPATH/GPATH.
+#
+GPATH = $(srcdir)
+
+TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE)
+
+EXTRA_DIST =                           \
+       $(content_files)                \
+       $(HTML_IMAGES)                  \
+       $(DOC_MAIN_SGML_FILE)           \
+       $(DOC_MODULE)-sections.txt      \
+       $(DOC_MODULE)-overrides.txt
+
+DOC_STAMPS=scan-build.stamp tmpl-build.stamp sgml-build.stamp html-build.stamp \
+       pdf-build.stamp \
+       $(srcdir)/tmpl.stamp $(srcdir)/sgml.stamp $(srcdir)/html.stamp \
+       $(srcdir)/pdf.stamp
+
+SCANOBJ_FILES =                 \
+       $(DOC_MODULE).args       \
+       $(DOC_MODULE).hierarchy  \
+       $(DOC_MODULE).interfaces \
+       $(DOC_MODULE).prerequisites \
+       $(DOC_MODULE).signals
+
+REPORT_FILES = \
+       $(DOC_MODULE)-undocumented.txt \
+       $(DOC_MODULE)-undeclared.txt \
+       $(DOC_MODULE)-unused.txt
+
+CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS)
+
+if ENABLE_GTK_DOC
+if GTK_DOC_BUILD_HTML
+HTML_BUILD_STAMP=html-build.stamp
+else
+HTML_BUILD_STAMP=
+endif
+if GTK_DOC_BUILD_PDF
+PDF_BUILD_STAMP=pdf-build.stamp
+else
+PDF_BUILD_STAMP=
+endif
+
+all-local: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP)
+else
+all-local:
+endif
+
+docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP)
+
+$(REPORT_FILES): sgml-build.stamp
+
+#### scan ####
+
+scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB)
+       @echo 'gtk-doc: Scanning header files'
+       @-chmod -R u+w $(srcdir)
+       @cd $(srcdir) && \
+         gtkdoc-scan --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --ignore-headers="$(IGNORE_HFILES)" $(SCAN_OPTIONS) $(EXTRA_HFILES)
+       @if grep -l '^..*$$' $(srcdir)/$(DOC_MODULE).types > /dev/null 2>&1 ; then \
+           CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" gtkdoc-scangobj $(SCANGOBJ_OPTIONS) --module=$(DOC_MODULE) --output-dir=$(srcdir) ; \
+       else \
+           cd $(srcdir) ; \
+           for i in $(SCANOBJ_FILES) ; do \
+               test -f $$i || touch $$i ; \
+           done \
+       fi
+       @touch scan-build.stamp
+
+$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp
+       @true
+
+#### templates ####
+
+tmpl-build.stamp: $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt
+       @echo 'gtk-doc: Rebuilding template files'
+       @-chmod -R u+w $(srcdir)
+       @cd $(srcdir) && gtkdoc-mktmpl --module=$(DOC_MODULE) $(MKTMPL_OPTIONS)
+       @touch tmpl-build.stamp
+
+tmpl.stamp: tmpl-build.stamp
+       @true
+
+$(srcdir)/tmpl/*.sgml:
+       @true
+
+#### xml ####
+
+sgml-build.stamp: tmpl.stamp $(DOC_MODULE)-sections.txt $(srcdir)/tmpl/*.sgml $(expand_content_files)
+       @echo 'gtk-doc: Building XML'
+       @-chmod -R u+w $(srcdir)
+       @cd $(srcdir) && \
+       gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $(MKDB_OPTIONS)
+       @touch sgml-build.stamp
+
+sgml.stamp: sgml-build.stamp
+       @true
+
+#### html ####
+
+html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files)
+       @echo 'gtk-doc: Building HTML'
+       @-chmod -R u+w $(srcdir)
+       @rm -rf $(srcdir)/html
+       @mkdir $(srcdir)/html
+       @mkhtml_options=""; \
+       gtkdoc-mkhtml 2>&1 --help | grep  >/dev/null "\-\-path"; \
+       if test "$(?)" = "0"; then \
+         mkhtml_options=--path="$(srcdir)"; \
+       fi; \
+       cd $(srcdir)/html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE)
+       @test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) html )
+       @echo 'gtk-doc: Fixing cross-references'
+       @cd $(srcdir) && gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS)
+       @touch html-build.stamp
+
+#### pdf ####
+
+pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files)
+       @echo 'gtk-doc: Building PDF'
+       @-chmod -R u+w $(srcdir)
+       @rm -rf $(srcdir)/$(DOC_MODULE).pdf
+       @mkpdf_imgdirs=""; \
+       if test "x$(HTML_IMAGES)" != "x"; then \
+         for img in $(HTML_IMAGES); do \
+           part=`dirname $$img`; \
+           echo $$mkpdf_imgdirs | grep >/dev/null "\-\-imgdir=$$part "; \
+           if test $$? != 0; then \
+             mkpdf_imgdirs="$$mkpdf_imgdirs --imgdir=$$part"; \
+           fi; \
+         done; \
+       fi; \
+       cd $(srcdir) && gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_imgdirs $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS)
+       @touch pdf-build.stamp
+
+##############
+
+clean-local:
+       rm -f *~ *.bak
+       rm -rf .libs
+
+distclean-local:
+       cd $(srcdir) && \
+         rm -rf xml $(REPORT_FILES) $(DOC_MODULE).pdf \
+                $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt
+
+maintainer-clean-local: clean
+       cd $(srcdir) && rm -rf xml html
+
+install-data-local:
+       @installfiles=`echo $(srcdir)/html/*`; \
+       if test "$$installfiles" = '$(srcdir)/html/*'; \
+       then echo '-- Nothing to install' ; \
+       else \
+         if test -n "$(DOC_MODULE_VERSION)"; then \
+           installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
+         else \
+           installdir="$(DESTDIR)$(TARGET_DIR)"; \
+         fi; \
+         $(mkinstalldirs) $${installdir} ; \
+         for i in $$installfiles; do \
+           echo '-- Installing '$$i ; \
+           $(INSTALL_DATA) $$i $${installdir}; \
+         done; \
+         if test -n "$(DOC_MODULE_VERSION)"; then \
+           mv -f $${installdir}/$(DOC_MODULE).devhelp2 \
+             $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \
+           mv -f $${installdir}/$(DOC_MODULE).devhelp \
+             $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp; \
+         fi; \
+         $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \
+       fi
+
+uninstall-local:
+       @if test -n "$(DOC_MODULE_VERSION)"; then \
+         installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
+       else \
+         installdir="$(DESTDIR)$(TARGET_DIR)"; \
+       fi; \
+       rm -rf $${installdir}
+
+#
+# Require gtk-doc when making dist
+#
+if ENABLE_GTK_DOC
+dist-check-gtkdoc:
+else
+dist-check-gtkdoc:
+       @echo "*** gtk-doc must be installed and enabled in order to make dist"
+       @false
+endif
+
+dist-hook: dist-check-gtkdoc dist-hook-local
+       mkdir $(distdir)/tmpl
+       mkdir $(distdir)/html
+       -cp $(srcdir)/tmpl/*.sgml $(distdir)/tmpl
+       cp $(srcdir)/html/* $(distdir)/html
+       -cp $(srcdir)/$(DOC_MODULE).pdf $(distdir)/
+       -cp $(srcdir)/$(DOC_MODULE).types $(distdir)/
+       -cp $(srcdir)/$(DOC_MODULE)-sections.txt $(distdir)/
+       cd $(distdir) && rm -f $(DISTCLEANFILES)
+       $(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html
+
+.PHONY : dist-hook-local docs
diff --git a/install-sh b/install-sh
new file mode 100755 (executable)
index 0000000..6781b98
--- /dev/null
@@ -0,0 +1,520 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2009-04-28.21; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""       $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -s            $stripprog installed files.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+       shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+       case $mode in
+         *' '* | *'    '* | *'
+'*       | *'*'* | *'?'* | *'['*)
+           echo "$0: invalid mode: $mode" >&2
+           exit 1;;
+       esac
+       shift;;
+
+    -o) chowncmd="$chownprog $2"
+       shift;;
+
+    -s) stripcmd=$stripprog;;
+
+    -t) dst_arg=$2
+       shift;;
+
+    -T) no_target_directory=true;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)        shift
+       break;;
+
+    -*)        echo "$0: invalid option: $1" >&2
+       exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  trap '(exit $?); exit' 1 2 13 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+
+    dst=$dst_arg
+    # Protect names starting with `-'.
+    case $dst in
+      -*) dst=./$dst;;
+    esac
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+       echo "$0: $dst_arg: Is a directory" >&2
+       exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+       (dirname "$dst") 2>/dev/null ||
+       expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+            X"$dst" : 'X\(//\)[^/]' \| \
+            X"$dst" : 'X\(//\)$' \| \
+            X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+       echo X"$dst" |
+           sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)[^/].*/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\).*/{
+                  s//\1/
+                  q
+                }
+                s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+       # Create intermediate dirs using mode 755 as modified by the umask.
+       # This is like FreeBSD 'install' as of 1997-10-28.
+       umask=`umask`
+       case $stripcmd.$umask in
+         # Optimize common cases.
+         *[2367][2367]) mkdir_umask=$umask;;
+         .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+         *[0-7])
+           mkdir_umask=`expr $umask + 22 \
+             - $umask % 100 % 40 + $umask % 20 \
+             - $umask % 10 % 4 + $umask % 2
+           `;;
+         *) mkdir_umask=$umask,go-w;;
+       esac
+
+       # With -d, create the new directory with the user-specified mode.
+       # Otherwise, rely on $mkdir_umask.
+       if test -n "$dir_arg"; then
+         mkdir_mode=-m$mode
+       else
+         mkdir_mode=
+       fi
+
+       posix_mkdir=false
+       case $umask in
+         *[123567][0-7][0-7])
+           # POSIX mkdir -p sets u+wx bits regardless of umask, which
+           # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+           ;;
+         *)
+           tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+           trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+           if (umask $mkdir_umask &&
+               exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+           then
+             if test -z "$dir_arg" || {
+                  # Check for POSIX incompatibilities with -m.
+                  # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+                  # other-writeable bit of parent directory when it shouldn't.
+                  # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+                  ls_ld_tmpdir=`ls -ld "$tmpdir"`
+                  case $ls_ld_tmpdir in
+                    d????-?r-*) different_mode=700;;
+                    d????-?--*) different_mode=755;;
+                    *) false;;
+                  esac &&
+                  $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+                    ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+                    test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+                  }
+                }
+             then posix_mkdir=:
+             fi
+             rmdir "$tmpdir/d" "$tmpdir"
+           else
+             # Remove any dirs left behind by ancient mkdir implementations.
+             rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+           fi
+           trap '' 0;;
+       esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+       umask $mkdir_umask &&
+       $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+       /*) prefix='/';;
+       -*) prefix='./';;
+       *)  prefix='';;
+      esac
+
+      eval "$initialize_posix_glob"
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob set -f
+      set fnord $dstdir
+      shift
+      $posix_glob set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+       test -z "$d" && continue
+
+       prefix=$prefix$d
+       if test -d "$prefix"; then
+         prefixes=
+       else
+         if $posix_mkdir; then
+           (umask=$mkdir_umask &&
+            $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+           # Don't fail if two instances are running concurrently.
+           test -d "$prefix" || exit 1
+         else
+           case $prefix in
+             *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+             *) qprefix=$prefix;;
+           esac
+           prefixes="$prefixes '$qprefix'"
+         fi
+       fi
+       prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+       # Don't fail if two instances are running concurrently.
+       (umask $mkdir_umask &&
+        eval "\$doit_exec \$mkdirprog $prefixes") ||
+         test -d "$dstdir" || exit 1
+       obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"    2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+       # Now remove or move aside any old file at destination location.
+       # We try this two ways since rm can't unlink itself on some
+       # systems and the destination file might be busy for other
+       # reasons.  In this case, the final cleanup might fail but the new
+       # file should still install successfully.
+       {
+         test ! -f "$dst" ||
+         $doit $rmcmd -f "$dst" 2>/dev/null ||
+         { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+           { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+         } ||
+         { echo "$0: cannot unlink or rename $dst" >&2
+           (exit 1); exit 1
+         }
+       } &&
+
+       # Now rename the file to the real destination.
+       $doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/interfaces/Makefile.am b/interfaces/Makefile.am
new file mode 100644 (file)
index 0000000..33e5d7e
--- /dev/null
@@ -0,0 +1,33 @@
+%.xml: %-full.xml
+       $(XSLT) -o $@ $(top_srcdir)/docs/tools/spec-strip-docs.xsl $<
+
+noinst_DATA = \
+       gc-iface-geoclue.xml \
+       gc-iface-position.xml \
+       gc-iface-position-ext.xml \
+       gc-iface-nmea.xml \
+       gc-iface-address.xml \
+       gc-iface-geocode.xml \
+       gc-iface-master.xml \
+       gc-iface-master-client.xml \
+       gc-iface-reverse-geocode.xml \
+       gc-iface-velocity.xml \
+       gc-iface-satellite.xml \
+       gc-iface-poi.xml
+
+BUILT_SOURCES = $(noinst_DATA)
+CLEANFILES = $(BUILT_SOURCES)
+
+EXTRA_DIST = \
+       gc-iface-geoclue-full.xml \
+       gc-iface-position-full.xml \
+       gc-iface-position-ext-full.xml \
+       gc-iface-nmea-full.xml \
+       gc-iface-address-full.xml \
+       gc-iface-geocode-full.xml \
+       gc-iface-master-full.xml \
+       gc-iface-master-client-full.xml \
+       gc-iface-reverse-geocode-full.xml \
+       gc-iface-velocity-full.xml \
+       gc-iface-satellite-full.xml \
+       gc-iface-poi-full.xml
diff --git a/interfaces/gc-iface-address-full.xml b/interfaces/gc-iface-address-full.xml
new file mode 100755 (executable)
index 0000000..2357d84
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+        <interface name="org.freedesktop.Geoclue.Address">
+               <method name="GetAddress">
+                       <arg type="i" name="timestamp" direction="out" />
+
+                       <arg name="address" type="a{ss}" direction="out" />
+
+                       <arg name="accuracy" type="(idd)" direction="out" />
+               </method>
+
+               <signal name="AddressChanged">
+                       <arg type="i" name="timestamp" />
+                       <arg type="a{ss}" name="address" />
+                       <arg type="(idd)" name="accuracy" />
+               </signal>
+       </interface>
+</node>
diff --git a/interfaces/gc-iface-geoclue-full.xml b/interfaces/gc-iface-geoclue-full.xml
new file mode 100644 (file)
index 0000000..f290e8b
--- /dev/null
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+       <interface name="org.freedesktop.Geoclue">
+               <doc:doc>
+                       <doc:para>Geoclue interface contains methods
+                       and signals common to all providers (and all providers
+                       must implement at least this interface).</doc:para>
+               </doc:doc>
+
+               <method name="GetProviderInfo">
+                       <arg type="s" name="Name" direction="out">
+                               <doc:doc>
+                                       <doc:summary>The provider name</doc:summary>
+                               </doc:doc>
+                       </arg>
+                       <arg type="s" name="Description" direction="out">
+                               <doc:doc>
+                                       <doc:summary>Short description of the provider</doc:summary>
+                               </doc:doc>
+                       </arg>
+               </method>
+
+               <method name="GetStatus">
+                       <arg type="i" name="status" direction="out" >
+                               <doc:doc>
+                                       <doc:summary>Current provider status, as GeoclueStatus</doc:summary>
+                               </doc:doc>
+                       </arg>
+               </method>
+
+               <signal name="StatusChanged">
+                       <arg type="i" name="status" direction="out">
+                               <doc:doc>
+                                       <doc:summary>Current provider status, as GeoclueStatus</doc:summary>
+                               </doc:doc>
+                       </arg>
+               </signal>
+
+               <method name="SetOptions">
+                       <arg type="a{ss}" name="options" direction="in" />
+               </method>
+
+               <method name="AddReference">
+                       <doc:doc>
+                               <doc:description>Increase the reference count on the provider.
+                               Provider may shutdown if reference count reaches zero, so
+                               using AddReference()/RemoveReference is important for clients needing server
+                               persistence -- basically any client that uses SetOptions() or connects to
+                               signals.</doc:description>
+                       </doc:doc>
+                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+               </method>
+
+               <method name="RemoveReference">
+                       <doc:doc>
+                               <doc:description>Decrease the reference count on the provider</doc:description>
+                       </doc:doc>
+                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+               </method>
+       </interface>
+</node>
+
diff --git a/interfaces/gc-iface-geocode-full.xml b/interfaces/gc-iface-geocode-full.xml
new file mode 100755 (executable)
index 0000000..5bec1c5
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+       <interface name="org.freedesktop.Geoclue.Geocode">
+
+               <method name="AddressToPosition">
+                       <arg name="address" type="a{ss}" direction="in" />
+                       <arg name="fields" type="i" direction="out" />
+                       <arg name="latitude" type="d" direction="out" />
+                       <arg name="longitude" type="d" direction="out" />
+                       <arg name="altitude" type="d" direction="out" />
+                       <arg name="accuracy" type="(idd)" direction="out" />
+               </method>
+
+               <method name="FreeformAddressToPosition">
+                       <arg name="address" type="s" direction="in" />
+                       <arg name="fields" type="i" direction="out" />
+                       <arg name="latitude" type="d" direction="out" />
+                       <arg name="longitude" type="d" direction="out" />
+                       <arg name="altitude" type="d" direction="out" />
+                       <arg name="accuracy" type="(idd)" direction="out" />
+               </method>
+
+       </interface>
+</node>
diff --git a/interfaces/gc-iface-master-client-full.xml b/interfaces/gc-iface-master-client-full.xml
new file mode 100755 (executable)
index 0000000..647b4fd
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+       <interface name="org.freedesktop.Geoclue.MasterClient">
+               <method name="SetRequirements">
+                       <arg name="accuracy_level" type="i" direction="in" />
+                       <arg name="time" type="i" direction="in" />
+                       <arg name="require_updates" type="b" direction="in" />
+                       <arg name="allowed_resources" type="i" direction="in" />
+               </method>
+
+               <method name="AddressStart"/>
+               <method name="PositionStart"/>
+
+               <method name="GetAddressProvider">
+                       <arg name="name" type="s" direction="out"/>
+                       <arg name="description" type="s" direction="out"/>
+                       <arg name="service" type="s" direction="out"/>
+                       <arg name="path" type="s" direction="out"/>
+               </method>
+               <method name="GetPositionProvider">
+                       <arg name="name" type="s" direction="out"/>
+                       <arg name="description" type="s" direction="out"/>
+                       <arg name="service" type="s" direction="out"/>
+                       <arg name="path" type="s" direction="out"/>
+               </method>
+
+               <signal name="AddressProviderChanged">
+                       <arg name="name" type="s" direction="out"/>
+                       <arg name="description" type="s" direction="out"/>
+                       <arg name="service" type="s" direction="out"/>
+                       <arg name="path" type="s" direction="out"/>
+               </signal>
+               <signal name="PositionProviderChanged">
+                       <arg name="name" type="s" direction="out"/>
+                       <arg name="description" type="s" direction="out"/>
+                       <arg name="service" type="s" direction="out"/>
+                       <arg name="path" type="s" direction="out"/>
+               </signal>
+       </interface>
+</node>
diff --git a/interfaces/gc-iface-master-full.xml b/interfaces/gc-iface-master-full.xml
new file mode 100755 (executable)
index 0000000..4cfec4e
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+       <interface name="org.freedesktop.Geoclue.Master">
+               <method name="Create">
+                       <arg type="o" name="path" direction="out" />
+               </method>
+       </interface>
+</node>
diff --git a/interfaces/gc-iface-nmea-full.xml b/interfaces/gc-iface-nmea-full.xml
new file mode 100644 (file)
index 0000000..2ef91aa
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+       <interface name="org.freedesktop.Geoclue.Nmea">
+               <doc:doc>
+                       <doc:para>Nmea interface contains a method
+                       and a signal for querying current coordinates.</doc:para>
+               </doc:doc>
+
+               <method name="GetNmea">
+                       <arg type="i" name="timestamp" direction="out" />
+                       <arg type="s" name="nmea_data" direction="out" />
+               </method>
+
+               <signal name="NmeaChanged">
+                       <arg type="i" name="timestamp" />
+                       <arg type="s" name="nmea_data" />
+               </signal>
+       </interface>
+</node>
diff --git a/interfaces/gc-iface-poi-full.xml b/interfaces/gc-iface-poi-full.xml
new file mode 100644 (file)
index 0000000..678c889
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+       <interface name="org.freedesktop.Geoclue.Poi">
+
+               <method name="SearchByPosition">
+                       <arg name="keyword" type="s" direction="in" />
+                       <arg name="lang" type="s" direction="in" />
+                       <arg name="country_code" type="s" direction="in" />
+                       <arg name="limit" type="i" direction="in" />
+                       <arg name="left" type="d" direction="in" />
+                       <arg name="top" type="d" direction="in" />
+                       <arg name="right" type="d" direction="in" />
+                       <arg name="bottom" type="d" direction="in" />
+                       <arg name="count" type="i" direction="out" />
+                       <arg name="landmark" type="a(iiddddddsssssssssss)" direction="out" />
+               </method>
+
+       </interface>
+</node>
diff --git a/interfaces/gc-iface-position-ext-full.xml b/interfaces/gc-iface-position-ext-full.xml
new file mode 100755 (executable)
index 0000000..43f4cd8
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+       <interface name="org.freedesktop.Geoclue.PositionExt">
+               <doc:doc>
+                       <doc:para>Position / Velocity interface contains a method
+                       and a signal for querying current coordinates.</doc:para>
+               </doc:doc>
+
+               <method name="GetPosition">
+                       <arg type="i" name="fields" direction="out" />
+                       <arg type="i" name="timestamp" direction="out" />
+
+                       <arg type="d" name="latitude" direction="out" />
+                       <arg type="d" name="longitude" direction="out" />
+                       <arg type="d" name="altitude" direction="out" />
+
+                       <arg type="d" name="speed" direction="out" />
+                       <arg type="d" name="direction" direction="out" />
+                       <arg type="d" name="climb" direction="out" />
+
+                       <arg name="accuracy" type="(idd)" direction="out" />
+               </method>
+
+               <method name="GetLastPosition">
+                       <arg type="i" name="fields" direction="out" />
+                       <arg type="i" name="timestamp" direction="out" />
+
+                       <arg type="d" name="latitude" direction="out" />
+                       <arg type="d" name="longitude" direction="out" />
+                       <arg type="d" name="altitude" direction="out" />
+
+                       <arg type="d" name="speed" direction="out" />
+                       <arg type="d" name="direction" direction="out" />
+                       <arg type="d" name="climb" direction="out" />
+
+                       <arg name="accuracy" type="(idd)" direction="out" />
+               </method>
+
+               <signal name="PositionChanged">
+                       <arg type="i" name="fields" />
+                       <arg type="i" name="timestamp" />
+                       <arg type="d" name="latitude" />
+                       <arg type="d" name="longitude" />
+                       <arg type="d" name="altitude" />
+                       <arg type="d" name="speed" />
+                       <arg type="d" name="direction" />
+                       <arg type="d" name="climb" />
+                       <arg type="(idd)" name="accuracy" />
+               </signal>
+       </interface>
+</node>
diff --git a/interfaces/gc-iface-position-full.xml b/interfaces/gc-iface-position-full.xml
new file mode 100755 (executable)
index 0000000..58c7017
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+       <interface name="org.freedesktop.Geoclue.Position">
+               <doc:doc>
+                       <doc:para>Position interface contains a method
+                       and a signal for querying current coordinates.</doc:para>
+               </doc:doc>
+
+               <method name="GetPosition">
+                       <arg type="i" name="fields" direction="out" />
+                       <arg type="i" name="timestamp" direction="out" />
+
+                       <arg type="d" name="latitude" direction="out" />
+                       <arg type="d" name="longitude" direction="out" />
+                       <arg type="d" name="altitude" direction="out" />
+
+                       <arg name="accuracy" type="(idd)" direction="out" />
+               </method>
+
+               <method name="GetLastPosition">
+                       <arg type="i" name="fields" direction="out" />
+                       <arg type="i" name="timestamp" direction="out" />
+
+                       <arg type="d" name="latitude" direction="out" />
+                       <arg type="d" name="longitude" direction="out" />
+                       <arg type="d" name="altitude" direction="out" />
+
+                       <arg name="accuracy" type="(idd)" direction="out" />
+               </method>
+
+               <signal name="PositionChanged">
+                       <arg type="i" name="fields" />
+                       <arg type="i" name="timestamp" />
+                       <arg type="d" name="latitude" />
+                       <arg type="d" name="longitude" />
+                       <arg type="d" name="altitude" />
+
+                       <arg type="(idd)" name="accuracy" />
+               </signal>
+       </interface>
+</node>
diff --git a/interfaces/gc-iface-reverse-geocode-full.xml b/interfaces/gc-iface-reverse-geocode-full.xml
new file mode 100755 (executable)
index 0000000..0247081
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+       <interface name="org.freedesktop.Geoclue.ReverseGeocode">
+               <method name="PositionToAddress">
+                       <arg name="latitude" type="d" direction="in" />
+                       <arg name="longitude" type="d" direction="in" />
+                       <arg name="position_accuracy" type="(idd)" direction="in" />
+
+                       <arg type="a{ss}" name="address" direction="out" />
+                       <arg name="address_accuracy" type="(idd)" direction="out" />
+               </method>
+       </interface>
+</node>
diff --git a/interfaces/gc-iface-satellite-full.xml b/interfaces/gc-iface-satellite-full.xml
new file mode 100644 (file)
index 0000000..c7be2da
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+       <interface name="org.freedesktop.Geoclue.Satellite">
+               <method name="GetSatellite">
+                       <arg type="i" name="timestamp" direction="out" />
+                       <arg type="i" name="satellite_used" direction="out" />
+                       <arg type="i" name="satellite_visible" direction="out" />
+                       <arg type="ai" name="used_prn" direction="out" />
+                       <arg type="a(iiii)" name="sat_info" direction="out" />
+               </method>
+
+               <method name="GetLastSatellite">
+                       <arg type="i" name="timestamp" direction="out" />
+                       <arg type="i" name="satellite_used" direction="out" />
+                       <arg type="i" name="satellite_visible" direction="out" />
+                       <arg type="ai" name="used_prn" direction="out" />
+                       <arg type="a(iiii)" name="sat_info" direction="out" />
+               </method>
+
+               <signal name="SatelliteChanged">
+                       <arg type="i" name="timestamp" />
+                       <arg type="i" name="satellite_used" />
+                       <arg type="i" name="satellite_visible" />
+                       <arg type="ai" name="used_prn" />
+                       <arg type="a(iiii)" name="sat_info" />
+               </signal>
+       </interface>
+</node>
diff --git a/interfaces/gc-iface-velocity-full.xml b/interfaces/gc-iface-velocity-full.xml
new file mode 100755 (executable)
index 0000000..f1e36f9
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+        <interface name="org.freedesktop.Geoclue.Velocity">
+               <method name="GetVelocity">
+                       <arg type="i" name="fields" direction="out" />
+                       <arg type="i" name="timestamp" direction="out" />
+                       <arg type="d" name="speed" direction="out" />
+                       <arg type="d" name="direction" direction="out" />
+                       <arg type="d" name="climb" direction="out" />
+               </method>
+
+               <method name="GetLastVelocity">
+                       <arg type="i" name="fields" direction="out" />
+                       <arg type="i" name="timestamp" direction="out" />
+                       <arg type="d" name="speed" direction="out" />
+                       <arg type="d" name="direction" direction="out" />
+                       <arg type="d" name="climb" direction="out" />
+               </method>
+
+               <signal name="VelocityChanged">
+                       <arg type="i" name="fields" />
+                       <arg type="i" name="timestamp" />
+                       <arg type="d" name="speed" />
+                       <arg type="d" name="direction" />
+                       <arg type="d" name="climb" />
+               </signal>
+       </interface>
+</node>
diff --git a/libgeoclue.manifest b/libgeoclue.manifest
new file mode 100644 (file)
index 0000000..97e8c31
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>
diff --git a/packaging/geoclue.spec b/packaging/geoclue.spec
new file mode 100644 (file)
index 0000000..d27ad25
--- /dev/null
@@ -0,0 +1,95 @@
+#sbs-git:slp/pkgs/g/geoclue geoclue 0.12.0 607dc26233fecdf2370e5a0b5eab4031f979fc0a
+Name:       geoclue
+Summary:    Geoinformation service
+Version:    0.12.0_28
+Release:    0
+Group:      TO_BE/FILLED_IN
+License:    TO BE FILLED IN
+Source0:    geoclue-%{version}.tar.gz
+BuildRequires:  which
+BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(dbus-glib-1)
+BuildRequires:  pkgconfig(libxml-2.0)
+BuildRequires:  pkgconfig(gconf-2.0)
+BuildRequires:  pkgconfig(libsoup-2.4)
+BuildRequires:  pkgconfig(libxslt)
+
+
+%description
+Geographic information framework GeoClue provides applications access to various geographical information 
+ sources using a D-Bus API or a C library. 
+ .
+ This package contains the master server for GeoClue.
+
+%package -n libgeoclue
+Summary:    C API for GeoClue
+Group:      TO_BE/FILLED
+Requires:   %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libgeoclue
+libgeoclue is a convenience wrapper for the GeoClue service, and
+the recommended way to use GeoClue in the C language.
+
+%package -n libgeoclue-devel
+Summary:    C API for GeoClue (development files)
+Group:      TO_BE/FILLED
+Requires:   libgeoclue = %{version}-%{release}
+
+%description -n libgeoclue-devel
+libgeoclue is a convenience wrapper for the GeoClue service, and
+the recommended way to use GeoClue in the C language.
+
+%package -n geoclue-nominatim
+Summary:    Geocode server for GeoClue (OpenStreetMap)
+Group:      TO_BE/FILLED
+Requires:   %{name} = %{version}-%{release}
+
+%description -n geoclue-nominatim
+GeoClue provides applications access to various geographical information
+sources using a D-Bus API or a C library.
+.
+This package provides a tool to search osm data by name and address and to generate synthetic addresses of osm points (reverse geocoding)
+
+
+%prep
+%setup -q -n %{name}-%{version}
+
+
+%build
+export CFLAGS+=" -Wall -g -fPIC"
+export LDFLAGS+=" -Wl,-z,defs -Wl,--rpath=/usr/lib -Wl,--as-needed -Wl,--hash-style=both"
+
+./autogen.sh
+./configure --disable-static --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-system-bus=yes --disable-gypsy --disable-lbs --disable-xps
+
+#make %{?jobs:-j%jobs}
+make
+
+%install
+rm -rf %{buildroot}
+%make_install
+rm -rf %{buildroot}/usr/bin/geoclue-test-gui
+
+
+%post -n libgeoclue -p /sbin/ldconfig
+
+%postun -n libgeoclue -p /sbin/ldconfig
+
+%files
+/usr/libexec/geoclue-master
+/usr/share/dbus-1/services/org.freedesktop.Geoclue.Master.service
+
+%files -n libgeoclue
+%manifest libgeoclue.manifest
+/usr/lib/libgeoclue.so*
+
+%files -n libgeoclue-devel
+/usr/include/*
+/usr/lib/pkgconfig/*
+
+%files -n geoclue-nominatim
+/usr/share/dbus-1/services/org.freedesktop.Geoclue.Providers.Nominatim.service
+/usr/share/geoclue-providers/geoclue-nominatim.provider
+/usr/libexec/geoclue-nominatim
diff --git a/providers/Makefile.am b/providers/Makefile.am
new file mode 100644 (file)
index 0000000..7a966e3
--- /dev/null
@@ -0,0 +1,3 @@
+SUBDIRS = $(PROVIDER_SUBDIRS)
+
+DIST_SUBDIRS = $(PROVIDER_SUBDIRS) $(NO_BUILD_PROVIDERS)
diff --git a/providers/example/Makefile.am b/providers/example/Makefile.am
new file mode 100644 (file)
index 0000000..29bf144
--- /dev/null
@@ -0,0 +1,30 @@
+libexec_PROGRAMS = geoclue-example
+
+geoclue_example_CFLAGS =       \
+       -I$(top_srcdir)         \
+       -I$(top_builddir)       \
+       $(GEOCLUE_CFLAGS)
+
+geoclue_example_LDADD =                \
+       $(GEOCLUE_LIBS)         \
+       $(top_builddir)/geoclue/libgeoclue.la
+
+geoclue_example_SOURCES =      \
+       geoclue-example.c
+
+providersdir = $(datadir)/geoclue-providers
+providers_DATA = geoclue-example.provider
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Providers.Example.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+EXTRA_DIST =                   \
+       $(service_in_files)     \
+       $(providers_DATA)
+
+DISTCLEANFILES = \
+       $(service_DATA)
diff --git a/providers/example/geoclue-example.c b/providers/example/geoclue-example.c
new file mode 100644 (file)
index 0000000..8e71b52
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Geoclue
+ * geoclue-example.c - Example provider which doesn't do anything.
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <geoclue/gc-provider.h>
+#include <geoclue/gc-iface-position.h>
+
+typedef struct {
+       GcProvider parent;
+
+       GMainLoop *loop;
+} GeoclueExample;
+
+typedef struct {
+       GcProviderClass parent_class;
+} GeoclueExampleClass;
+
+#define GEOCLUE_TYPE_EXAMPLE (geoclue_example_get_type ())
+#define GEOCLUE_EXAMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_EXAMPLE, GeoclueExample))
+
+static void geoclue_example_position_init (GcIfacePositionClass *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueExample, geoclue_example, GC_TYPE_PROVIDER,
+                        G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION,
+                                               geoclue_example_position_init))
+
+
+static gboolean
+get_status (GcIfaceGeoclue *gc,
+           GeoclueStatus  *status,
+           GError        **error)
+{
+       *status = GEOCLUE_STATUS_AVAILABLE;
+
+       return TRUE;
+}
+
+static void
+print_option (gpointer key,
+              gpointer value,
+              gpointer data)
+{
+        g_print ("   %s - %s\n", key, value);
+}
+
+static gboolean
+set_options (GcIfaceGeoclue *gc,
+             GHashTable     *options,
+             GError        **error)
+{
+        g_print ("Options received---\n");
+        g_hash_table_foreach (options, print_option, NULL);
+        return TRUE;
+}
+
+static void
+shutdown (GcProvider *provider)
+{
+       GeoclueExample *example = GEOCLUE_EXAMPLE (provider);
+
+       g_main_loop_quit (example->loop);
+}
+
+static void
+geoclue_example_class_init (GeoclueExampleClass *klass)
+{
+       GcProviderClass *p_class = (GcProviderClass *) klass;
+
+       p_class->get_status = get_status;
+        p_class->set_options = set_options;
+       p_class->shutdown = shutdown;
+}
+
+static void
+geoclue_example_init (GeoclueExample *example)
+{
+       gc_provider_set_details (GC_PROVIDER (example),
+                                "org.freedesktop.Geoclue.Providers.Example",
+                                "/org/freedesktop/Geoclue/Providers/Example",
+                                "Example", "Example provider");
+}
+
+static gboolean
+get_position (GcIfacePosition       *gc,
+             GeocluePositionFields *fields,
+             int                   *timestamp,
+             double                *latitude,
+             double                *longitude,
+             double                *altitude,
+             GeoclueAccuracy      **accuracy,
+             GError               **error)
+{
+       *timestamp = time (NULL);
+
+       /* We're not emitting location details here because we don't want
+          geoclue to accidently use this as a source */
+       *fields = GEOCLUE_POSITION_FIELDS_NONE;
+       *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0.0, 0.0);
+       return TRUE;
+}
+
+static void
+geoclue_example_position_init (GcIfacePositionClass *iface)
+{
+       iface->get_position = get_position;
+}
+
+static gboolean
+emit_position_signal (gpointer data)
+{
+       GeoclueExample *example = data;
+       GeoclueAccuracy *accuracy;
+
+       accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE,
+                                        0.0, 0.0);
+
+       gc_iface_position_emit_position_changed
+               (GC_IFACE_POSITION (example),
+                GEOCLUE_POSITION_FIELDS_NONE,
+                time (NULL), 0.0, 0.0, 0.0, accuracy);
+
+       geoclue_accuracy_free (accuracy);
+
+       return TRUE;
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+       GeoclueExample *example;
+
+       g_type_init ();
+
+       example = g_object_new (GEOCLUE_TYPE_EXAMPLE, NULL);
+
+       g_timeout_add (5000, emit_position_signal, example);
+
+       example->loop = g_main_loop_new (NULL, TRUE);
+       g_main_loop_run (example->loop);
+
+       return 0;
+}
diff --git a/providers/example/geoclue-example.provider b/providers/example/geoclue-example.provider
new file mode 100755 (executable)
index 0000000..a2d3b05
--- /dev/null
@@ -0,0 +1,7 @@
+[Geoclue Provider]
+Name=Example Provider
+Service=org.freedesktop.Geoclue.Providers.Example
+Path=/org/freedesktop/Geoclue/Providers/Example
+Interfaces=org.freedesktop.Geoclue.Position
+Provides=ProvidesUpdates
+Accuracy=None
diff --git a/providers/example/org.freedesktop.Geoclue.Providers.Example.service.in b/providers/example/org.freedesktop.Geoclue.Providers.Example.service.in
new file mode 100755 (executable)
index 0000000..7531ec4
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Providers.Example
+Exec=@libexecdir@/geoclue-example
diff --git a/providers/geonames/Makefile.am b/providers/geonames/Makefile.am
new file mode 100644 (file)
index 0000000..cf9a683
--- /dev/null
@@ -0,0 +1,35 @@
+libexec_PROGRAMS = \
+       geoclue-geonames
+
+NOINST_H_FILES =               \
+       geoclue-geonames.h
+
+geoclue_geonames_SOURCES =     \
+       $(NOINST_H_FILES)       \
+       geoclue-geonames.c
+
+geoclue_geonames_CFLAGS = \
+       -I$(top_srcdir) \
+       -I$(top_builddir) \
+       $(GEOCLUE_CFLAGS)
+
+geoclue_geonames_LDADD = \
+       $(GEOCLUE_LIBS) \
+       $(top_builddir)/geoclue/libgeoclue.la
+
+providersdir = $(datadir)/geoclue-providers
+providers_DATA = geoclue-geonames.provider
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Providers.Geonames.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+EXTRA_DIST =                   \
+       $(service_in_files)     \
+       $(providers_DATA)
+
+DISTCLEANFILES = \
+       $(service_DATA)
diff --git a/providers/geonames/geoclue-geonames.c b/providers/geonames/geoclue-geonames.c
new file mode 100755 (executable)
index 0000000..db8b28d
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+ * Geoclue
+ * geoclue-geonames.c - A geonames.org-based "Geocode" and
+ *                          "Reverse geocode" provider
+ *
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/*
+ * The used web service APIs are documented at
+ * http://www.geonames.org/export/
+ *
+ * Geonames currently does not support street level geocoding. There
+ * is a street level reverse geocoder in beta, but it's US only.
+ * http://www.geonames.org/export/reverse-geocoding.html
+ */
+
+#include <config.h>
+
+#include <time.h>
+#include <dbus/dbus-glib-bindings.h>
+
+
+#include <geoclue/gc-provider.h>
+#include <geoclue/geoclue-address-details.h>
+#include <geoclue/geoclue-error.h>
+#include <geoclue/gc-iface-geocode.h>
+#include <geoclue/gc-iface-reverse-geocode.h>
+#include "geoclue-geonames.h"
+
+
+#define GEOCLUE_GEONAMES_DBUS_SERVICE "org.freedesktop.Geoclue.Providers.Geonames"
+#define GEOCLUE_GEONAMES_DBUS_PATH "/org/freedesktop/Geoclue/Providers/Geonames"
+
+#define REV_GEOCODE_STREET_URL "http://ws.geonames.org/findNearestAddress"
+#define REV_GEOCODE_PLACE_URL "http://ws.geonames.org/findNearby"
+#define GEOCODE_PLACE_URL "http://ws.geonames.org/search"
+#define GEOCODE_POSTALCODE_URL "http://ws.geonames.org/postalCodeSearch"
+
+#define POSTALCODE_LAT "//geonames/code/lat"
+#define POSTALCODE_LON "//geonames/code/lng"
+
+#define GEONAME_LAT "//geonames/geoname/lat"
+#define GEONAME_LON "//geonames/geoname/lng"
+#define GEONAME_NAME "//geonames/geoname/name"
+#define GEONAME_COUNTRY "//geonames/geoname/countryName"
+#define GEONAME_ADMIN1 "//geonames/geoname/adminName1"
+#define GEONAME_COUNTRYCODE "//geonames/geoname/countryCode"
+#define GEONAME_FEATURE_CLASS "//geonames/geoname/fcl"
+
+#define ADDRESS_STREETNO "//geonames/address/streetNumber"
+#define ADDRESS_STREET "//geonames/address/street"
+#define ADDRESS_POSTALCODE "//geonames/address/postalcode"
+#define ADDRESS_ADMIN2 "//geonames/address/adminName2"
+#define ADDRESS_ADMIN1 "//geonames/address/adminName1"
+#define ADDRESS_COUNTRY "//geonames/geoname/countryName"
+#define ADDRESS_COUNTRYCODE "//geonames/geoname/countryCode"
+
+
+static void geoclue_geonames_init (GeoclueGeonames *obj);
+static void geoclue_geonames_geocode_init (GcIfaceGeocodeClass *iface);
+static void geoclue_geonames_reverse_geocode_init (GcIfaceReverseGeocodeClass *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueGeonames, geoclue_geonames, GC_TYPE_PROVIDER,
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_GEOCODE,
+                                                geoclue_geonames_geocode_init)
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_REVERSE_GEOCODE,
+                                                geoclue_geonames_reverse_geocode_init))
+
+
+/* Geoclue interface implementation */
+
+static gboolean
+geoclue_geonames_get_status (GcIfaceGeoclue *iface,
+                            GeoclueStatus  *status,
+                            GError        **error)
+{
+       /* Assumption that we are available so long as the
+          providers requirements are met: ie network is up */
+       *status = GEOCLUE_STATUS_AVAILABLE;
+
+       return TRUE;
+}
+
+static void
+shutdown (GcProvider *provider)
+{
+       GeoclueGeonames *obj = GEOCLUE_GEONAMES (provider);
+
+       g_main_loop_quit (obj->loop);
+}
+
+
+/* Geocode interface implementation */
+
+static gboolean
+geoclue_geonames_address_to_position (GcIfaceGeocode        *iface,
+                                      GHashTable            *address,
+                                      GeocluePositionFields *fields,
+                                      double                *latitude,
+                                      double                *longitude,
+                                      double                *altitude,
+                                      GeoclueAccuracy      **accuracy,
+                                      GError               **error)
+{
+       GeoclueGeonames *obj = GEOCLUE_GEONAMES (iface);
+       gchar *countrycode, *locality, *postalcode;
+
+       countrycode = g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_COUNTRYCODE);
+       locality = g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_LOCALITY);
+       postalcode = g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_POSTALCODE);
+
+       *fields = GEOCLUE_POSITION_FIELDS_NONE;
+
+       if (countrycode && postalcode) {
+               if (!gc_web_service_query (obj->postalcode_geocoder, error,
+                                          "postalcode", postalcode,
+                                          "country", countrycode,
+                                          "maxRows", "1",
+                                          "style", "FULL",
+                                          (char *)0)) {
+                       return FALSE;
+               }
+               if (gc_web_service_get_double (obj->postalcode_geocoder,
+                                              latitude, POSTALCODE_LAT) &&
+                   gc_web_service_get_double (obj->postalcode_geocoder,
+                                              longitude, POSTALCODE_LON)) {
+                       *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE;
+                       *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE;
+                       *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_POSTALCODE,
+                                                         0, 0);
+               }
+       } else if (countrycode && locality) {
+               if (!gc_web_service_query (obj->place_geocoder, error,
+                                          "name", locality,
+                                          "country", countrycode,
+                                          "maxRows", "1",
+                                          "style", "FULL",
+                                          (char *)0)) {
+                       return FALSE;
+               }
+               if (gc_web_service_get_double (obj->place_geocoder,
+                                              latitude, GEONAME_LAT) &&
+                   gc_web_service_get_double (obj->place_geocoder,
+                                              longitude, GEONAME_LON)) {
+                       *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE;
+                       *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE;
+                       *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_LOCALITY,
+                                                         0, 0);
+               }
+       }
+       if (*accuracy == NULL) {
+               *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0);
+       }
+       return TRUE;
+}
+
+static gboolean
+geoclue_geonames_freeform_address_to_position (GcIfaceGeocode        *iface,
+                                               const char            *address,
+                                               GeocluePositionFields *fields,
+                                               double                *latitude,
+                                               double                *longitude,
+                                               double                *altitude,
+                                               GeoclueAccuracy      **accuracy,
+                                               GError               **error)
+{
+       GeoclueGeonames *obj = GEOCLUE_GEONAMES (iface);
+
+       if (fields) {
+               *fields = GEOCLUE_POSITION_FIELDS_NONE;
+       }
+
+       if (address) {
+               if (!gc_web_service_query (obj->place_geocoder, error,
+                                          "q", address,
+                                          "maxRows", "1",
+                                          "style", "FULL",
+                                          (char *)0)) {
+                       return FALSE;
+               }
+               if (gc_web_service_get_double (obj->place_geocoder,
+                                              latitude, GEONAME_LAT) &&
+                       gc_web_service_get_double (obj->place_geocoder,
+                                                  longitude, GEONAME_LON)) {
+                       if (fields) {
+                               *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE;
+                               *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE;
+                       }
+                       if (accuracy) {
+                               char *fclass = NULL;
+                               GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE;
+
+                               /* this is crude but should cover most results from geonames */
+                               if (gc_web_service_get_string (obj->place_geocoder,
+                                                              &fclass, GEONAME_FEATURE_CLASS)) {
+                                       if (g_strcmp0 (fclass, "A") == 0) {
+                                               level = GEOCLUE_ACCURACY_LEVEL_COUNTRY;
+                                       }else if (g_strcmp0 (fclass, "P") == 0) {
+                                               level = GEOCLUE_ACCURACY_LEVEL_LOCALITY;
+                                       }
+                                       g_free (fclass);
+                               }
+                               *accuracy = geoclue_accuracy_new (level, 0.0, 0.0);
+                       }
+               }
+       }
+
+       if (accuracy && *accuracy == NULL) {
+               *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0.0, 0.0);
+       }
+       return TRUE;
+}
+
+/* ReverseGeocode interface implementation */
+
+static gboolean
+geoclue_geonames_position_to_address (GcIfaceReverseGeocode  *iface,
+                                      double                  latitude,
+                                      double                  longitude,
+                                      GeoclueAccuracy        *position_accuracy,
+                                      GHashTable            **address,
+                                      GeoclueAccuracy       **address_accuracy,
+                                      GError                **error)
+{
+       GeoclueGeonames *obj = GEOCLUE_GEONAMES (iface);
+       gchar lat[G_ASCII_DTOSTR_BUF_SIZE];
+       gchar lon[G_ASCII_DTOSTR_BUF_SIZE];
+       gchar *locality = NULL;
+       gchar *region = NULL;
+       gchar *country = NULL;
+       gchar *countrycode = NULL;
+       GeoclueAccuracyLevel in_acc = GEOCLUE_ACCURACY_LEVEL_DETAILED;
+
+       if (!address) {
+               return TRUE;
+       }
+       g_ascii_dtostr (lat, G_ASCII_DTOSTR_BUF_SIZE, latitude);
+       g_ascii_dtostr (lon, G_ASCII_DTOSTR_BUF_SIZE, longitude);
+       if (!gc_web_service_query (obj->rev_place_geocoder, error,
+                                  "lat", lat,
+                                  "lng", lon,
+                                  "featureCode","PPL",  /* http://www.geonames.org/export/codes.html*/
+                                  "featureCode","PPLA",
+                                  "featureCode","PPLC",
+                                  "featureCode","PPLG",
+                                  "featureCode","PPLL",
+                                  "featureCode","PPLR",
+                                  "featureCode","PPLS",
+                                  "maxRows", "1",
+                                  "style", "FULL",
+                                  (char *)0)) {
+               return FALSE;
+       }
+
+       if (position_accuracy) {
+               geoclue_accuracy_get_details (position_accuracy, &in_acc, NULL, NULL);
+       }
+
+       *address = g_hash_table_new (g_str_hash, g_str_equal);
+
+       if (in_acc >= GEOCLUE_ACCURACY_LEVEL_COUNTRY &&
+           gc_web_service_get_string (obj->rev_place_geocoder,
+                                      &countrycode, GEONAME_COUNTRYCODE)) {
+               geoclue_address_details_insert (*address,
+                                               GEOCLUE_ADDRESS_KEY_COUNTRYCODE,
+                                               countrycode);
+               g_free (countrycode);
+               geoclue_address_details_set_country_from_code (*address);
+       }
+       if (!g_hash_table_lookup (*address, GEOCLUE_ADDRESS_KEY_COUNTRY) &&
+           in_acc >= GEOCLUE_ACCURACY_LEVEL_COUNTRY &&
+           gc_web_service_get_string (obj->rev_place_geocoder,
+                                      &country, GEONAME_COUNTRY)) {
+               geoclue_address_details_insert (*address,
+                                               GEOCLUE_ADDRESS_KEY_COUNTRY,
+                                               country);
+               g_free (country);
+       }
+       if (in_acc >= GEOCLUE_ACCURACY_LEVEL_REGION &&
+           gc_web_service_get_string (obj->rev_place_geocoder,
+                                      &region, GEONAME_ADMIN1)) {
+               geoclue_address_details_insert (*address,
+                                               GEOCLUE_ADDRESS_KEY_REGION,
+                                               region);
+               g_free (region);
+       }
+       if (in_acc >= GEOCLUE_ACCURACY_LEVEL_LOCALITY &&
+           gc_web_service_get_string (obj->rev_place_geocoder,
+                                      &locality, GEONAME_NAME)) {
+               geoclue_address_details_insert (*address,
+                                               GEOCLUE_ADDRESS_KEY_LOCALITY,
+                                               locality);
+               g_free (locality);
+       }
+
+       if (address_accuracy) {
+               GeoclueAccuracyLevel level = geoclue_address_details_get_accuracy_level (*address);
+               *address_accuracy = geoclue_accuracy_new (level, 0.0, 0.0);
+       }
+       return TRUE;
+}
+
+static void
+geoclue_geonames_finalize (GObject *obj)
+{
+       ((GObjectClass *) geoclue_geonames_parent_class)->finalize (obj);
+}
+
+static void
+geoclue_geonames_dispose (GObject *obj)
+{
+       GeoclueGeonames *self = (GeoclueGeonames *) obj;
+
+       if (self->place_geocoder) {
+               g_object_unref (self->place_geocoder);
+               self->place_geocoder = NULL;
+       }
+
+       if (self->postalcode_geocoder) {
+               g_object_unref (self->postalcode_geocoder);
+               self->postalcode_geocoder = NULL;
+       }
+
+       if (self->rev_place_geocoder) {
+               g_object_unref (self->rev_place_geocoder);
+               self->rev_place_geocoder = NULL;
+       }
+
+       if (self->rev_street_geocoder) {
+               g_object_unref (self->rev_street_geocoder);
+               self->rev_street_geocoder = NULL;
+       }
+
+       ((GObjectClass *) geoclue_geonames_parent_class)->dispose (obj);
+}
+
+/* Initialization */
+
+static void
+geoclue_geonames_class_init (GeoclueGeonamesClass *klass)
+{
+       GcProviderClass *p_class = (GcProviderClass *)klass;
+       GObjectClass *o_class = (GObjectClass *)klass;
+
+       p_class->shutdown = shutdown;
+       p_class->get_status = geoclue_geonames_get_status;
+
+       o_class->finalize = geoclue_geonames_finalize;
+       o_class->dispose = geoclue_geonames_dispose;
+}
+
+static void
+geoclue_geonames_init (GeoclueGeonames *obj)
+{
+       gc_provider_set_details (GC_PROVIDER (obj),
+                                GEOCLUE_GEONAMES_DBUS_SERVICE,
+                                GEOCLUE_GEONAMES_DBUS_PATH,
+                                "Geonames", "Geonames provider");
+
+       obj->place_geocoder = g_object_new (GC_TYPE_WEB_SERVICE, NULL);
+       gc_web_service_set_base_url (obj->place_geocoder,
+                                    GEOCODE_PLACE_URL);
+
+       obj->postalcode_geocoder = g_object_new (GC_TYPE_WEB_SERVICE, NULL);
+       gc_web_service_set_base_url (obj->postalcode_geocoder,
+                                    GEOCODE_POSTALCODE_URL);
+
+       obj->rev_place_geocoder = g_object_new (GC_TYPE_WEB_SERVICE, NULL);
+       gc_web_service_set_base_url (obj->rev_place_geocoder,
+                                    REV_GEOCODE_PLACE_URL);
+
+       obj->rev_street_geocoder = g_object_new (GC_TYPE_WEB_SERVICE, NULL);
+       gc_web_service_set_base_url (obj->rev_street_geocoder,
+                                    REV_GEOCODE_STREET_URL);
+}
+
+
+static void
+geoclue_geonames_geocode_init (GcIfaceGeocodeClass *iface)
+{
+       iface->address_to_position = geoclue_geonames_address_to_position;
+       iface->freeform_address_to_position =
+                       geoclue_geonames_freeform_address_to_position;
+}
+
+static void
+geoclue_geonames_reverse_geocode_init (GcIfaceReverseGeocodeClass *iface)
+{
+       iface->position_to_address = geoclue_geonames_position_to_address;
+}
+
+int
+main()
+{
+       GeoclueGeonames *obj;
+
+       g_type_init();
+       obj = g_object_new (GEOCLUE_TYPE_GEONAMES, NULL);
+       obj->loop = g_main_loop_new (NULL, TRUE);
+
+       g_main_loop_run (obj->loop);
+
+       g_main_loop_unref (obj->loop);
+       g_object_unref (obj);
+
+       return 0;
+}
diff --git a/providers/geonames/geoclue-geonames.h b/providers/geonames/geoclue-geonames.h
new file mode 100755 (executable)
index 0000000..3468337
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Geoclue
+ * geoclue-geonames.h - A Geocode/ReverseGeocode provider for geonames.org
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_GEONAMES
+#define _GEOCLUE_GEONAMES
+
+#include <glib-object.h>
+#include <geoclue/gc-web-service.h>
+
+G_BEGIN_DECLS
+
+
+#define GEOCLUE_TYPE_GEONAMES (geoclue_geonames_get_type ())
+
+#define GEOCLUE_GEONAMES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GEONAMES, GeoclueGeonames))
+#define GEOCLUE_GEONAMES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEOCLUE_TYPE_GEONAMES, GeoclueGeonamesClass))
+#define GEOCLUE_IS_GEONAMES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_GEONAMES))
+#define GEOCLUE_IS_GEONAMES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEOCLUE_TYPE_GEONAMES))
+
+typedef struct _GeoclueGeonames {
+       GcProvider parent;
+       GMainLoop *loop;
+
+       GcWebService *place_geocoder;
+       GcWebService *postalcode_geocoder;
+
+       GcWebService *rev_street_geocoder;
+       GcWebService *rev_place_geocoder;
+} GeoclueGeonames;
+
+typedef struct _GeoclueGeonamesClass {
+       GcProviderClass parent_class;
+} GeoclueGeonamesClass;
+
+GType geoclue_geonames_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/providers/geonames/geoclue-geonames.provider b/providers/geonames/geoclue-geonames.provider
new file mode 100755 (executable)
index 0000000..10fc2cc
--- /dev/null
@@ -0,0 +1,7 @@
+[Geoclue Provider]
+Name=Geonames Provider
+Service=org.freedesktop.Geoclue.Providers.Geonames
+Path=/org/freedesktop/Geoclue/Providers/Geonames
+Requires=RequiresNetwork
+Accuracy=Postalcode
+Interfaces=org.freedesktop.Geoclue.Geocode;org.freedesktop.Geoclue.ReverseGeocode
diff --git a/providers/geonames/org.freedesktop.Geoclue.Providers.Geonames.service.in b/providers/geonames/org.freedesktop.Geoclue.Providers.Geonames.service.in
new file mode 100755 (executable)
index 0000000..e4aec5d
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Providers.Geonames
+Exec=@libexecdir@/geoclue-geonames
diff --git a/providers/gpsd/Makefile.am b/providers/gpsd/Makefile.am
new file mode 100644 (file)
index 0000000..7bc900a
--- /dev/null
@@ -0,0 +1,36 @@
+libexec_PROGRAMS = geoclue-gpsd
+
+geoclue_gpsd_CFLAGS =          \
+       -I$(top_srcdir)         \
+       -I$(top_builddir)       \
+       $(GEOCLUE_CFLAGS)       \
+       $(GPSD_CFLAGS)
+
+geoclue_gpsd_LDFLAGS = \
+       -Wl,--warn-unresolved-symbols
+
+geoclue_gpsd_LDADD =           \
+       $(GEOCLUE_LIBS)         \
+       $(GPSD_LIBS)            \
+       -lm                     \
+       $(top_builddir)/geoclue/libgeoclue.la
+
+geoclue_gpsd_SOURCES =         \
+       geoclue-gpsd.c
+
+providersdir = $(datadir)/geoclue-providers
+providers_DATA = geoclue-gpsd.provider
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Providers.Gpsd.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+EXTRA_DIST =                   \
+       $(service_in_files)     \
+       $(providers_DATA)
+
+DISTCLEANFILES = \
+       $(service_DATA)
diff --git a/providers/gpsd/geoclue-gpsd.c b/providers/gpsd/geoclue-gpsd.c
new file mode 100644 (file)
index 0000000..0b23e14
--- /dev/null
@@ -0,0 +1,446 @@
+/*
+ * Geoclue
+ * geoclue-gpsd.c - Geoclue Position backend for gpsd
+ *
+ * Authors: Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* TODO:
+ *
+ *     call to gps_set_callback blocks for a long time if
+ *     BT device is not present.
+ *
+ **/
+
+#include <config.h>
+
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <gps.h>
+
+#include <geoclue/geoclue-error.h>
+#include <geoclue/gc-provider.h>
+#include <geoclue/gc-iface-position.h>
+#include <geoclue/gc-iface-velocity.h>
+
+typedef struct gps_data_t gps_data;
+typedef struct gps_fix_t gps_fix;
+
+/* only listing used tags */
+typedef enum {
+       NMEA_NONE,
+       NMEA_GSA,
+       NMEA_GGA,
+       NMEA_GSV,
+       NMEA_RMC
+} NmeaTag;
+
+typedef struct {
+       GcProvider parent;
+
+       char *host;
+       char *port;
+
+       gps_data *gpsdata;
+
+       gps_fix *last_fix;
+
+       GeoclueStatus last_status;
+       GeocluePositionFields last_pos_fields;
+       GeoclueAccuracy *last_accuracy;
+       GeoclueVelocityFields last_velo_fields;
+
+       GMainLoop *loop;
+} GeoclueGpsd;
+
+typedef struct {
+       GcProviderClass parent_class;
+} GeoclueGpsdClass;
+
+static void geoclue_gpsd_position_init(GcIfacePositionClass * iface);
+static void geoclue_gpsd_velocity_init(GcIfaceVelocityClass * iface);
+
+#define GEOCLUE_TYPE_GPSD (geoclue_gpsd_get_type ())
+#define GEOCLUE_GPSD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GPSD, GeoclueGpsd))
+
+G_DEFINE_TYPE_WITH_CODE(GeoclueGpsd, geoclue_gpsd, GC_TYPE_PROVIDER,
+                       G_IMPLEMENT_INTERFACE(GC_TYPE_IFACE_POSITION, geoclue_gpsd_position_init)
+                       G_IMPLEMENT_INTERFACE(GC_TYPE_IFACE_VELOCITY, geoclue_gpsd_velocity_init))
+
+static void geoclue_gpsd_stop_gpsd(GeoclueGpsd * self);
+static gboolean geoclue_gpsd_start_gpsd(GeoclueGpsd * self);
+
+/* defining global GeoclueGpsd because gpsd does not support "user_data"
+ * pointers in callbacks */
+GeoclueGpsd *gpsd;
+
+/* Geoclue interface */
+static gboolean get_status(GcIfaceGeoclue * gc, GeoclueStatus * status, GError ** error)
+{
+       GeoclueGpsd *gpsd = GEOCLUE_GPSD(gc);
+
+       *status = gpsd->last_status;
+       return TRUE;
+}
+
+static void shutdown(GcProvider * provider)
+{
+       GeoclueGpsd *gpsd = GEOCLUE_GPSD(provider);
+
+       g_main_loop_quit(gpsd->loop);
+}
+
+static void geoclue_gpsd_set_status(GeoclueGpsd * self, GeoclueStatus status)
+{
+       if (status != self->last_status) {
+               self->last_status = status;
+
+               /* make position and velocity invalid if no fix */
+               if (status != GEOCLUE_STATUS_AVAILABLE) {
+                       self->last_pos_fields = GEOCLUE_POSITION_FIELDS_NONE;
+                       self->last_velo_fields = GEOCLUE_VELOCITY_FIELDS_NONE;
+               }
+               g_debug("status changed [%d]", status);
+               gc_iface_geoclue_emit_status_changed(GC_IFACE_GEOCLUE(self), status);
+       }
+}
+
+static gboolean set_options(GcIfaceGeoclue * gc, GHashTable * options, GError ** error)
+{
+       GeoclueGpsd *gpsd = GEOCLUE_GPSD(gc);
+       char *port, *host;
+       gboolean changed = FALSE;
+
+       host = g_hash_table_lookup(options, "org.freedesktop.Geoclue.GPSHost");
+       port = g_hash_table_lookup(options, "org.freedesktop.Geoclue.GPSPort");
+
+       if (port == NULL) {
+               port = DEFAULT_GPSD_PORT;
+       }
+
+       /* new values? */
+       if (g_strcmp0(host, gpsd->host) != 0 || g_strcmp0(port, gpsd->port) != 0) {
+               changed = TRUE;
+       }
+
+       if (!changed) {
+               return TRUE;
+       }
+
+       /* update private values with new ones, restart gpsd */
+       g_free(gpsd->port);
+       gpsd->port = NULL;
+       g_free(gpsd->host);
+       gpsd->host = NULL;
+
+       geoclue_gpsd_stop_gpsd(gpsd);
+
+       if (host == NULL) {
+               return TRUE;
+       }
+
+       gpsd->port = g_strdup(port);
+       gpsd->host = g_strdup(host);
+       if (!geoclue_gpsd_start_gpsd(gpsd)) {
+               geoclue_gpsd_set_status(gpsd, GEOCLUE_STATUS_ERROR);
+               g_set_error(error, GEOCLUE_ERROR, GEOCLUE_ERROR_FAILED, "Gpsd not found");
+               return FALSE;
+       }
+       return TRUE;
+}
+
+static void finalize(GObject * object)
+{
+       GeoclueGpsd *gpsd = GEOCLUE_GPSD(object);
+
+       geoclue_gpsd_stop_gpsd(gpsd);
+       g_free(gpsd->last_fix);
+       geoclue_accuracy_free(gpsd->last_accuracy);
+
+       g_free(gpsd->port);
+       if (gpsd->host) {
+               g_free(gpsd->host);
+       }
+
+       ((GObjectClass *) geoclue_gpsd_parent_class)->finalize(object);
+}
+
+static void geoclue_gpsd_class_init(GeoclueGpsdClass * klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+       GcProviderClass *p_class = (GcProviderClass *) klass;
+
+       o_class->finalize = finalize;
+
+       p_class->get_status = get_status;
+       p_class->set_options = set_options;
+       p_class->shutdown = shutdown;
+}
+
+static gboolean equal_or_nan(double a, double b)
+{
+       if (isnan(a) && isnan(b)) {
+               return TRUE;
+       }
+       return a == b;
+}
+
+static void geoclue_gpsd_update_position(GeoclueGpsd * gpsd)
+{
+       if (gpsd->last_status != GEOCLUE_STATUS_AVAILABLE)
+               return;
+
+       gps_fix *fix = &gpsd->gpsdata->fix;
+       gps_fix *last_fix = gpsd->last_fix;
+
+       if (isnan(fix->time) == 0) {
+               last_fix->time = fix->time;
+       }
+       if (equal_or_nan(fix->latitude, last_fix->latitude) && equal_or_nan(fix->longitude, last_fix->longitude)
+           && equal_or_nan(fix->altitude, last_fix->altitude)) {
+               return;
+       }
+       /* save values */
+       if (fix->mode >= MODE_2D && isnan(fix->latitude) == 0) {
+               last_fix->latitude = fix->latitude;
+       }
+       if (fix->mode >= MODE_2D && isnan(fix->longitude) == 0) {
+               last_fix->longitude = fix->longitude;
+       }
+       if (fix->mode == MODE_3D && isnan(fix->altitude) == 0) {
+               last_fix->altitude = fix->altitude;
+       }
+
+       if (isnan(fix->epx) == 0) {
+               last_fix->epx = fix->epx;
+       }
+       if (isnan(fix->epy) == 0) {
+               last_fix->epy = fix->epy;
+       }
+       if (isnan(fix->epv) == 0) {
+               last_fix->epv = fix->epv;
+       }
+       geoclue_accuracy_set_details(gpsd->last_accuracy,
+                                    GEOCLUE_ACCURACY_LEVEL_DETAILED,
+                                    sqrt(pow(last_fix->epx, 2) + pow(last_fix->epy, 2)), fix->epv);
+       gpsd->last_pos_fields = GEOCLUE_POSITION_FIELDS_NONE;
+       gpsd->last_pos_fields |= (isnan(fix->latitude)) ? 0 : GEOCLUE_POSITION_FIELDS_LATITUDE;
+       gpsd->last_pos_fields |= (isnan(fix->longitude)) ? 0 : GEOCLUE_POSITION_FIELDS_LONGITUDE;
+       gpsd->last_pos_fields |= (isnan(fix->altitude)) ? 0 : GEOCLUE_POSITION_FIELDS_ALTITUDE;
+
+       g_debug
+           ("Update position: %lf, %lf, %lf, fields:0x%x, Accuracy level: %d, hori:%lf vert:%lf",
+            last_fix->latitude, last_fix->longitude, last_fix->altitude,
+            gpsd->last_pos_fields, GEOCLUE_ACCURACY_LEVEL_DETAILED,
+            sqrt(pow(last_fix->epx, 2) + pow(last_fix->epy, 2)), fix->epv);
+       gc_iface_position_emit_position_changed(GC_IFACE_POSITION(gpsd),
+                                               gpsd->last_pos_fields,
+                                               (int)(last_fix->time + 0.5),
+                                               last_fix->latitude,
+                                               last_fix->longitude, last_fix->altitude, gpsd->last_accuracy);
+
+}
+
+static void geoclue_gpsd_update_velocity(GeoclueGpsd * gpsd)
+{
+       if (gpsd->last_status != GEOCLUE_STATUS_AVAILABLE)
+               return;
+
+       gps_fix *fix = &gpsd->gpsdata->fix;
+       gps_fix *last_fix = gpsd->last_fix;
+
+       if (isnan(fix->time) == 0) {
+               last_fix->time = fix->time;
+       }
+       if (equal_or_nan(fix->track, last_fix->track) && equal_or_nan(fix->speed, last_fix->speed)
+           && equal_or_nan(fix->climb, last_fix->climb)) {
+               return;
+       }
+       if (fix->mode >= MODE_2D && isnan(fix->track) == 0) {
+               last_fix->track = fix->track;
+       }
+       if (fix->mode >= MODE_2D && isnan(fix->speed) == 0) {
+               last_fix->speed = fix->speed;
+       }
+       if (fix->mode >= MODE_3D && isnan(fix->climb) == 0) {
+               last_fix->climb = fix->climb;
+       }
+
+       g_debug("Update velocity: %lf, %lf, %lf", last_fix->track, last_fix->speed, last_fix->climb);
+       gpsd->last_velo_fields = GEOCLUE_VELOCITY_FIELDS_NONE;
+       gpsd->last_velo_fields |= (isnan(last_fix->track)) ? 0 : GEOCLUE_VELOCITY_FIELDS_DIRECTION;
+       gpsd->last_velo_fields |= (isnan(last_fix->speed)) ? 0 : GEOCLUE_VELOCITY_FIELDS_SPEED;
+       gpsd->last_velo_fields |= (isnan(last_fix->climb)) ? 0 : GEOCLUE_VELOCITY_FIELDS_CLIMB;
+
+       gc_iface_velocity_emit_velocity_changed
+           (GC_IFACE_VELOCITY(gpsd), gpsd->last_velo_fields,
+            (int)(last_fix->time + 0.5), last_fix->speed, last_fix->track, last_fix->climb);
+}
+
+static void geoclue_gpsd_update_status(GeoclueGpsd * gpsd)
+{
+       GeoclueStatus status;
+
+       /* gpsdata->online is supposedly always up-to-date */
+       if (gpsd->gpsdata->online <= 0) {
+               status = GEOCLUE_STATUS_UNAVAILABLE;
+       } else if (gpsd->gpsdata->set & STATUS_SET) {
+               gpsd->gpsdata->set &= ~(STATUS_SET);
+               if (gpsd->gpsdata->status > 0) {
+                       status = GEOCLUE_STATUS_AVAILABLE;
+               } else {
+                       status = GEOCLUE_STATUS_ACQUIRING;
+               }
+       } else {
+               status = GEOCLUE_STATUS_AVAILABLE;
+               return;
+       }
+
+       geoclue_gpsd_set_status(gpsd, status);
+}
+
+static void gpsd_raw_hook(gps_data * gpsdata, char *message, size_t len)
+{
+       if (gpsdata == NULL)
+               return;
+
+       geoclue_gpsd_update_status(gpsd);
+       geoclue_gpsd_update_position(gpsd);
+       geoclue_gpsd_update_velocity(gpsd);
+}
+
+static void geoclue_gpsd_stop_gpsd(GeoclueGpsd * self)
+{
+       if (self->gpsdata) {
+               gps_close(self->gpsdata);
+               self->gpsdata = NULL;
+       }
+}
+
+static gboolean geoclue_gpsd_start_gpsd(GeoclueGpsd * self)
+{
+       self->gpsdata = gps_open(self->host, self->port);
+       if (self->gpsdata) {
+               gps_stream(self->gpsdata, WATCH_ENABLE | WATCH_NEWSTYLE, NULL);
+               gps_set_raw_hook(self->gpsdata, gpsd_raw_hook);
+               return TRUE;
+       } else {
+               g_warning("gps_open() failed, is gpsd running (host=%s,port=%s)?", self->host, self->port);
+               return FALSE;
+       }
+}
+
+gboolean gpsd_poll(gpointer data)
+{
+       GeoclueGpsd *self = (GeoclueGpsd *) data;
+       if (self->gpsdata) {
+               if (gps_poll(self->gpsdata) < 0) {
+                       geoclue_gpsd_set_status(self, GEOCLUE_STATUS_ERROR);
+                       geoclue_gpsd_stop_gpsd(self);
+                       return FALSE;
+               }
+       }
+       return TRUE;
+}
+
+static void geoclue_gpsd_init(GeoclueGpsd * self)
+{
+       self->gpsdata = NULL;
+       self->last_fix = g_new0(gps_fix, 1);
+
+       self->last_pos_fields = GEOCLUE_POSITION_FIELDS_NONE;
+       self->last_velo_fields = GEOCLUE_VELOCITY_FIELDS_NONE;
+       self->last_accuracy = geoclue_accuracy_new(GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0);
+
+       gc_provider_set_details(GC_PROVIDER(self),
+                               "org.freedesktop.Geoclue.Providers.Gpsd",
+                               "/org/freedesktop/Geoclue/Providers/Gpsd", "Gpsd", "Gpsd provider");
+
+       self->port = g_strdup(DEFAULT_GPSD_PORT);
+       self->host = g_strdup("localhost");
+
+       geoclue_gpsd_set_status(self, GEOCLUE_STATUS_ACQUIRING);
+       if (!geoclue_gpsd_start_gpsd(self)) {
+               geoclue_gpsd_set_status(self, GEOCLUE_STATUS_ERROR);
+       }
+}
+
+static gboolean
+get_position(GcIfacePosition * gc,
+            GeocluePositionFields * fields,
+            int *timestamp,
+            double *latitude, double *longitude, double *altitude, GeoclueAccuracy ** accuracy, GError ** error)
+{
+       GeoclueGpsd *gpsd = GEOCLUE_GPSD(gc);
+
+       *timestamp = (int)(gpsd->last_fix->time + 0.5);
+       *latitude = gpsd->last_fix->latitude;
+       *longitude = gpsd->last_fix->longitude;
+       *altitude = gpsd->last_fix->altitude;
+       *fields = gpsd->last_pos_fields;
+       *accuracy = geoclue_accuracy_copy(gpsd->last_accuracy);
+
+       return TRUE;
+}
+
+static void geoclue_gpsd_position_init(GcIfacePositionClass * iface)
+{
+       iface->get_position = get_position;
+}
+
+static gboolean
+get_velocity(GcIfaceVelocity * gc,
+            GeoclueVelocityFields * fields, int *timestamp, double *speed, double *direction, double *climb, GError ** error)
+{
+       GeoclueGpsd *gpsd = GEOCLUE_GPSD(gc);
+
+       *timestamp = (int)(gpsd->last_fix->time + 0.5);
+       *speed = gpsd->last_fix->speed;
+       *direction = gpsd->last_fix->track;
+       *climb = gpsd->last_fix->climb;
+       *fields = gpsd->last_velo_fields;
+
+       return TRUE;
+}
+
+static void geoclue_gpsd_velocity_init(GcIfaceVelocityClass * iface)
+{
+       iface->get_velocity = get_velocity;
+}
+
+int main(int argc, char **argv)
+{
+       g_type_init();
+
+       gpsd = g_object_new(GEOCLUE_TYPE_GPSD, NULL);
+
+       gpsd->loop = g_main_loop_new(NULL, TRUE);
+       g_timeout_add(500, gpsd_poll, (gpointer) gpsd);
+
+       g_main_loop_run(gpsd->loop);
+
+       g_main_loop_unref(gpsd->loop);
+       g_object_unref(gpsd);
+
+       return 0;
+}
diff --git a/providers/gpsd/geoclue-gpsd.provider b/providers/gpsd/geoclue-gpsd.provider
new file mode 100644 (file)
index 0000000..5391ced
--- /dev/null
@@ -0,0 +1,8 @@
+[Geoclue Provider]
+Name=GPSd
+Service=org.freedesktop.Geoclue.Providers.Gpsd
+Path=/org/freedesktop/Geoclue/Providers/Gpsd
+Requires=RequiresGPS
+Provides=ProvidesUpdates
+Accuracy=Detailed
+Interfaces=org.freedesktop.Geoclue.Position;org.freedesktop.Geoclue.Velocity
diff --git a/providers/gpsd/org.freedesktop.Geoclue.Providers.Gpsd.service.in b/providers/gpsd/org.freedesktop.Geoclue.Providers.Gpsd.service.in
new file mode 100644 (file)
index 0000000..a811876
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Providers.Gpsd
+Exec=@libexecdir@/geoclue-gpsd
diff --git a/providers/gsmloc/Makefile.am b/providers/gsmloc/Makefile.am
new file mode 100644 (file)
index 0000000..1b1e314
--- /dev/null
@@ -0,0 +1,68 @@
+libexec_PROGRAMS =     \
+       geoclue-gsmloc
+
+nodist_geoclue_gsmloc_SOURCES = \
+       ofono-marshal.c \
+       ofono-marshal.h \
+       ofono-manager-bindings.h \
+       ofono-modem-bindings.h \
+       ofono-network-registration-bindings.h \
+       ofono-network-operator-bindings.h
+
+BUILT_SOURCES = \
+       $(nodist_geoclue_gsmloc_SOURCES)
+
+geoclue_gsmloc_SOURCES = \
+       mcc.h \
+       geoclue-gsmloc.c \
+       geoclue-gsmloc-ofono.c \
+       geoclue-gsmloc-ofono.h
+
+
+geoclue_gsmloc_CFLAGS = \
+       -I$(top_srcdir) \
+       -I$(top_builddir) \
+       $(GEOCLUE_CFLAGS)
+
+geoclue_gsmloc_LDADD = \
+       $(GEOCLUE_LIBS) \
+       $(top_builddir)/geoclue/libgeoclue.la
+
+providersdir = $(datadir)/geoclue-providers
+providers_DATA = geoclue-gsmloc.provider
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Providers.Gsmloc.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+EXTRA_DIST =                   \
+       ofono-marshal.list      \
+       ofono-manager.xml \
+       ofono-modem.xml \
+       ofono-network-operator.xml \
+       ofono-network-registration.xml \
+       $(service_in_files)     \
+       $(providers_DATA)
+
+CLEANFILES = \
+       $(BUILT_SOURCES)
+
+DISTCLEANFILES = \
+       $(service_DATA)
+
+%-bindings.h: stamp-%-bindings.h
+       @true
+stamp-%-bindings.h: %.xml
+       $(DBUS_BINDING_TOOL) --mode=glib-client $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
+
+ofono-marshal.h: ofono-marshal.list $(GLIB_GENMARSHAL)
+       $(GLIB_GENMARSHAL) $< --header --prefix=ofono_marshal > $@
+ofono-marshal.c: ofono-marshal.list ofono-marshal.h $(GLIB_GENMARSHAL)
+       echo "#include \"ofono-marshal.h\"" > $@ \
+       && $(GLIB_GENMARSHAL) --prefix=ofono_marshal $(srcdir)/ofono-marshal.list --body >> $@
diff --git a/providers/gsmloc/geoclue-gsmloc-ofono.c b/providers/gsmloc/geoclue-gsmloc-ofono.c
new file mode 100755 (executable)
index 0000000..898e387
--- /dev/null
@@ -0,0 +1,662 @@
+/*
+ * Geoclue
+ * geoclue-gsmloc-ofono.c - oFono abstraction for gsmloc provider
+ *
+ * Author: Jussi Kukkonen <jku@linux.intel.com>
+ * Copyright 2008 by Garmin Ltd. or its subsidiaries
+ *           2010 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib-object.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-bindings.h>
+
+#include "geoclue-gsmloc-ofono.h"
+
+/* generated ofono bindings */
+#include "ofono-marshal.h"
+#include "ofono-manager-bindings.h"
+#include "ofono-modem-bindings.h"
+#include "ofono-network-registration-bindings.h"
+#include "ofono-network-operator-bindings.h"
+
+G_DEFINE_TYPE (GeoclueGsmlocOfono, geoclue_gsmloc_ofono, G_TYPE_OBJECT)
+#define GET_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_GSMLOC_OFONO, GeoclueGsmlocOfonoPrivate))
+
+typedef struct _GeoclueGsmlocOfonoPrivate {
+       DBusGProxy *ofono_manager;
+       GList *modems;
+       gboolean available;
+} GeoclueGsmlocOfonoPrivate;
+
+enum {
+       NETWORK_DATA_CHANGED,
+       LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL] = {0};
+
+enum {
+       PROP_0,
+       PROP_AVAILABLE,
+};
+
+static void emit_network_data_changed (GeoclueGsmlocOfono *ofono);
+
+
+typedef struct _NetOp {
+       GeoclueGsmlocOfono *ofono;
+       DBusGProxy *proxy;
+
+       char *mcc;
+       char *mnc;
+} NetOp;
+
+typedef struct _Modem {
+       GeoclueGsmlocOfono *ofono;
+       DBusGProxy *proxy;
+       DBusGProxy *netreg_proxy;
+       GList *netops;
+
+       char *lac;
+       char *cid;
+} Modem;
+
+static gboolean
+net_op_set_mnc (NetOp *op, const char *mnc)
+{
+       if (g_strcmp0 (op->mnc, mnc) == 0) {
+               return FALSE;
+       }
+
+       g_free (op->mnc);
+       op->mnc = g_strdup (mnc);
+       return TRUE;
+}
+
+static gboolean
+net_op_set_mcc (NetOp *op, const char *mcc)
+{
+       if (g_strcmp0 (op->mcc, mcc) == 0) {
+               return FALSE;
+       }
+
+       g_free (op->mcc);
+       op->mcc = g_strdup (mcc);
+       return TRUE;
+}
+
+static void
+net_op_property_changed_cb (DBusGProxy *proxy,
+                            char *name,
+                            GValue *value,
+                            NetOp *op)
+{
+       if (g_strcmp0 ("MobileNetworkCode", name) == 0) {
+               if (net_op_set_mnc (op, g_value_get_string (value))) {
+                       emit_network_data_changed (op->ofono);
+               }
+       } else if (g_strcmp0 ("MobileCountryCode", name) == 0) {
+               if (net_op_set_mcc (op, g_value_get_string (value))) {
+                       emit_network_data_changed (op->ofono);
+               }
+       }
+}
+
+static void
+net_op_free (NetOp *op)
+{
+       g_free (op->mcc);
+       g_free (op->mnc);
+
+       if (op->proxy) {
+               dbus_g_proxy_disconnect_signal (op->proxy, "PropertyChanged",
+                                               G_CALLBACK (net_op_property_changed_cb),
+                                               op);
+               g_object_unref (op->proxy);
+       }
+
+       g_slice_free (NetOp, op);
+}
+
+static gboolean
+modem_set_lac (Modem *modem, const char *lac)
+{
+       if (g_strcmp0 (modem->lac, lac) == 0) {
+               return FALSE;
+       }
+
+       g_free (modem->lac);
+       modem->lac = g_strdup (lac);
+       return TRUE;
+}
+
+static gboolean
+modem_set_cid (Modem *modem, const char *cid)
+{
+       if (g_strcmp0 (modem->cid, cid) == 0) {
+               return FALSE;
+       }
+
+       g_free (modem->cid);
+       modem->cid = g_strdup (cid);
+       return TRUE;
+}
+
+static void
+get_netop_properties_cb (DBusGProxy *proxy,
+                         GHashTable *props,
+                         GError *error,
+                         NetOp *op)
+{
+       GValue *mnc_val, *mcc_val;
+
+       if (error) {
+               g_warning ("oFono NetworkOperator.GetProperties failed: %s", error->message);
+               g_error_free (error);
+               return;
+       }
+
+       mnc_val = g_hash_table_lookup (props, "MobileNetworkCode");
+       mcc_val = g_hash_table_lookup (props, "MobileCountryCode");
+       if (mnc_val && mcc_val) {
+               gboolean changed;
+               changed = net_op_set_mcc (op, g_value_get_string (mcc_val));
+               changed = net_op_set_mnc (op, g_value_get_string (mnc_val)) || changed;
+
+               if (changed) {
+                       emit_network_data_changed (op->ofono);
+               }
+       }
+}
+
+static void
+modem_set_net_ops (Modem *modem, GPtrArray *ops)
+{
+       int i;
+       GList *list;
+
+       for (list = modem->netops; list; list = list->next) {
+               net_op_free ((NetOp*)list->data);
+       }
+       g_list_free (modem->netops);
+       modem->netops = NULL;
+
+       if (ops->len == 0) {
+               return;
+       }
+
+       for (i = 0; i < ops->len; i++) {
+               const char* op_path;
+               NetOp *op;
+
+               op_path = g_ptr_array_index (ops, i);
+               op = g_slice_new0 (NetOp);
+               op->ofono = modem->ofono;
+               op->proxy = dbus_g_proxy_new_from_proxy (modem->proxy,
+                                                                                                "org.ofono.NetworkOperator",
+                                                                                                op_path);
+               if (!op->proxy) {
+                       g_warning ("failed to find the oFono NetworkOperator '%s'", op_path);
+               } else {
+                       modem->netops = g_list_prepend (modem->netops, op);
+                       org_ofono_NetworkOperator_get_properties_async (op->proxy,
+                                                                                                                       (org_ofono_NetworkOperator_get_properties_reply)get_netop_properties_cb,
+                                                                                                                       op);
+                       dbus_g_proxy_add_signal (op->proxy,"PropertyChanged",
+                                                                        G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID);
+                       dbus_g_proxy_connect_signal (op->proxy, "PropertyChanged",
+                                                                                G_CALLBACK (net_op_property_changed_cb),
+                                                                                op, NULL);
+               }
+       }
+}
+
+static void
+net_reg_get_properties_cb (DBusGProxy *proxy,
+                           GHashTable *props,
+                           GError *error,
+                           Modem *modem)
+{
+       GValue *lac_val, *cid_val, *ops_val;
+
+       if (error) {
+               g_warning ("oFono NetworkRegistration.GetProperties failed: %s", error->message);
+               g_error_free (error);
+               return;
+       }
+
+       lac_val = g_hash_table_lookup (props, "LocationAreaCode");
+       cid_val = g_hash_table_lookup (props, "CellId");
+       ops_val = g_hash_table_lookup (props, "AvailableOperators");
+
+       if (lac_val && cid_val) {
+               gboolean changed;
+               char *str;
+
+               str = g_strdup_printf ("%u", g_value_get_uint (lac_val));
+               changed = modem_set_lac (modem, str);
+               g_free (str);
+               str = g_strdup_printf ("%u", g_value_get_uint (cid_val));
+               changed = modem_set_cid (modem, str) || changed;
+               g_free (str);
+
+               if (changed) {
+                       emit_network_data_changed (modem->ofono);
+               }
+       }
+
+       if (ops_val) {
+               GPtrArray *ops;
+
+               ops = g_value_get_boxed (ops_val);
+               modem_set_net_ops (modem, ops);
+       }
+}
+
+static void
+netreg_property_changed_cb (DBusGProxy *proxy,
+                            char *name,
+                            GValue *value,
+                            Modem *modem)
+{
+       char *str;
+
+       if (g_strcmp0 ("LocationAreaCode", name) == 0) {
+               str = g_strdup_printf ("%u", g_value_get_uint (value));
+               if (modem_set_lac (modem, str)) {
+                       emit_network_data_changed (modem->ofono);
+               }
+               g_free (str);
+       } else if (g_strcmp0 ("CellId", name) == 0) {
+               str = g_strdup_printf ("%u", g_value_get_uint (value));
+               if (modem_set_cid (modem, str)) {
+                       emit_network_data_changed (modem->ofono);
+               }
+               g_free (str);
+       } else if (g_strcmp0 ("AvailableOperators", name) == 0) {
+               modem_set_net_ops (modem, g_value_get_boxed (value));
+       }
+}
+
+static void
+modem_set_net_reg (Modem *modem, gboolean net_reg)
+{
+       GList *netops;
+
+       g_free (modem->cid);
+       modem->cid = NULL;
+       g_free (modem->lac);
+       modem->lac = NULL;
+
+       if (modem->netreg_proxy) {
+               dbus_g_proxy_disconnect_signal (modem->netreg_proxy, "PropertyChanged",
+                                               G_CALLBACK (netreg_property_changed_cb),
+                                               modem);
+               g_object_unref (modem->netreg_proxy);
+               modem->netreg_proxy = NULL;
+       }
+
+       for (netops = modem->netops; netops; netops = netops->next) {
+               net_op_free ((NetOp*)netops->data);
+       }
+       g_list_free (modem->netops);
+       modem->netops = NULL;
+
+       if (net_reg) {
+               modem->netreg_proxy = dbus_g_proxy_new_from_proxy (modem->proxy,
+                                                                  "org.ofono.NetworkRegistration",
+                                                                  dbus_g_proxy_get_path (modem->proxy));
+               if (!modem->netreg_proxy) {
+                       g_warning ("failed to find the oFono NetworkRegistration '%s'",
+                                  dbus_g_proxy_get_path (modem->proxy));
+               } else {
+                       org_ofono_NetworkRegistration_get_properties_async (modem->netreg_proxy,
+                                                                                                                               (org_ofono_NetworkRegistration_get_properties_reply)net_reg_get_properties_cb,
+                                                                                                                               modem);
+                       dbus_g_proxy_add_signal (modem->netreg_proxy,"PropertyChanged",
+                                                                        G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID);
+                       dbus_g_proxy_connect_signal (modem->netreg_proxy, "PropertyChanged",
+                                                                                G_CALLBACK (netreg_property_changed_cb),
+                                                                                modem, NULL);
+               }
+       }
+}
+
+static void
+modem_set_interfaces (Modem *modem, char **ifaces)
+{
+       int i = 0;
+
+       while (ifaces[i]) {
+               if (g_strcmp0 ("org.ofono.NetworkRegistration", ifaces[i]) == 0) {
+                       if (!modem->netreg_proxy) {
+                               modem_set_net_reg (modem, TRUE);
+                       }
+                       return;
+               }
+               i++;
+       }
+       modem_set_net_reg (modem, FALSE);
+}
+
+static void
+modem_property_changed_cb (DBusGProxy *proxy,
+                           char *name,
+                           GValue *value,
+                           Modem *modem)
+{
+       if (g_strcmp0 ("Interfaces", name) == 0) {
+               modem_set_interfaces (modem, g_value_get_boxed (value));
+               emit_network_data_changed (modem->ofono);
+       }
+}
+
+static void
+modem_get_properties_cb (DBusGProxy *proxy,
+                         GHashTable *props,
+                         GError *error,
+                         Modem *modem)
+{
+       GValue *val;
+
+       if (error) {
+               g_warning ("oFono Modem.GetProperties failed: %s", error->message);
+               g_error_free (error);
+               return;
+       }
+
+       val = g_hash_table_lookup (props, "Interfaces");
+       modem_set_interfaces (modem, g_value_get_boxed (val));
+}
+
+static void
+modem_free (Modem *modem)
+{
+       GList *netops;
+
+       g_free (modem->cid);
+       g_free (modem->lac);
+
+       if (modem->netreg_proxy) {
+               dbus_g_proxy_disconnect_signal (modem->netreg_proxy, "PropertyChanged",
+                                               G_CALLBACK (netreg_property_changed_cb),
+                                               modem);
+               g_object_unref (modem->netreg_proxy);
+       }
+
+       if (modem->proxy) {
+               dbus_g_proxy_disconnect_signal (modem->proxy, "PropertyChanged",
+                                               G_CALLBACK (modem_property_changed_cb),
+                                               modem);
+               g_object_unref (modem->proxy);
+       }
+
+       for (netops = modem->netops; netops; netops = netops->next) {
+               net_op_free ((NetOp*)netops->data);
+       }
+       g_list_free (modem->netops);
+
+       g_slice_free (Modem, modem);
+}
+
+
+static void
+emit_network_data_changed (GeoclueGsmlocOfono *ofono)
+{
+       GeoclueGsmlocOfonoPrivate *priv = GET_PRIVATE (ofono);
+       const char *mcc, *mnc, *lac, *cid;
+       GList *modems, *netops;
+
+       mcc = mnc = lac = cid = NULL;
+
+       /* find the first complete cell data we have */
+       for (modems = priv->modems; modems; modems = modems->next) {
+               Modem *modem = (Modem*)modems->data;
+
+               if (modem->lac && modem->cid) {
+                       for (netops = modem->netops; netops; netops = netops->next) {
+                               NetOp *netop = (NetOp*)netops->data;
+
+                               if (netop->mnc && netop->mcc) {
+                                       mcc = netop->mcc;
+                                       mnc = netop->mnc;
+                                       lac = modem->lac;
+                                       cid = modem->cid;
+                                       break;
+                               }
+                       }
+               }
+               if (cid) {
+                       break;
+               }
+       }
+
+       g_signal_emit (ofono, signals[NETWORK_DATA_CHANGED], 0,
+                      mcc, mnc, lac, cid);
+}
+
+
+static void
+geoclue_gsmloc_ofono_set_modems (GeoclueGsmlocOfono *ofono, GPtrArray *modems)
+{
+       GeoclueGsmlocOfonoPrivate *priv = GET_PRIVATE (ofono);
+       int i;
+       GList *mlist;
+
+       /* empty current modem list */
+       for (mlist = priv->modems; mlist; mlist = mlist->next) {
+               modem_free ((Modem*)mlist->data);
+       }
+       g_list_free (priv->modems);
+       priv->modems = NULL;
+
+       if (!modems || modems->len == 0) {
+               return;
+       }
+
+       for (i = 0; i < modems->len; i++) {
+               const char* str;
+               Modem *modem;
+
+               str = (const char*)g_ptr_array_index (modems, i);
+
+               modem = g_slice_new0 (Modem);
+               modem->ofono = ofono;
+               modem->lac = NULL;
+               modem->cid = NULL;
+               modem->proxy = dbus_g_proxy_new_from_proxy (priv->ofono_manager,
+                                                           "org.ofono.Modem",
+                                                           str);
+               if (!modem->proxy) {
+                       g_warning ("failed to find the oFono Modem '%s'", str);
+               } else {
+                       priv->modems = g_list_prepend (priv->modems, modem);
+                       org_ofono_Modem_get_properties_async (modem->proxy,
+                                                             (org_ofono_Manager_get_properties_reply)modem_get_properties_cb,
+                                                             modem);
+                       dbus_g_proxy_add_signal (modem->proxy,"PropertyChanged",
+                                                G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID);
+                       dbus_g_proxy_connect_signal (modem->proxy, "PropertyChanged",
+                                                    G_CALLBACK (modem_property_changed_cb),
+                                                    modem, NULL);
+               }
+       }
+}
+
+
+static void
+geoclue_gsmloc_ofono_get_property (GObject *obj, guint property_id,
+                                   GValue *value, GParamSpec *pspec)
+{
+       GeoclueGsmlocOfono *ofono = GEOCLUE_GSMLOC_OFONO (obj);
+       GeoclueGsmlocOfonoPrivate *priv = GET_PRIVATE (ofono);
+
+       switch (property_id) {
+       case PROP_AVAILABLE:
+               g_value_set_boolean (value, priv->available);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
+       }
+}
+
+static void
+manager_get_properties_cb (DBusGProxy *proxy,
+                           GHashTable *props,
+                           GError *error,
+                           GeoclueGsmlocOfono *ofono)
+{
+       GeoclueGsmlocOfonoPrivate *priv = GET_PRIVATE (ofono);
+       GValue *val;
+       GPtrArray *modems = NULL;
+
+       if (error) {
+               if(error->code != DBUS_GERROR_SERVICE_UNKNOWN) {
+                       g_warning ("oFono Manager.GetProperties failed: %s", error->message);
+               }
+               g_error_free (error);
+               return;
+       }
+
+       val = g_hash_table_lookup (props, "Modems");
+       if (val) {
+               modems = (GPtrArray*)g_value_get_boxed (val);
+       }
+       geoclue_gsmloc_ofono_set_modems (ofono, modems);
+
+       priv->available = TRUE;
+}
+
+static void
+manager_property_changed_cb (DBusGProxy *proxy,
+                             char *name,
+                             GValue *value,
+                             GeoclueGsmlocOfono *ofono)
+{
+       if (g_strcmp0 ("Modems", name) == 0) {
+               GPtrArray *modems;
+
+               modems = (GPtrArray*)g_value_get_boxed (value);
+               geoclue_gsmloc_ofono_set_modems (ofono, modems);
+       }
+}
+
+static void
+geoclue_gsmloc_ofono_dispose (GObject *obj)
+{
+       GeoclueGsmlocOfono *ofono = GEOCLUE_GSMLOC_OFONO (obj);
+       GeoclueGsmlocOfonoPrivate *priv = GET_PRIVATE (ofono);
+       GList *mlist;
+
+       if (priv->ofono_manager) {
+               dbus_g_proxy_disconnect_signal (priv->ofono_manager, "PropertyChanged",
+                                               G_CALLBACK (manager_property_changed_cb),
+                                               ofono);
+               g_object_unref (priv->ofono_manager);
+               priv->ofono_manager = NULL;
+       }
+
+       if (priv->modems) {
+               for (mlist = priv->modems; mlist; mlist = mlist->next) {
+                       modem_free ((Modem*)mlist->data);
+               }
+               g_list_free (priv->modems);
+               priv->modems = NULL;
+       }
+
+       ((GObjectClass *) geoclue_gsmloc_ofono_parent_class)->dispose (obj);
+}
+
+static void
+geoclue_gsmloc_ofono_class_init (GeoclueGsmlocOfonoClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *)klass;
+       GParamSpec *pspec;
+
+       g_type_class_add_private (klass, sizeof (GeoclueGsmlocOfonoPrivate));
+
+       o_class->dispose = geoclue_gsmloc_ofono_dispose;
+       o_class->get_property = geoclue_gsmloc_ofono_get_property;
+
+       dbus_g_object_register_marshaller (ofono_marshal_VOID__STRING_BOXED,
+                                          G_TYPE_NONE,
+                                          G_TYPE_STRING,
+                                          G_TYPE_VALUE,
+                                          G_TYPE_INVALID);
+
+       signals[NETWORK_DATA_CHANGED] = g_signal_new (
+                       "network-data-changed",
+                       G_OBJECT_CLASS_TYPE (klass),
+                       G_SIGNAL_RUN_LAST, 0,
+                       NULL, NULL,
+                       ofono_marshal_VOID__STRING_STRING_STRING_STRING,
+                       G_TYPE_NONE, 4,
+                       G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+       pspec = g_param_spec_boolean ("available",
+                                     "Available",
+                                     "Is oFono available",
+                                     FALSE,
+                                     G_PARAM_READABLE);
+       g_object_class_install_property (o_class, PROP_AVAILABLE, pspec);
+}
+
+static void
+geoclue_gsmloc_ofono_init (GeoclueGsmlocOfono *ofono)
+{
+       GeoclueGsmlocOfonoPrivate *priv = GET_PRIVATE (ofono);
+       DBusGConnection *system_bus;
+
+       priv->modems = NULL;
+       priv->available = FALSE;
+
+       system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
+       if (!system_bus) {
+               g_warning ("failed to connect to DBus system bus");
+               return;
+       }
+
+       priv->ofono_manager =
+           dbus_g_proxy_new_for_name (system_bus,
+                                      "org.ofono",
+                                      "/",
+                                      "org.ofono.Manager");
+
+       org_ofono_Manager_get_properties_async (priv->ofono_manager,
+                                               (org_ofono_Manager_get_properties_reply)manager_get_properties_cb,
+                                               ofono);
+       dbus_g_proxy_add_signal (priv->ofono_manager,"PropertyChanged",
+                                G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID);
+       dbus_g_proxy_connect_signal (priv->ofono_manager, "PropertyChanged",
+                                    G_CALLBACK (manager_property_changed_cb),
+                                    ofono, NULL);
+}
+
+GeoclueGsmlocOfono*
+geoclue_gsmloc_ofono_new (void)
+{
+       return (g_object_new (GEOCLUE_TYPE_GSMLOC_OFONO, NULL));
+}
diff --git a/providers/gsmloc/geoclue-gsmloc-ofono.h b/providers/gsmloc/geoclue-gsmloc-ofono.h
new file mode 100755 (executable)
index 0000000..552e73a
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef _GEOCLUE_GSMLOC_OFONO
+#define _GEOCLUE_GSMLOC_OFONO
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_GSMLOC_OFONO geoclue_gsmloc_ofono_get_type()
+
+#define GEOCLUE_GSMLOC_OFONO(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GSMLOC_OFONO, GeoclueGsmlocOfono))
+
+#define GEOCLUE_GSMLOC_OFONO_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), GEOCLUE_TYPE_GSMLOC_OFONO, GeoclueGsmlocOfonoClass))
+
+#define GEOCLUE_IS_GSMLOC_OFONO(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_GSMLOC_OFONO))
+
+#define GEOCLUE_IS_GSMLOC_OFONO_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), GEOCLUE_TYPE_GSMLOC_OFONO))
+
+#define GEOCLUE_GSMLOC_OFONO_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), GEOCLUE_TYPE_GSMLOC_OFONO, GeoclueGsmlocOfonoClass))
+
+typedef struct {
+  GObject parent;
+} GeoclueGsmlocOfono;
+
+typedef struct {
+  GObjectClass parent_class;
+
+  void (*network_data_changed) (GeoclueGsmlocOfono *ofono,
+                                char *mcc, char *mnc,
+                                char *lac, char *cid);
+} GeoclueGsmlocOfonoClass;
+
+GType geoclue_gsmloc_ofono_get_type (void);
+
+GeoclueGsmlocOfono* geoclue_gsmloc_ofono_new (void);
+
+G_END_DECLS
+
+#endif
diff --git a/providers/gsmloc/geoclue-gsmloc.c b/providers/gsmloc/geoclue-gsmloc.c
new file mode 100644 (file)
index 0000000..4d65b97
--- /dev/null
@@ -0,0 +1,439 @@
+/*
+ * Geoclue
+ * geoclue-gsmloc.c - A GSM cell based Position provider
+ *
+ * Author: Jussi Kukkonen <jku@linux.intel.com>
+ * Copyright 2008 by Garmin Ltd. or its subsidiaries
+ *           2010 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+ /**
+  * Gsmloc provider is a position and address provider that uses GSM cell
+  * location and the webservice http://www.opencellid.org/ (a similar service
+  * used to live at gsmloc.org, hence the name). The web service does not
+  * provide any address data: that is done with a
+  * "mobile country code -> ISO country code" lookup table: as a result address
+  * will only ever have country code and country fields.
+  *
+  * Gsmloc requires the telephony stack oFono to work -- more IMSI data
+  * sources could be added fairly easily.
+  **/
+
+#include <config.h>
+
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib-object.h>
+#include <dbus/dbus-glib-bindings.h>
+
+#include <geoclue/gc-web-service.h>
+#include <geoclue/gc-provider.h>
+#include <geoclue/geoclue-error.h>
+#include <geoclue/gc-iface-position.h>
+#include <geoclue/gc-iface-address.h>
+
+/* ofono implementation */
+#include "geoclue-gsmloc-ofono.h"
+
+/* country code list */
+#include "mcc.h"
+
+#define GEOCLUE_DBUS_SERVICE_GSMLOC "org.freedesktop.Geoclue.Providers.Gsmloc"
+#define GEOCLUE_DBUS_PATH_GSMLOC "/org/freedesktop/Geoclue/Providers/Gsmloc"
+
+#define OPENCELLID_URL "http://www.opencellid.org/cell/get"
+#define OPENCELLID_LAT "/rsp/cell/@lat"
+#define OPENCELLID_LON "/rsp/cell/@lon"
+#define OPENCELLID_CID "/rsp/cell/@cellId"
+
+#define GEOCLUE_TYPE_GSMLOC (geoclue_gsmloc_get_type ())
+#define GEOCLUE_GSMLOC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GSMLOC, GeoclueGsmloc))
+
+typedef struct _GeoclueGsmloc GeoclueGsmloc;
+
+struct _GeoclueGsmloc {
+       GcProvider parent;
+       GMainLoop *loop;
+       GcWebService *web_service;
+
+       GeoclueGsmlocOfono *ofono;
+
+       /* current data */
+       char *mcc;
+       char *mnc;
+       char *lac;
+       char *cid;
+       GeocluePositionFields last_position_fields;
+       GeoclueAccuracyLevel last_accuracy_level;
+       double last_lat;
+       double last_lon;
+
+       GHashTable *address;
+};
+
+typedef struct _GeoclueGsmlocClass {
+       GcProviderClass parent_class;
+} GeoclueGsmlocClass;
+
+
+static void geoclue_gsmloc_init (GeoclueGsmloc *gsmloc);
+static void geoclue_gsmloc_position_init (GcIfacePositionClass  *iface);
+static void geoclue_gsmloc_address_init (GcIfaceAddressClass  *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueGsmloc, geoclue_gsmloc, GC_TYPE_PROVIDER,
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION,
+                                                geoclue_gsmloc_position_init)
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS,
+                                                geoclue_gsmloc_address_init))
+
+
+/* Geoclue interface implementation */
+static gboolean
+geoclue_gsmloc_get_status (GcIfaceGeoclue *iface,
+                          GeoclueStatus  *status,
+                          GError        **error)
+{
+       GeoclueGsmloc *gsmloc = GEOCLUE_GSMLOC (iface);
+       gboolean ofono_available;
+
+       g_object_get (gsmloc->ofono, "available", &ofono_available, NULL);
+
+       if (!ofono_available) {
+               *status = GEOCLUE_STATUS_ERROR;
+       } else if (!gsmloc->mcc || !gsmloc->mnc ||
+                  !gsmloc->lac || !gsmloc->cid) {
+               *status = GEOCLUE_STATUS_UNAVAILABLE;
+       } else {
+               *status = GEOCLUE_STATUS_AVAILABLE;
+       }
+       return TRUE;
+}
+
+static void
+shutdown (GcProvider *provider)
+{
+       GeoclueGsmloc *gsmloc = GEOCLUE_GSMLOC (provider);
+       g_main_loop_quit (gsmloc->loop);
+}
+
+static gboolean
+geoclue_gsmloc_query_opencellid (GeoclueGsmloc *gsmloc)
+{
+       double lat, lon;
+       GeocluePositionFields fields = GEOCLUE_POSITION_FIELDS_NONE;
+       GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE;
+
+       if (gsmloc->mcc && gsmloc->mnc &&
+           gsmloc->lac && gsmloc->cid) {
+
+               if (gc_web_service_query (gsmloc->web_service, NULL,
+                                         "mcc", gsmloc->mcc,
+                                         "mnc", gsmloc->mnc,
+                                         "lac", gsmloc->lac,
+                                         "cellid", gsmloc->cid,
+                                         (char *)0)) {
+
+                       if (gc_web_service_get_double (gsmloc->web_service,
+                                                      &lat, OPENCELLID_LAT)) {
+                               fields |= GEOCLUE_POSITION_FIELDS_LATITUDE;
+                       }
+                       if (gc_web_service_get_double (gsmloc->web_service,
+                                                      &lon, OPENCELLID_LON)) {
+                               fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE;
+                       }
+
+                       if (fields != GEOCLUE_POSITION_FIELDS_NONE) {
+                               char *retval_cid;
+                               /* if cellid is not present, location is for the local area code.
+                                * the accuracy might be an overstatement -- I have no idea how
+                                * big LACs typically are */
+                               level = GEOCLUE_ACCURACY_LEVEL_LOCALITY;
+                               if (gc_web_service_get_string (gsmloc->web_service,
+                                                              &retval_cid, OPENCELLID_CID)) {
+                                       if (retval_cid && strlen (retval_cid) != 0) {
+                                               level = GEOCLUE_ACCURACY_LEVEL_POSTALCODE;
+                                       }
+                                       g_free (retval_cid);
+                               }
+                       }
+               }
+       }
+
+       if (fields != gsmloc->last_position_fields ||
+           (fields != GEOCLUE_POSITION_FIELDS_NONE &&
+            (lat != gsmloc->last_lat ||
+             lon != gsmloc->last_lon ||
+             level != gsmloc->last_accuracy_level))) {
+               GeoclueAccuracy *acc;
+
+               /* position changed */
+
+               gsmloc->last_position_fields = fields;
+               gsmloc->last_accuracy_level = level;
+               gsmloc->last_lat = lat;
+               gsmloc->last_lon = lon;
+
+               acc = geoclue_accuracy_new (gsmloc->last_accuracy_level, 0.0, 0.0);
+               gc_iface_position_emit_position_changed (GC_IFACE_POSITION (gsmloc),
+                                                        fields,
+                                                        time (NULL),
+                                                        lat, lon, 0.0,
+                                                        acc);
+               geoclue_accuracy_free (acc);
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static void
+geoclue_gsmloc_update_address (GeoclueGsmloc *gsmloc)
+{
+       char *countrycode = NULL;
+       const char *old_countrycode;
+       gboolean changed = FALSE;
+       GeoclueAccuracy *acc;
+
+       if (gsmloc->mcc) {
+               gint64 i;
+               i = g_ascii_strtoll (gsmloc->mcc, NULL, 10);
+               if (i > 0 && i < 800 && mcc_country_codes[i]) {
+                       countrycode = mcc_country_codes[i];
+               }
+       }
+
+       old_countrycode = g_hash_table_lookup (gsmloc->address,
+                                              GEOCLUE_ADDRESS_KEY_COUNTRYCODE);
+       if (g_strcmp0 (old_countrycode, countrycode) != 0) {
+               changed = TRUE;
+       }
+
+       if (countrycode) {
+               g_hash_table_insert (gsmloc->address,
+                                    GEOCLUE_ADDRESS_KEY_COUNTRYCODE, g_strdup (countrycode));
+               acc = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_COUNTRY, 0.0, 0.0);
+       } else {
+               g_hash_table_remove (gsmloc->address, GEOCLUE_ADDRESS_KEY_COUNTRYCODE);
+               g_hash_table_remove (gsmloc->address, GEOCLUE_ADDRESS_KEY_COUNTRY);
+               acc = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0.0, 0.0);
+       }
+       geoclue_address_details_set_country_from_code (gsmloc->address);
+
+       if (changed) {
+               gc_iface_address_emit_address_changed (GC_IFACE_ADDRESS (gsmloc),
+                                                      time (NULL),
+                                                      gsmloc->address,
+                                                      acc);
+
+       }
+       geoclue_accuracy_free (acc);
+}
+static void
+geoclue_gsmloc_set_cell (GeoclueGsmloc *gsmloc,
+                         const char *mcc, const char *mnc,
+                         const char *lac, const char *cid)
+{
+       g_free (gsmloc->mcc);
+       g_free (gsmloc->mnc);
+       g_free (gsmloc->lac);
+       g_free (gsmloc->cid);
+
+       gsmloc->mcc = g_strdup (mcc);
+       gsmloc->mnc = g_strdup (mnc);
+       gsmloc->lac = g_strdup (lac);
+       gsmloc->cid = g_strdup (cid);
+
+       geoclue_gsmloc_update_address (gsmloc);
+       geoclue_gsmloc_query_opencellid (gsmloc);
+}
+
+static void
+network_data_changed_cb (gpointer connection_manager,
+                         const char *mcc, const char *mnc,
+                         const char *lac, const char *cid,
+                         GeoclueGsmloc *gsmloc)
+{
+       if (g_strcmp0 (mcc, gsmloc->mcc) != 0 ||
+           g_strcmp0 (mnc, gsmloc->mnc) != 0 ||
+           g_strcmp0 (lac, gsmloc->lac) != 0 ||
+           g_strcmp0 (cid, gsmloc->cid) != 0) {
+
+               /* new cell data, do a opencellid lookup */
+               geoclue_gsmloc_set_cell (gsmloc, mcc, mnc, lac, cid);
+       }
+}
+
+/* Position interface implementation */
+
+static gboolean
+geoclue_gsmloc_get_position (GcIfacePosition        *iface,
+                             GeocluePositionFields  *fields,
+                             int                    *timestamp,
+                             double                 *latitude,
+                             double                 *longitude,
+                             double                 *altitude,
+                             GeoclueAccuracy       **accuracy,
+                             GError                **error)
+{
+       GeoclueGsmloc *gsmloc;
+
+       gsmloc = (GEOCLUE_GSMLOC (iface));
+
+       if (gsmloc->last_position_fields == GEOCLUE_POSITION_FIELDS_NONE) {
+               /* re-query in case there was a network problem */
+               geoclue_gsmloc_query_opencellid (gsmloc);
+       }
+
+       if (timestamp) {
+               *timestamp = time (NULL);
+       }
+
+       if (fields) {
+               *fields = gsmloc->last_position_fields;
+       }
+       if (latitude) {
+               *latitude = gsmloc->last_lat;
+       }
+       if (longitude) {
+               *longitude = gsmloc->last_lon;
+       }
+       if (accuracy) {
+               *accuracy = geoclue_accuracy_new (gsmloc->last_accuracy_level, 0, 0);
+       }
+
+       return TRUE;
+}
+
+/* Address interface implementation */
+static gboolean
+geoclue_gsmloc_get_address (GcIfaceAddress   *iface,
+                            int              *timestamp,
+                            GHashTable      **address,
+                            GeoclueAccuracy **accuracy,
+                            GError          **error)
+{
+       GeoclueGsmloc *obj = GEOCLUE_GSMLOC (iface);
+
+       if (address) {
+               *address = geoclue_address_details_copy (obj->address);
+       }
+       if (accuracy) {
+               GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE;
+               if (g_hash_table_lookup (obj->address, GEOCLUE_ADDRESS_KEY_COUNTRY)) {
+                       level = GEOCLUE_ACCURACY_LEVEL_COUNTRY;
+               }
+               *accuracy = geoclue_accuracy_new (level, 0.0, 0.0);
+       }
+       if (timestamp) {
+               *timestamp = time (NULL);
+       }
+
+       return TRUE;
+}
+
+
+static void
+geoclue_gsmloc_dispose (GObject *obj)
+{
+       GeoclueGsmloc *gsmloc = GEOCLUE_GSMLOC (obj);
+
+       if (gsmloc->ofono) {
+               g_signal_handlers_disconnect_by_func (gsmloc->ofono,
+                                                     network_data_changed_cb,
+                                                     gsmloc);
+               g_object_unref (gsmloc->ofono);
+               gsmloc->ofono = NULL;
+       }
+
+       if (gsmloc->address) {
+               g_hash_table_destroy (gsmloc->address);
+               gsmloc->address = NULL;
+       }
+
+       ((GObjectClass *) geoclue_gsmloc_parent_class)->dispose (obj);
+}
+
+
+/* Initialization */
+
+static void
+geoclue_gsmloc_class_init (GeoclueGsmlocClass *klass)
+{
+       GcProviderClass *p_class = (GcProviderClass *)klass;
+       GObjectClass *o_class = (GObjectClass *)klass;
+
+       p_class->shutdown = shutdown;
+       p_class->get_status = geoclue_gsmloc_get_status;
+
+       o_class->dispose = geoclue_gsmloc_dispose;
+}
+
+static void
+geoclue_gsmloc_init (GeoclueGsmloc *gsmloc)
+{
+       gsmloc->address = geoclue_address_details_new ();
+
+       gc_provider_set_details (GC_PROVIDER (gsmloc),
+                                GEOCLUE_DBUS_SERVICE_GSMLOC,
+                                GEOCLUE_DBUS_PATH_GSMLOC,
+                                "Gsmloc", "GSM cell based position provider");
+
+       gsmloc->web_service = g_object_new (GC_TYPE_WEB_SERVICE, NULL);
+       gc_web_service_set_base_url (gsmloc->web_service, OPENCELLID_URL);
+
+       geoclue_gsmloc_set_cell (gsmloc, NULL, NULL, NULL, NULL);
+
+       gsmloc->address = geoclue_address_details_new ();
+
+       /* init ofono*/
+       gsmloc->ofono = geoclue_gsmloc_ofono_new ();
+       g_signal_connect (gsmloc->ofono, "network-data-changed",
+                         G_CALLBACK (network_data_changed_cb), gsmloc);
+}
+
+static void
+geoclue_gsmloc_position_init (GcIfacePositionClass  *iface)
+{
+       iface->get_position = geoclue_gsmloc_get_position;
+}
+
+static void
+geoclue_gsmloc_address_init (GcIfaceAddressClass  *iface)
+{
+       iface->get_address = geoclue_gsmloc_get_address;
+}
+
+int
+main()
+{
+       g_type_init();
+
+       GeoclueGsmloc *o = g_object_new (GEOCLUE_TYPE_GSMLOC, NULL);
+       o->loop = g_main_loop_new (NULL, TRUE);
+
+       g_main_loop_run (o->loop);
+
+       g_main_loop_unref (o->loop);
+       g_object_unref (o);
+
+       return 0;
+}
diff --git a/providers/gsmloc/geoclue-gsmloc.provider b/providers/gsmloc/geoclue-gsmloc.provider
new file mode 100755 (executable)
index 0000000..921990b
--- /dev/null
@@ -0,0 +1,8 @@
+[Geoclue Provider]
+Name=Gsmloc
+Service=org.freedesktop.Geoclue.Providers.Gsmloc
+Path=/org/freedesktop/Geoclue/Providers/Gsmloc
+Accuracy=Postalcode
+Requires=RequiresNetwork, RequiresCell
+Provides=ProvidesUpdates
+Interfaces=org.freedesktop.Geoclue.Position, org.freedesktop.Geoclue.Address
diff --git a/providers/gsmloc/mcc.h b/providers/gsmloc/mcc.h
new file mode 100755 (executable)
index 0000000..f860cf2
--- /dev/null
@@ -0,0 +1,494 @@
+/* Mobile country code list from
+ * "LIST OF MOBILE COUNTRY OR GEOGRAPHICAL AREA CODES"
+ * (http://www.itu.int/publ/T-SP-E.212A-2007)
+ * combined with ISO 3166-1 alpha-2 list for two letter country codes
+ */
+
+char *mcc_country_codes[] = {
+       NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 100 */
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 200 */
+       NULL,
+       NULL,
+       NULL,
+       "NL",
+       NULL,
+       "BE",
+       NULL,
+       "FR",
+       NULL,
+       NULL,
+       NULL,
+       "MC",
+       "AD",
+       "ES",
+       NULL,
+       "HU",
+       NULL,
+       "BA",
+       "HR",
+       "RS",
+       NULL,
+       "IT",
+       NULL,
+       NULL,
+       "VA",
+       "RO",
+       NULL,
+       "CH",
+       NULL,
+       "CZ",
+       "SK",
+       "AT",
+       NULL,
+       "GB",
+       "GB",
+       NULL,
+       NULL,
+       "DK",
+       NULL,
+       "SE",
+       NULL,
+       "NO",
+       NULL,
+       "FI",
+       NULL,
+       "LT",
+       "LV",
+       "EE",
+       NULL,
+       "RU",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "UA",
+       NULL,
+       "BY",
+       NULL,
+       "MD",
+       "PL",
+       NULL,
+       "DE",
+       NULL,
+       NULL,
+       NULL,
+       "GI",
+       NULL,
+       "PT",
+       NULL,
+       "LU",
+       NULL,
+       "IE",
+       NULL,
+       "IS",
+       NULL,
+       "AL",
+       NULL,
+       "MT",
+       NULL,
+       "CY",
+       NULL,
+       "GE",
+       "AM",
+       "BG",
+       NULL,
+       "TR",
+       NULL,
+       "FO",
+       NULL,
+       "GL",
+       NULL,
+       "SM",
+       "SI",
+       "MK",
+       "LI",
+       NULL,
+       "ME",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "CA",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "PM",
+       NULL,
+       "US",
+       "US",
+       "US",
+       "US",
+       "US",
+       "US",
+       "US",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "PR",
+       NULL,
+       "VI",
+       NULL,
+       "MX",
+       NULL,
+       NULL,
+       NULL,
+       "JM",
+       NULL,
+       "MQ",
+       NULL,
+       "BB",
+       NULL,
+       "AG",
+       NULL,
+       "KY",
+       NULL,
+       "VG",
+       NULL,
+       "BM",
+       NULL,
+       "GD",
+       NULL,
+       "MS",
+       NULL,
+       "KN",
+       NULL,
+       "LC",
+       NULL,
+       "VC",
+       NULL,
+       "AN",
+       "AW",
+       "BS",
+       "AI",
+       "DM",
+       NULL,
+       "CU",
+       NULL,
+       "DO",
+       NULL,
+       "HT",
+       NULL,
+       "TT",
+       NULL,
+       "TC",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "AZ",
+       "KZ",
+       "BT",
+       NULL,
+       "IN",
+       "IN",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "PK",
+       NULL,
+       "AF",
+       "LK",
+       "MM",
+       "LB",
+       "JO",
+       "SY",
+       "IQ",
+       "KW",
+       "SA",
+       "YE",
+       "OM",
+       NULL,
+       "AE",
+       "IL",
+       "BH",
+       "QA",
+       "MN",
+       "NP",
+       "AE",
+       "AE",
+       "IR",
+       NULL,
+       "UZ",
+       NULL,
+       "TJ",
+       "KG",
+       "TM",
+       NULL,
+       "JP",
+       "JP",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "KR",
+       NULL,
+       "VN",
+       NULL,
+       "HK",
+       "MO",
+       "KH",
+       "LA",
+       NULL,
+       NULL,
+       "CN",
+       "CN",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "TW",
+       "KP",
+       NULL,
+       NULL,
+       "BD",
+       NULL,
+       "MV",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 500 */
+       NULL,
+       "MY",
+       NULL,
+       NULL,
+       "AU",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "ID",
+       NULL,
+       NULL,
+       NULL,
+       "TL",
+       "PH",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "TH",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "SG",
+       NULL,
+       NULL,
+       "BN",
+       NULL,
+       "NZ",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "NR",
+       "PG",
+       NULL,
+       "TO",
+       "SB",
+       "VU",
+       "FJ",
+       "WF",
+       "AS",
+       "KI",
+       "NC",
+       "PF",
+       "CK",
+       "WS",
+       "FM",
+       "MH",
+       "PW",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 600 */
+       NULL,
+       "EG",
+       "DZ",
+       "MA",
+       "TN",
+       "LY",
+       "GM",
+       "SN",
+       "MR",
+       "ML",
+       "GN",
+       "CI",
+       "BF",
+       "NE",
+       "TG",
+       "BJ",
+       "MU",
+       "LR",
+       "SL",
+       "GH",
+       "NG",
+       "TD",
+       "CF",
+       "CM",
+       "CV",
+       "ST",
+       "GQ",
+       "GA",
+       "CG",
+       "CD",
+       "AO",
+       "GW",
+       "SC",
+       "SD",
+       "RW",
+       "ET",
+       "SO",
+       "DJ",
+       "KE",
+       "TZ",
+       "UG",
+       "BI",
+       "MZ",
+       NULL,
+       "ZM",
+       "MG",
+       "TF",
+       "ZW",
+       "NA",
+       "MW",
+       "LS",
+       "BW",
+       "SZ",
+       "KM",
+       "ZA",
+       NULL,
+       "ER",
+       NULL,
+       NULL,
+       NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 700 */
+       NULL,
+       "BZ",
+       NULL,
+       "GT",
+       NULL,
+       "SV",
+       NULL,
+       "HN",
+       NULL,
+       "NI",
+       NULL,
+       "CR",
+       NULL,
+       "PA",
+       NULL,
+       "PE",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "AR",
+       NULL,
+       "BR",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "CL",
+       NULL,
+       "CO",
+       NULL,
+       "VE",
+       NULL,
+       "BO",
+       NULL,
+       "GY",
+       NULL,
+       "EC",
+       NULL,
+       "GF",
+       NULL,
+       "PY",
+       NULL,
+       "SR",
+       NULL,
+       "UY",
+       NULL,
+       "FK",
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 799 */
+};
diff --git a/providers/gsmloc/ofono-manager.xml b/providers/gsmloc/ofono-manager.xml
new file mode 100755 (executable)
index 0000000..3b92411
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node name="/" >
+       <interface name="org.ofono.Manager">
+               <method name="GetProperties">
+                       <arg type="a{sv}" direction="out"/>
+               </method>
+               <signal name="PropertyChanged">
+                       <arg type="s"/>
+                       <arg type="v"/>
+               </signal>
+       </interface>
+</node>
diff --git a/providers/gsmloc/ofono-marshal.list b/providers/gsmloc/ofono-marshal.list
new file mode 100755 (executable)
index 0000000..5d5d8c4
--- /dev/null
@@ -0,0 +1,2 @@
+VOID:STRING,BOXED
+VOID:STRING,STRING,STRING,STRING
diff --git a/providers/gsmloc/ofono-modem.xml b/providers/gsmloc/ofono-modem.xml
new file mode 100755 (executable)
index 0000000..b4d59d5
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node name="/">
+       <interface name="org.ofono.Modem">
+               <method name="GetProperties">
+                       <arg type="a{sv}" direction="out"/>
+               </method>
+               <method name="SetProperty">
+                       <arg type="s" direction="in"/>
+                       <arg type="v" direction="in"/>
+               </method>
+               <signal name="PropertyChanged">
+                       <arg type="s"/>
+                       <arg type="v"/>
+               </signal>
+       </interface>
+</node>
diff --git a/providers/gsmloc/ofono-network-operator.xml b/providers/gsmloc/ofono-network-operator.xml
new file mode 100755 (executable)
index 0000000..ae95478
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node name="/">
+       <interface name="org.ofono.NetworkOperator">
+               <method name="GetProperties">
+                       <arg type="a{sv}" direction="out"/>
+               </method>
+               <method name="Register"/>
+               <signal name="PropertyChanged">
+                       <arg type="s"/>
+                       <arg type="v"/>
+               </signal>
+       </interface>
+</node>
+
diff --git a/providers/gsmloc/ofono-network-registration.xml b/providers/gsmloc/ofono-network-registration.xml
new file mode 100755 (executable)
index 0000000..21a86ec
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node name="/">
+       <interface name="org.ofono.NetworkRegistration">
+               <method name="GetProperties">
+                       <arg type="a{sv}" direction="out"/>
+               </method>
+               <method name="Register"/>
+               <method name="Deregister"/>
+               <method name="ProposeScan">
+                       <arg type="ao" direction="out"/>
+               </method>
+               <signal name="PropertyChanged">
+                       <arg type="s"/>
+                       <arg type="v"/>
+               </signal>
+       </interface>
+</node>
+
diff --git a/providers/gsmloc/org.freedesktop.Geoclue.Providers.Gsmloc.service.in b/providers/gsmloc/org.freedesktop.Geoclue.Providers.Gsmloc.service.in
new file mode 100755 (executable)
index 0000000..3be587c
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Providers.Gsmloc
+Exec=@libexecdir@/geoclue-gsmloc
diff --git a/providers/gypsy/Makefile.am b/providers/gypsy/Makefile.am
new file mode 100644 (file)
index 0000000..4fef42e
--- /dev/null
@@ -0,0 +1,32 @@
+libexec_PROGRAMS = geoclue-gypsy
+
+geoclue_gypsy_CFLAGS =         \
+       -I$(top_srcdir)         \
+       -I$(top_builddir)       \
+       $(GEOCLUE_CFLAGS)       \
+       $(GYPSY_CFLAGS)
+
+geoclue_gypsy_LDADD =          \
+       $(GEOCLUE_LIBS)         \
+       $(GYPSY_LIBS)           \
+       $(top_builddir)/geoclue/libgeoclue.la
+
+geoclue_gypsy_SOURCES =                \
+       geoclue-gypsy.c
+
+providersdir = $(datadir)/geoclue-providers
+providers_DATA = geoclue-gypsy.provider
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Providers.Gypsy.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+EXTRA_DIST =                   \
+       $(service_in_files)     \
+       $(providers_DATA)
+
+DISTCLEANFILES = \
+       $(service_DATA)
diff --git a/providers/gypsy/geoclue-gypsy.c b/providers/gypsy/geoclue-gypsy.c
new file mode 100644 (file)
index 0000000..4ebae94
--- /dev/null
@@ -0,0 +1,591 @@
+/*
+ * Geoclue
+ * geoclue-gypsy.c - Geoclue backend for Gypsy which provides the Position.
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <gypsy/gypsy-control.h>
+#include <gypsy/gypsy-device.h>
+#include <gypsy/gypsy-position.h>
+#include <gypsy/gypsy-course.h>
+#include <gypsy/gypsy-accuracy.h>
+
+#include <geoclue/gc-provider.h>
+#include <geoclue/gc-iface-position.h>
+#include <geoclue/gc-iface-velocity.h>
+
+typedef struct {
+       GcProvider parent;
+
+        char *device_name;
+
+       GypsyControl *control;
+       GypsyDevice *device;
+       GypsyPosition *position;
+       GypsyCourse *course;
+       GypsyAccuracy *acc;
+
+       GMainLoop *loop;
+
+       int timestamp;
+
+       GeoclueStatus status;
+
+       /* Cached so we don't have to make D-Bus method calls all the time */
+       GypsyPositionFields position_fields;
+       double latitude;
+       double longitude;
+       double altitude;
+
+       GypsyCourseFields course_fields;
+       double speed;
+       double direction;
+       double climb;
+
+       GeoclueAccuracy *accuracy;
+} GeoclueGypsy;
+
+typedef struct {
+       GcProviderClass parent_class;
+} GeoclueGypsyClass;
+
+static void geoclue_gypsy_position_init (GcIfacePositionClass *iface);
+static void geoclue_gypsy_velocity_init (GcIfaceVelocityClass *iface);
+
+#define GEOCLUE_TYPE_GYPSY (geoclue_gypsy_get_type ())
+#define GEOCLUE_GYPSY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GYPSY, GeoclueGypsy))
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueGypsy, geoclue_gypsy, GC_TYPE_PROVIDER,
+                        G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION,
+                                               geoclue_gypsy_position_init)
+                        G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_VELOCITY,
+                                               geoclue_gypsy_velocity_init))
+
+
+/* GcIfaceGeoclue methods */
+
+static gboolean
+get_status (GcIfaceGeoclue *gc,
+            GeoclueStatus  *status,
+            GError        **error)
+{
+       GeoclueGypsy *gypsy = GEOCLUE_GYPSY (gc);
+
+       *status = gypsy->status;
+
+        return TRUE;
+}
+
+
+/* Compare the two fields and return TRUE if they have changed */
+static gboolean
+compare_field (GypsyPositionFields fields_a,
+              double              value_a,
+              GypsyPositionFields fields_b,
+              double              value_b,
+              GypsyPositionFields field)
+{
+       /* If both fields are valid, compare the values */
+       if ((fields_a & field) && (fields_b & field)) {
+               if (value_a == value_b) {
+                       return FALSE;
+               } else {
+                       return TRUE;
+               }
+       }
+
+       /* Otherwise return if both the fields set are the same */
+       return ((fields_a & field) != (fields_b & field));
+}
+
+static GeocluePositionFields
+gypsy_position_to_geoclue (GypsyPositionFields fields)
+{
+       GeocluePositionFields gc_fields = GEOCLUE_POSITION_FIELDS_NONE;
+
+       gc_fields |= (fields & GYPSY_POSITION_FIELDS_LATITUDE) ? GEOCLUE_POSITION_FIELDS_LATITUDE : 0;
+       gc_fields |= (fields & GYPSY_POSITION_FIELDS_LONGITUDE) ? GEOCLUE_POSITION_FIELDS_LONGITUDE : 0;
+       gc_fields |= (fields & GYPSY_POSITION_FIELDS_ALTITUDE) ? GEOCLUE_POSITION_FIELDS_ALTITUDE : 0;
+
+       return gc_fields;
+}
+
+static GeoclueVelocityFields
+gypsy_course_to_geoclue (GypsyCourseFields fields)
+{
+       GeoclueVelocityFields gc_fields = GEOCLUE_VELOCITY_FIELDS_NONE;
+
+       gc_fields |= (fields & GYPSY_COURSE_FIELDS_SPEED) ? GEOCLUE_VELOCITY_FIELDS_SPEED : 0;
+       gc_fields |= (fields & GYPSY_COURSE_FIELDS_DIRECTION) ? GEOCLUE_VELOCITY_FIELDS_DIRECTION : 0;
+       gc_fields |= (fields & GYPSY_COURSE_FIELDS_CLIMB) ? GEOCLUE_VELOCITY_FIELDS_CLIMB : 0;
+
+       return gc_fields;
+}
+
+static void
+position_changed (GypsyPosition      *position,
+                 GypsyPositionFields fields,
+                 int                 timestamp,
+                 double              latitude,
+                 double              longitude,
+                 double              altitude,
+                 GeoclueGypsy       *gypsy)
+{
+       gboolean changed = FALSE;
+
+        g_print ("Gypsy position changed\n");
+       gypsy->timestamp = timestamp;
+       if (compare_field (gypsy->position_fields, gypsy->latitude,
+                          fields, latitude, GYPSY_POSITION_FIELDS_LATITUDE)) {
+               if (fields | GYPSY_POSITION_FIELDS_LATITUDE) {
+                       gypsy->position_fields |= GYPSY_POSITION_FIELDS_LATITUDE;
+                       gypsy->latitude = latitude;
+                       changed = TRUE;
+               }
+       }
+
+       if (compare_field (gypsy->position_fields, gypsy->longitude,
+                          fields, longitude, GYPSY_POSITION_FIELDS_LONGITUDE)) {
+               if (fields | GYPSY_POSITION_FIELDS_LONGITUDE) {
+                       gypsy->position_fields |= GYPSY_POSITION_FIELDS_LONGITUDE;
+                       gypsy->longitude = longitude;
+                       changed = TRUE;
+               }
+       }
+
+       if (compare_field (gypsy->position_fields, gypsy->altitude,
+                          fields, altitude, GYPSY_POSITION_FIELDS_ALTITUDE)) {
+               if (fields | GYPSY_POSITION_FIELDS_ALTITUDE) {
+                       gypsy->position_fields |= GYPSY_POSITION_FIELDS_ALTITUDE;
+                       gypsy->altitude = altitude;
+                       changed = TRUE;
+               }
+       }
+
+       if (changed) {
+               GeocluePositionFields fields;
+
+                g_print ("Emitting signal\n");
+               fields = gypsy_position_to_geoclue (gypsy->position_fields);
+               gc_iface_position_emit_position_changed
+                       (GC_IFACE_POSITION (gypsy), fields,
+                        timestamp, gypsy->latitude, gypsy->longitude,
+                        gypsy->altitude, gypsy->accuracy);
+       }
+}
+
+static void
+course_changed (GypsyCourse      *course,
+               GypsyCourseFields fields,
+               int               timestamp,
+               double            speed,
+               double            direction,
+               double            climb,
+               GeoclueGypsy     *gypsy)
+{
+       gboolean changed = FALSE;
+
+       gypsy->timestamp = timestamp;
+       if (compare_field (gypsy->course_fields, gypsy->speed,
+                          fields, speed, GYPSY_COURSE_FIELDS_SPEED)) {
+               if (fields & GYPSY_COURSE_FIELDS_SPEED) {
+                       gypsy->course_fields |= GYPSY_COURSE_FIELDS_SPEED;
+                       gypsy->speed = speed;
+                       changed = TRUE;
+               }
+       }
+
+       if (compare_field (gypsy->course_fields, gypsy->direction,
+                          fields, direction, GYPSY_COURSE_FIELDS_DIRECTION)) {
+               if (fields & GYPSY_COURSE_FIELDS_DIRECTION) {
+                       gypsy->course_fields |= GYPSY_COURSE_FIELDS_DIRECTION;
+                       gypsy->direction = direction;
+                       changed = TRUE;
+               }
+       }
+
+       if (compare_field (gypsy->course_fields, gypsy->climb,
+                          fields, climb, GYPSY_COURSE_FIELDS_CLIMB)) {
+               if (fields & GYPSY_COURSE_FIELDS_CLIMB) {
+                       gypsy->course_fields |= GYPSY_COURSE_FIELDS_CLIMB;
+                       gypsy->climb = climb;
+                       changed = TRUE;
+               }
+       }
+
+       if (changed) {
+               GeoclueVelocityFields fields;
+
+               fields = gypsy_course_to_geoclue (gypsy->course_fields);
+               gc_iface_velocity_emit_velocity_changed
+                       (GC_IFACE_VELOCITY (gypsy), fields,
+                        timestamp, gypsy->speed, gypsy->direction, gypsy->climb);
+       }
+}
+
+static void
+accuracy_changed (GypsyAccuracy      *accuracy,
+                 GypsyAccuracyFields fields,
+                 double              pdop,
+                 double              hdop,
+                 double              vdop,
+                 GeoclueGypsy       *gypsy)
+{
+       gboolean changed = FALSE;
+       GeoclueAccuracyLevel level;
+       double horiz, vert;
+
+       geoclue_accuracy_get_details (gypsy->accuracy, &level, &horiz, &vert);
+       if (fields & (GYPSY_ACCURACY_FIELDS_HORIZONTAL |
+                     GYPSY_ACCURACY_FIELDS_VERTICAL)){
+               if (level != GEOCLUE_ACCURACY_LEVEL_DETAILED ||
+                   horiz != hdop || vert != vdop) {
+                       changed = TRUE;
+               }
+
+               geoclue_accuracy_set_details (gypsy->accuracy,
+                                             GEOCLUE_ACCURACY_LEVEL_DETAILED,
+                                             hdop, vdop);
+       } else {
+
+               if (level != GEOCLUE_ACCURACY_LEVEL_NONE ||
+                   horiz != 0.0 || vert != 0.0) {
+                       changed = TRUE;
+               }
+
+               geoclue_accuracy_set_details (gypsy->accuracy,
+                                             GEOCLUE_ACCURACY_LEVEL_NONE,
+                                             0.0, 0.0);
+       }
+
+       if (changed) {
+               GeocluePositionFields fields;
+
+               fields = gypsy_position_to_geoclue (gypsy->position_fields);
+               gc_iface_position_emit_position_changed
+                       (GC_IFACE_POSITION (gypsy), fields,
+                        gypsy->timestamp, gypsy->latitude, gypsy->longitude,
+                        gypsy->altitude, gypsy->accuracy);
+       }
+}
+
+static void
+connection_changed (GypsyDevice  *device,
+                   gboolean      connected,
+                   GeoclueGypsy *gypsy)
+{
+       if (connected == FALSE &&
+           gypsy->status != GEOCLUE_STATUS_UNAVAILABLE) {
+               gypsy->status = GEOCLUE_STATUS_UNAVAILABLE;
+               gc_iface_geoclue_emit_status_changed (GC_IFACE_GEOCLUE (gypsy),
+                                                     gypsy->status);
+       }
+}
+
+static void
+fix_status_changed (GypsyDevice         *device,
+                   GypsyDeviceFixStatus status,
+                   GeoclueGypsy        *gypsy)
+{
+       gboolean changed = FALSE;
+
+       switch (status) {
+       case GYPSY_DEVICE_FIX_STATUS_INVALID:
+               if (gypsy->status != GEOCLUE_STATUS_UNAVAILABLE) {
+                       changed = TRUE;
+                       gypsy->status = GEOCLUE_STATUS_UNAVAILABLE;
+               }
+               break;
+
+       case GYPSY_DEVICE_FIX_STATUS_NONE:
+               if (gypsy->status != GEOCLUE_STATUS_ACQUIRING) {
+                       changed = TRUE;
+                       gypsy->status = GEOCLUE_STATUS_ACQUIRING;
+               }
+               break;
+
+       case GYPSY_DEVICE_FIX_STATUS_2D:
+       case GYPSY_DEVICE_FIX_STATUS_3D:
+               if (gypsy->status != GEOCLUE_STATUS_AVAILABLE) {
+                       changed = TRUE;
+                       gypsy->status = GEOCLUE_STATUS_AVAILABLE;
+               }
+               break;
+       }
+
+       if (changed) {
+               gc_iface_geoclue_emit_status_changed (GC_IFACE_GEOCLUE (gypsy),
+                                                     gypsy->status);
+       }
+}
+
+static void
+get_initial_status (GeoclueGypsy *gypsy)
+{
+       gboolean connected;
+       GypsyDeviceFixStatus status;
+       GError *error = NULL;
+
+       connected = gypsy_device_get_connection_status (gypsy->device, &error);
+       if (connected == FALSE) {
+               gypsy->status = GEOCLUE_STATUS_UNAVAILABLE;
+               g_print ("Initial status - %d (disconnected)\n", gypsy->status);
+               return;
+       }
+
+       status = gypsy_device_get_fix_status (gypsy->device, &error);
+       switch (status) {
+       case GYPSY_DEVICE_FIX_STATUS_INVALID:
+               gypsy->status = GEOCLUE_STATUS_UNAVAILABLE;
+               break;
+
+       case GYPSY_DEVICE_FIX_STATUS_NONE:
+               gypsy->status = GEOCLUE_STATUS_ACQUIRING;
+               break;
+
+       case GYPSY_DEVICE_FIX_STATUS_2D:
+       case GYPSY_DEVICE_FIX_STATUS_3D:
+               gypsy->status = GEOCLUE_STATUS_AVAILABLE;
+               break;
+       }
+
+       g_print ("Initial status - %d (connected)\n", gypsy->status);
+}
+
+static gboolean
+set_options (GcIfaceGeoclue *gc,
+             GHashTable     *options,
+             GError        **error)
+{
+        GeoclueGypsy *gypsy = GEOCLUE_GYPSY (gc);
+        const char *device_name;
+        char *path;
+
+        device_name = g_hash_table_lookup (options,
+                                           "org.freedesktop.Geoclue.GPSDevice");
+
+        if (g_strcmp0 (gypsy->device_name, device_name) == 0) {
+               return TRUE;
+       }
+
+       g_free (gypsy->device_name);
+       gypsy->device_name = NULL;
+
+       if (device_name == NULL || *device_name == '\0') {
+               return TRUE;
+       }
+
+        gypsy->device_name = g_strdup (device_name);
+        g_print ("Gypsy provider using '%s'\n", gypsy->device_name);
+       path = gypsy_control_create (gypsy->control, gypsy->device_name,
+                                    error);
+       if (*error != NULL) {
+                g_print ("Error - %s?\n", (*error)->message);
+                gypsy->status = GEOCLUE_STATUS_ERROR;
+                return FALSE;
+       }
+
+        /* If we've got here, then we are out of the ERROR condition */
+        gypsy->status = GEOCLUE_STATUS_UNAVAILABLE;
+
+       gypsy->device = gypsy_device_new (path);
+       g_signal_connect (gypsy->device, "connection-changed",
+                         G_CALLBACK (connection_changed), gypsy);
+       g_signal_connect (gypsy->device, "fix-status-changed",
+                         G_CALLBACK (fix_status_changed), gypsy);
+
+       gypsy->position = gypsy_position_new (path);
+       g_signal_connect (gypsy->position, "position-changed",
+                         G_CALLBACK (position_changed), gypsy);
+       gypsy->course = gypsy_course_new (path);
+       g_signal_connect (gypsy->course, "course-changed",
+                         G_CALLBACK (course_changed), gypsy);
+       gypsy->acc = gypsy_accuracy_new (path);
+       g_signal_connect (gypsy->acc, "accuracy-changed",
+                         G_CALLBACK (accuracy_changed), gypsy);
+
+       g_debug ("starting device");
+       gypsy_device_start (gypsy->device, error);
+       if (*error != NULL) {
+               g_print ("Error - %s?\n", (*error)->message);
+               gypsy->status = GEOCLUE_STATUS_ERROR;
+               g_free (path);
+               return FALSE;
+       }
+       get_initial_status (gypsy);
+       g_free (path);
+
+       return TRUE;
+}
+
+static void
+shutdown (GcProvider *provider)
+{
+       GeoclueGypsy *gypsy = GEOCLUE_GYPSY (provider);
+
+       g_main_loop_quit (gypsy->loop);
+}
+
+static void
+finalize (GObject *object)
+{
+       GeoclueGypsy *gypsy = GEOCLUE_GYPSY (object);
+
+       geoclue_accuracy_free (gypsy->accuracy);
+        g_free (gypsy->device_name);
+
+       ((GObjectClass *) geoclue_gypsy_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       GeoclueGypsy *gypsy = GEOCLUE_GYPSY (object);
+
+       if (gypsy->control) {
+               g_object_unref (gypsy->control);
+               gypsy->control = NULL;
+       }
+
+       if (gypsy->device) {
+               g_object_unref (gypsy->device);
+               gypsy->device = NULL;
+       }
+
+       if (gypsy->position) {
+               g_object_unref (gypsy->position);
+               gypsy->position = NULL;
+       }
+
+       ((GObjectClass *) geoclue_gypsy_parent_class)->dispose (object);
+}
+
+static void
+geoclue_gypsy_class_init (GeoclueGypsyClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+       GcProviderClass *p_class = (GcProviderClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+
+       p_class->get_status = get_status;
+       p_class->set_options = set_options;
+       p_class->shutdown = shutdown;
+}
+
+static void
+geoclue_gypsy_init (GeoclueGypsy *gypsy)
+{
+       gypsy->status = GEOCLUE_STATUS_ERROR;
+       gypsy->control = gypsy_control_get_default ();
+
+       gc_provider_set_details (GC_PROVIDER (gypsy),
+                                "org.freedesktop.Geoclue.Providers.Gypsy",
+                                "/org/freedesktop/Geoclue/Providers/Gypsy",
+                                "Gypsy", "Gypsy provider");
+
+       gypsy->position_fields = GYPSY_POSITION_FIELDS_NONE;
+
+       gypsy->accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE,
+                                               0.0, 0.0);
+}
+
+static gboolean
+get_position (GcIfacePosition       *gc,
+             GeocluePositionFields *fields,
+             int                   *timestamp,
+             double                *latitude,
+             double                *longitude,
+             double                *altitude,
+             GeoclueAccuracy      **accuracy,
+             GError               **error)
+{
+       GeoclueGypsy *gypsy = GEOCLUE_GYPSY (gc);
+       GeoclueAccuracyLevel level;
+       double horizontal, vertical;
+
+       *timestamp = gypsy->timestamp;
+
+       *fields = GEOCLUE_POSITION_FIELDS_NONE;
+       if (gypsy->position_fields & GYPSY_POSITION_FIELDS_LATITUDE) {
+               *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE;
+               *latitude = gypsy->latitude;
+       }
+       if (gypsy->position_fields & GYPSY_POSITION_FIELDS_LONGITUDE) {
+               *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE;
+               *longitude = gypsy->longitude;
+       }
+       if (gypsy->position_fields & GYPSY_POSITION_FIELDS_ALTITUDE) {
+               *fields |= GEOCLUE_POSITION_FIELDS_ALTITUDE;
+               *altitude = gypsy->altitude;
+       }
+
+       geoclue_accuracy_get_details (gypsy->accuracy, &level,
+                                     &horizontal, &vertical);
+       *accuracy = geoclue_accuracy_new (level, horizontal, vertical);
+
+       return TRUE;
+}
+
+static void
+geoclue_gypsy_position_init (GcIfacePositionClass *iface)
+{
+       iface->get_position = get_position;
+}
+
+static gboolean
+get_velocity (GcIfaceVelocity       *gc,
+             GeoclueVelocityFields *fields,
+             int                   *timestamp,
+             double                *speed,
+             double                *direction,
+             double                *climb,
+             GError               **error)
+{
+       return TRUE;
+}
+
+static void
+geoclue_gypsy_velocity_init (GcIfaceVelocityClass *iface)
+{
+       iface->get_velocity = get_velocity;
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+       GeoclueGypsy *gypsy;
+
+       g_type_init ();
+
+       gypsy = g_object_new (GEOCLUE_TYPE_GYPSY, NULL);
+
+       gypsy->loop = g_main_loop_new (NULL, TRUE);
+       g_main_loop_run (gypsy->loop);
+
+       /* Unref the object so that gypsy-daemon knows we've shutdown */
+       g_object_unref (gypsy);
+       return 0;
+}
diff --git a/providers/gypsy/geoclue-gypsy.provider b/providers/gypsy/geoclue-gypsy.provider
new file mode 100755 (executable)
index 0000000..766a7ab
--- /dev/null
@@ -0,0 +1,8 @@
+[Geoclue Provider]
+Name=Gypsy
+Service=org.freedesktop.Geoclue.Providers.Gypsy
+Path=/org/freedesktop/Geoclue/Providers/Gypsy
+Requires=RequiresGPS
+Provides=ProvidesUpdates
+Interfaces=org.freedesktop.Geoclue.Position;org.freedesktop.Geoclue.Velocity
+Accuracy=Detailed
diff --git a/providers/gypsy/org.freedesktop.Geoclue.Providers.Gypsy.service.in b/providers/gypsy/org.freedesktop.Geoclue.Providers.Gypsy.service.in
new file mode 100755 (executable)
index 0000000..d6613ac
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Providers.Gypsy
+Exec=@libexecdir@/geoclue-gypsy
diff --git a/providers/hostip/Makefile.am b/providers/hostip/Makefile.am
new file mode 100644 (file)
index 0000000..e4220a8
--- /dev/null
@@ -0,0 +1,35 @@
+libexec_PROGRAMS =     \
+       geoclue-hostip
+
+NOINST_H_FILES =               \
+       geoclue-hostip.h
+
+geoclue_hostip_SOURCES =       \
+       $(NOINST_H_FILES)       \
+       geoclue-hostip.c
+
+geoclue_hostip_CFLAGS = \
+       -I$(top_srcdir) \
+       -I$(top_builddir) \
+       $(GEOCLUE_CFLAGS)
+
+geoclue_hostip_LDADD = \
+       $(GEOCLUE_LIBS) \
+       $(top_builddir)/geoclue/libgeoclue.la
+
+providersdir = $(datadir)/geoclue-providers
+providers_DATA = geoclue-hostip.provider
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Providers.Hostip.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+EXTRA_DIST =                   \
+       $(service_in_files)     \
+       $(providers_DATA)
+
+DISTCLEANFILES = \
+       $(service_DATA)
diff --git a/providers/hostip/geoclue-hostip.c b/providers/hostip/geoclue-hostip.c
new file mode 100755 (executable)
index 0000000..1988abf
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Geoclue
+ * geoclue-hostip.c - A hostip.info-based Address/Position provider
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2007, 2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <time.h>
+#include <dbus/dbus-glib-bindings.h>
+
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-error.h>
+
+#include <geoclue/gc-iface-position.h>
+#include <geoclue/gc-iface-address.h>
+
+#include "geoclue-hostip.h"
+
+#define GEOCLUE_DBUS_SERVICE_HOSTIP "org.freedesktop.Geoclue.Providers.Hostip"
+#define GEOCLUE_DBUS_PATH_HOSTIP "/org/freedesktop/Geoclue/Providers/Hostip"
+
+#define HOSTIP_URL "http://api.hostip.info/"
+
+#define HOSTIP_NS_GML_NAME "gml"
+#define HOSTIP_NS_GML_URI "http://www.opengis.net/gml"
+
+#define HOSTIP_COUNTRY_XPATH "//gml:featureMember/Hostip/countryName"
+#define HOSTIP_COUNTRYCODE_XPATH "//gml:featureMember/Hostip/countryAbbrev"
+#define HOSTIP_LOCALITY_XPATH "//gml:featureMember/Hostip/gml:name"
+#define HOSTIP_LATLON_XPATH "//gml:featureMember/Hostip//gml:coordinates"
+
+static void geoclue_hostip_init (GeoclueHostip *obj);
+static void geoclue_hostip_position_init (GcIfacePositionClass  *iface);
+static void geoclue_hostip_address_init (GcIfaceAddressClass  *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueHostip, geoclue_hostip, GC_TYPE_PROVIDER,
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION,
+                                                geoclue_hostip_position_init)
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS,
+                                                geoclue_hostip_address_init))
+
+
+/* Geoclue interface implementation */
+static gboolean
+geoclue_hostip_get_status (GcIfaceGeoclue *iface,
+                          GeoclueStatus  *status,
+                          GError        **error)
+{
+       /* Assume it is available so long as all the requirements are satisfied
+          ie: Network is available */
+       *status = GEOCLUE_STATUS_AVAILABLE;
+       return TRUE;
+}
+
+static void
+shutdown (GcProvider *provider)
+{
+       GeoclueHostip *obj = GEOCLUE_HOSTIP (provider);
+       g_main_loop_quit (obj->loop);
+}
+
+/* Position interface implementation */
+
+static gboolean
+geoclue_hostip_get_position (GcIfacePosition        *iface,
+                                 GeocluePositionFields  *fields,
+                                 int                    *timestamp,
+                                 double                 *latitude,
+                                 double                 *longitude,
+                                 double                 *altitude,
+                                 GeoclueAccuracy       **accuracy,
+                                 GError                **error)
+{
+       GeoclueHostip *obj = (GEOCLUE_HOSTIP (iface));
+       gchar *coord_str = NULL;
+
+       *fields = GEOCLUE_POSITION_FIELDS_NONE;
+
+       if (!gc_web_service_query (obj->web_service, error, (char *)0)) {
+               return FALSE;
+       }
+
+       if (gc_web_service_get_string (obj->web_service,
+                                       &coord_str, HOSTIP_LATLON_XPATH)) {
+               if (sscanf (coord_str, "%lf,%lf", longitude , latitude) == 2) {
+                       *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE;
+                       *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE;
+               }
+               g_free (coord_str);
+       }
+
+       time ((time_t *)timestamp);
+
+       if (*fields == GEOCLUE_POSITION_FIELDS_NONE) {
+               *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE,
+                                                 0, 0);
+       } else {
+               *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_LOCALITY,
+                                                 0, 0);
+       }
+       return TRUE;
+}
+
+/* Address interface implementation */
+
+static gboolean
+geoclue_hostip_get_address (GcIfaceAddress   *iface,
+                            int              *timestamp,
+                            GHashTable      **address,
+                            GeoclueAccuracy **accuracy,
+                            GError          **error)
+{
+       GeoclueHostip *obj = GEOCLUE_HOSTIP (iface);
+       gchar *locality = NULL;
+       gchar *country = NULL;
+       gchar *country_code = NULL;
+
+       if (!gc_web_service_query (obj->web_service, error, (char *)0)) {
+               return FALSE;
+       }
+
+       if (address) {
+               *address = geoclue_address_details_new ();
+               if (gc_web_service_get_string (obj->web_service,
+                                              &locality, HOSTIP_LOCALITY_XPATH)) {
+                       /* hostip "sctructured data" for the win... */
+                       if (g_ascii_strcasecmp (locality, "(Unknown city)") == 0 ||
+                           g_ascii_strcasecmp (locality, "(Unknown City?)") == 0) {
+
+                               g_free (locality);
+                               locality = NULL;
+                       } else {
+                               geoclue_address_details_insert (*address,
+                                                               GEOCLUE_ADDRESS_KEY_LOCALITY,
+                                                               locality);
+                       }
+               }
+
+               if (gc_web_service_get_string (obj->web_service,
+                                              &country_code, HOSTIP_COUNTRYCODE_XPATH)) {
+                       if (g_ascii_strcasecmp (country_code, "XX") == 0) {
+                               g_free (country_code);
+                               country_code = NULL;
+                       } else {
+                               geoclue_address_details_insert (*address,
+                                                               GEOCLUE_ADDRESS_KEY_COUNTRYCODE,
+                                                               country_code);
+                               geoclue_address_details_set_country_from_code (*address);
+                       }
+               }
+
+               if (!g_hash_table_lookup (*address, GEOCLUE_ADDRESS_KEY_COUNTRY) &&
+                   gc_web_service_get_string (obj->web_service,
+                                              &country, HOSTIP_COUNTRY_XPATH)) {
+                       if (g_ascii_strcasecmp (country, "(Unknown Country?)") == 0) {
+                               g_free (country);
+                               country = NULL;
+                       } else {
+                               geoclue_address_details_insert (*address,
+                                                               GEOCLUE_ADDRESS_KEY_COUNTRY,
+                                                               country);
+                       }
+               }
+       }
+
+       if (timestamp) {
+               *timestamp = time (NULL);
+       }
+
+       if (accuracy) {
+               if (locality && country) {
+                       *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_LOCALITY,
+                                                         0, 0);
+               } else if (country) {
+                       *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_COUNTRY,
+                                                         0, 0);
+               } else {
+                       *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE,
+                                                         0, 0);
+               }
+       }
+       g_free (locality);
+       g_free (country);
+       g_free (country_code);
+
+       return TRUE;
+}
+
+static void
+geoclue_hostip_finalize (GObject *obj)
+{
+       GeoclueHostip *self = (GeoclueHostip *) obj;
+
+       g_object_unref (self->web_service);
+
+       ((GObjectClass *) geoclue_hostip_parent_class)->finalize (obj);
+}
+
+
+/* Initialization */
+
+static void
+geoclue_hostip_class_init (GeoclueHostipClass *klass)
+{
+       GcProviderClass *p_class = (GcProviderClass *)klass;
+       GObjectClass *o_class = (GObjectClass *)klass;
+
+       p_class->shutdown = shutdown;
+       p_class->get_status = geoclue_hostip_get_status;
+
+       o_class->finalize = geoclue_hostip_finalize;
+}
+
+static void
+geoclue_hostip_init (GeoclueHostip *obj)
+{
+       gc_provider_set_details (GC_PROVIDER (obj),
+                                GEOCLUE_DBUS_SERVICE_HOSTIP,
+                                GEOCLUE_DBUS_PATH_HOSTIP,
+                                "Hostip", "Hostip provider");
+
+       obj->web_service = g_object_new (GC_TYPE_WEB_SERVICE, NULL);
+       gc_web_service_set_base_url (obj->web_service, HOSTIP_URL);
+       gc_web_service_add_namespace (obj->web_service,
+                                     HOSTIP_NS_GML_NAME, HOSTIP_NS_GML_URI);
+}
+
+static void
+geoclue_hostip_position_init (GcIfacePositionClass  *iface)
+{
+       iface->get_position = geoclue_hostip_get_position;
+}
+
+static void
+geoclue_hostip_address_init (GcIfaceAddressClass  *iface)
+{
+       iface->get_address = geoclue_hostip_get_address;
+}
+
+int
+main()
+{
+       g_type_init();
+
+       GeoclueHostip *o = g_object_new (GEOCLUE_TYPE_HOSTIP, NULL);
+       o->loop = g_main_loop_new (NULL, TRUE);
+
+       g_main_loop_run (o->loop);
+
+       g_main_loop_unref (o->loop);
+       g_object_unref (o);
+
+       return 0;
+}
diff --git a/providers/hostip/geoclue-hostip.h b/providers/hostip/geoclue-hostip.h
new file mode 100755 (executable)
index 0000000..e92ab85
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Geoclue
+ * geoclue-hostip.h - An Address/Position provider for hostip.info
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_HOSTIP
+#define _GEOCLUE_HOSTIP
+
+#include <glib-object.h>
+#include <geoclue/gc-web-service.h>
+#include <geoclue/gc-provider.h>
+
+G_BEGIN_DECLS
+
+
+#define GEOCLUE_TYPE_HOSTIP (geoclue_hostip_get_type ())
+
+#define GEOCLUE_HOSTIP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_HOSTIP, GeoclueHostip))
+#define GEOCLUE_HOSTIP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEOCLUE_TYPE_HOSTIP, GeoclueHostipClass))
+#define GEOCLUE_IS_HOSTIP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_HOSTIP))
+#define GEOCLUE_IS_HOSTIP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEOCLUE_TYPE_HOSTIP))
+
+typedef struct _GeoclueHostip {
+       GcProvider parent;
+       GMainLoop *loop;
+       GcWebService *web_service;
+} GeoclueHostip;
+
+typedef struct _GeoclueHostipClass {
+       GcProviderClass parent_class;
+} GeoclueHostipClass;
+
+GType geoclue_hostip_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/providers/hostip/geoclue-hostip.provider b/providers/hostip/geoclue-hostip.provider
new file mode 100755 (executable)
index 0000000..5467260
--- /dev/null
@@ -0,0 +1,8 @@
+[Geoclue Provider]
+Name=Hostip
+Service=org.freedesktop.Geoclue.Providers.Hostip
+Path=/org/freedesktop/Geoclue/Providers/Hostip
+Accuracy=Locality
+Requires=RequiresNetwork
+Provides=ProvidesCacheableOnConnection
+Interfaces=org.freedesktop.Geoclue.Position;org.freedesktop.Geoclue.Address
diff --git a/providers/hostip/org.freedesktop.Geoclue.Providers.Hostip.service.in b/providers/hostip/org.freedesktop.Geoclue.Providers.Hostip.service.in
new file mode 100755 (executable)
index 0000000..a475c2e
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Providers.Hostip
+Exec=@libexecdir@/geoclue-hostip
diff --git a/providers/localnet/Makefile.am b/providers/localnet/Makefile.am
new file mode 100644 (file)
index 0000000..f810ec3
--- /dev/null
@@ -0,0 +1,54 @@
+libexec_PROGRAMS = geoclue-localnet
+
+noinst_DATA = \
+       geoclue-localnet.xml
+
+nodist_geoclue_localnet_SOURCES = \
+       geoclue-localnet-glue.h
+
+BUILT_SOURCES =                        \
+       $(nodist_geoclue_localnet_SOURCES)
+
+geoclue_localnet_SOURCES =     \
+       geoclue-localnet.c
+
+geoclue_localnet_CFLAGS = \
+       -I$(top_srcdir)     \
+       -I$(top_builddir)   \
+       $(GEOCLUE_CFLAGS)
+
+geoclue_localnet_LDADD = \
+       $(GEOCLUE_LIBS)    \
+       $(top_builddir)/geoclue/libgeoclue.la
+
+
+providersdir = $(datadir)/geoclue-providers
+providers_DATA = geoclue-localnet.provider
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Providers.Localnet.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+CLEANFILES = \
+       stamp-geoclue-localnet-glue.h
+
+EXTRA_DIST =                   \
+       $(service_in_files)     \
+       $(providers_DATA)       \
+       $(noinst_DATA)
+
+DISTCLEANFILES = \
+       $(service_DATA)         \
+       $(nodist_geoclue_localnet_SOURCES)
+
+%-glue.h: stamp-%-glue.h
+       @true
+
+stamp-geoclue-localnet-glue.h: geoclue-localnet.xml
+       $(DBUS_BINDING_TOOL) --prefix=geoclue_localnet --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
diff --git a/providers/localnet/geoclue-localnet.c b/providers/localnet/geoclue-localnet.c
new file mode 100644 (file)
index 0000000..57379ed
--- /dev/null
@@ -0,0 +1,603 @@
+/**
+ *
+ * Expects to find a keyfile in user config dir
+ * (~/.config/geoclue-localnet-gateways).
+ *
+ * The keyfile should contain entries like this:
+ *
+ * [00:1D:7E:55:8D:80]
+ * country=Finland
+ * street=Solnantie 24
+ * locality=Helsinki
+ *
+ * Only address interface is supported so far.
+ *
+ * Any application that can obtain a reliable address can submit it
+ * to localnet provider through the D-Bus API -- it will then be provided
+ * whenever connected to the same router:
+ *    org.freedesktop.Geoclue.Localnet.SetAddress
+ *    org.freedesktop.Geoclue.Localnet.SetAddressFields
+ *
+ * SetAddress allows setting the current address as a GeoclueAddress,
+ * while SetAddressFields is a convenience version with separate
+ * address fields. Shell example using SetAddressFields:
+ *
+  dbus-send --print-reply --type=method_call \
+            --dest=org.freedesktop.Geoclue.Providers.Localnet \
+            /org/freedesktop/Geoclue/Providers/Localnet \
+            org.freedesktop.Geoclue.Localnet.SetAddressFields \
+            string: \
+            string:"Finland" \
+            string: \
+            string:"Helsinki" \
+            string: \
+            string: \
+            string:"Solnantie 24"
+
+ * This would make the provider save the specified address with current
+ * router mac address. It will provide the address to clients whenever
+ * the computer is connected to the same router again.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <dbus/dbus-glib-bindings.h>
+#include <dbus/dbus.h>
+
+#include <geoclue/gc-provider.h>
+#include <geoclue/geoclue-error.h>
+#include <geoclue/gc-iface-address.h>
+
+#define KEYFILE_NAME "geoclue-localnet-gateways"
+
+typedef struct {
+       char *mac;
+       GHashTable *address;
+       GeoclueAccuracy *accuracy;
+} Gateway;
+
+
+typedef struct {
+       GcProvider parent;
+
+       GMainLoop *loop;
+
+       char *keyfile_name;
+       GSList *gateways;
+} GeoclueLocalnet;
+
+typedef struct {
+       GcProviderClass parent_class;
+} GeoclueLocalnetClass;
+
+#define GEOCLUE_TYPE_LOCALNET (geoclue_localnet_get_type ())
+#define GEOCLUE_LOCALNET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_LOCALNET, GeoclueLocalnet))
+
+static void geoclue_localnet_address_init (GcIfaceAddressClass *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueLocalnet, geoclue_localnet, GC_TYPE_PROVIDER,
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS,
+                                                geoclue_localnet_address_init))
+
+static gboolean geoclue_localnet_set_address (GeoclueLocalnet *localnet, GHashTable *address, GError **error);
+static gboolean geoclue_localnet_set_address_fields (GeoclueLocalnet *localnet, char *country_code, char *country, char *region, char *locality, char *area, char *postalcode, char *street, GError **error);
+#include "geoclue-localnet-glue.h"
+
+
+static gboolean
+get_status (GcIfaceGeoclue *gc,
+            GeoclueStatus  *status,
+            GError        **error)
+{
+       *status = GEOCLUE_STATUS_AVAILABLE;
+       return TRUE;
+}
+
+static void
+shutdown (GcProvider *provider)
+{
+       GeoclueLocalnet *localnet;
+
+       localnet = GEOCLUE_LOCALNET (provider);
+       g_main_loop_quit (localnet->loop);
+}
+
+static void
+free_gateway_list (GSList *gateways)
+{
+       GSList *l;
+
+       l = gateways;
+       while (l) {
+               Gateway *gw;
+
+               gw = l->data;
+               g_free (gw->mac);
+               g_hash_table_destroy (gw->address);
+               geoclue_accuracy_free (gw->accuracy);
+               g_free (gw);
+
+               l = l->next;
+       }
+       g_slist_free (gateways);
+}
+
+static void
+finalize (GObject *object)
+{
+       GeoclueLocalnet *localnet;
+
+       localnet = GEOCLUE_LOCALNET (object);
+
+       g_free (localnet->keyfile_name);
+       free_gateway_list (localnet->gateways);
+
+       G_OBJECT_CLASS (geoclue_localnet_parent_class)->finalize (object);
+}
+
+static void
+geoclue_localnet_class_init (GeoclueLocalnetClass *klass)
+{
+       GcProviderClass *p_class = (GcProviderClass *) klass;
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+
+       p_class->get_status = get_status;
+       p_class->shutdown = shutdown;
+
+       dbus_g_object_type_install_info (geoclue_localnet_get_type (),
+                                        &dbus_glib_geoclue_localnet_object_info);
+
+}
+
+/* Parse /proc/net/route to get default gateway address and then parse
+ * /proc/net/arp to find matching mac address.
+ *
+ * There are some problems with this. First, it's IPv4 only.
+ * Second, there must be a way to do this with ioctl, but that seemed really
+ * complicated... even /usr/sbin/arp parses /proc/net/arp
+ *
+ * returns:
+ *   1 : on success
+ *   0 : no success, no errors
+ *  <0 : error
+ */
+int
+get_mac_address (char **mac)
+{
+       char *content;
+       char **lines, **entry;
+       GError *error = NULL;
+       char *route_gateway = NULL;
+
+       g_assert (*mac == NULL);
+
+       if (!g_file_get_contents ("/proc/net/route", &content, NULL, &error)) {
+               g_warning ("Failed to read /proc/net/route: %s", error->message);
+               g_error_free (error);
+               return -1;
+       }
+
+       lines = g_strsplit (content, "\n", 0);
+       g_free (content);
+       entry = lines + 1;
+
+       while (*entry && strlen (*entry) > 0) {
+               char dest[9];
+               char gateway[9];
+               if (sscanf (*entry,
+                               "%*s %8[0-9A-Fa-f] %8[0-9A-Fa-f] %*s",
+                               dest, gateway) != 2) {
+                       g_warning ("Failed to parse /proc/net/route entry '%s'", *entry);
+               } else if (strcmp (dest, "00000000") == 0) {
+                       route_gateway = g_strdup (gateway);
+                       break;
+               }
+               entry++;
+       }
+       g_strfreev (lines);
+
+       if (!route_gateway) {
+               g_warning ("Failed to find default route in /proc/net/route");
+               return -1;
+       }
+
+       if (!g_file_get_contents ("/proc/net/arp", &content, NULL, &error)) {
+               g_warning ("Failed to read /proc/net/arp: %s", error->message);
+               g_error_free (error);
+               return -1;
+       }
+
+       lines = g_strsplit (content, "\n", 0);
+       g_free (content);
+       entry = lines+1;
+       while (*entry && strlen (*entry) > 0) {
+               char hwa[100];
+               char *arp_gateway;
+               int ip[4];
+
+               if (sscanf(*entry,
+                          "%d.%d.%d.%d 0x%*x 0x%*x %100s %*s %*s\n",
+                          &ip[0], &ip[1], &ip[2], &ip[3], hwa) != 5) {
+                       g_warning ("Failed to parse /proc/net/arp entry '%s'", *entry);
+               } else {
+                       arp_gateway = g_strdup_printf ("%02X%02X%02X%02X", ip[3], ip[2], ip[1], ip[0]);
+                       if (strcmp (arp_gateway, route_gateway) == 0) {
+                               g_free (arp_gateway);
+                               *mac = g_strdup (hwa);
+                               break;
+                       }
+                       g_free (arp_gateway);
+
+               }
+               entry++;
+       }
+       g_free (route_gateway);
+       g_strfreev (lines);
+
+       return *mac ? 1 : 0;
+}
+
+static void
+geoclue_localnet_load_gateways_from_keyfile (GeoclueLocalnet  *localnet,
+                                             GKeyFile         *keyfile)
+{
+       char **groups;
+       char **g;
+       GError *error = NULL;
+
+       groups = g_key_file_get_groups (keyfile, NULL);
+       g = groups;
+       while (*g) {
+               GeoclueAccuracyLevel level;
+               char **keys;
+               char **k;
+               Gateway *gateway = g_new0 (Gateway, 1);
+
+               gateway->mac = g_ascii_strdown (*g, -1);
+               gateway->address = geoclue_address_details_new ();
+
+               /* read all keys in the group as address fields */
+               keys = g_key_file_get_keys (keyfile, *g,
+                                           NULL, &error);
+               if (error) {
+                       g_warning ("Could not load keys for group [%s] from %s: %s",
+                                  *g, localnet->keyfile_name, error->message);
+                       g_error_free (error);
+                       error = NULL;
+               }
+
+               k = keys;
+               while (*k) {
+                       char *value;
+
+                       value = g_key_file_get_string (keyfile, *g, *k, NULL);
+                       g_hash_table_insert (gateway->address,
+                                            *k, value);
+                       k++;
+               }
+               g_free (keys);
+
+               level = geoclue_address_details_get_accuracy_level (gateway->address);
+               gateway->accuracy = geoclue_accuracy_new (level, 0, 0);
+
+               localnet->gateways = g_slist_prepend (localnet->gateways, gateway);
+
+               g++;
+       }
+       g_strfreev (groups);
+}
+
+static Gateway *
+geoclue_localnet_find_gateway (GeoclueLocalnet *localnet, char *mac)
+{
+       GSList *l;
+
+       l = localnet->gateways;
+       /* eww, should be using a hashtable or something here */
+       while (l) {
+               Gateway *gw = l->data;
+
+               if (strcmp (gw->mac, mac) == 0) {
+                       return gw;
+               }
+
+               l = l->next;
+       }
+
+       return NULL;
+}
+
+static void
+geoclue_localnet_init (GeoclueLocalnet *localnet)
+{
+       const char *dir;
+       GKeyFile *keyfile;
+       GError *error = NULL;
+
+       gc_provider_set_details (GC_PROVIDER (localnet),
+                                "org.freedesktop.Geoclue.Providers.Localnet",
+                                "/org/freedesktop/Geoclue/Providers/Localnet",
+                                "Localnet", "provides Address based on current gateway mac address and a local address file (which can be updated through D-Bus)");
+
+
+       localnet->gateways = NULL;
+
+       /* load known addresses from keyfile */
+       dir = g_get_user_config_dir ();
+       g_mkdir_with_parents (dir, 0755);
+       localnet->keyfile_name = g_build_filename (dir, KEYFILE_NAME, NULL);
+
+       keyfile = g_key_file_new ();
+       if (!g_key_file_load_from_file (keyfile, localnet->keyfile_name,
+                                       G_KEY_FILE_NONE, &error)) {
+               g_warning ("Could not load keyfile %s: %s",
+                          localnet->keyfile_name, error->message);
+               g_error_free (error);
+       }
+       geoclue_localnet_load_gateways_from_keyfile (localnet, keyfile);
+       g_key_file_free (keyfile);
+
+
+}
+
+typedef struct {
+       GKeyFile *keyfile;
+       char *group_name;
+} localnet_keyfile_group;
+
+static void
+add_address_detail_to_keyfile (char *key, char *value,
+                               localnet_keyfile_group *group)
+{
+       g_key_file_set_string (group->keyfile, group->group_name,
+                              key, value);
+}
+
+static gboolean
+geoclue_localnet_set_address (GeoclueLocalnet *localnet,
+                              GHashTable *details,
+                              GError **error)
+{
+       char *str, *mac = NULL;
+       GKeyFile *keyfile;
+       GError *int_err = NULL;
+       localnet_keyfile_group *keyfile_group;
+       Gateway *gw;
+
+       if (!details) {
+               /* TODO set error */
+               return FALSE;
+       }
+
+       if (get_mac_address (&mac) < 0)
+               return FALSE;
+
+       if (!mac) {
+               g_warning ("Couldn't get current gateway mac address");
+               /* TODO set error */
+               return FALSE;
+       }
+       /* reload keyfile just in case it's changed */
+       keyfile = g_key_file_new ();
+       if (!g_key_file_load_from_file (keyfile, localnet->keyfile_name,
+                                       G_KEY_FILE_NONE, &int_err)) {
+               g_warning ("Could not load keyfile %s: %s",
+                        localnet->keyfile_name, int_err->message);
+               g_error_free (int_err);
+               int_err = NULL;
+       }
+
+       /* remove old group (if exists) and add new to GKeyFile */
+       g_key_file_remove_group (keyfile, mac, NULL);
+
+       keyfile_group = g_new0 (localnet_keyfile_group, 1);
+       keyfile_group->keyfile = keyfile;
+       keyfile_group->group_name = mac;
+       g_hash_table_foreach (details, (GHFunc) add_address_detail_to_keyfile, keyfile_group);
+       g_free (keyfile_group);
+
+       /* save keyfile*/
+       str = g_key_file_to_data (keyfile, NULL, &int_err);
+       if (int_err) {
+               g_warning ("Failed to get keyfile data as string: %s", int_err->message);
+               g_error_free (int_err);
+               g_key_file_free (keyfile);
+               g_free (mac);
+               /* TODO set error */
+               return FALSE;
+       }
+
+       g_file_set_contents (localnet->keyfile_name, str, -1, &int_err);
+       g_free (str);
+       if (int_err) {
+               g_warning ("Failed to save keyfile: %s", int_err->message);
+               g_error_free (int_err);
+               g_key_file_free (keyfile);
+               g_free (mac);
+               /* TODO set error */
+               return FALSE;
+       }
+
+       /* re-parse keyfile */
+       free_gateway_list (localnet->gateways);
+       localnet->gateways = NULL;
+       geoclue_localnet_load_gateways_from_keyfile (localnet, keyfile);
+       g_key_file_free (keyfile);
+
+       gw = geoclue_localnet_find_gateway (localnet, mac);
+       g_free (mac);
+
+       if (gw) {
+               gc_iface_address_emit_address_changed (GC_IFACE_ADDRESS (localnet),
+                                                      time (NULL), gw->address, gw->accuracy);
+       } else {
+               /* empty address -- should emit anyway? */
+       }
+       return TRUE;
+}
+
+static gboolean
+geoclue_localnet_set_address_fields (GeoclueLocalnet *localnet,
+                                     char *country_code,
+                                     char *country,
+                                     char *region,
+                                     char *locality,
+                                     char *area,
+                                     char *postalcode,
+                                     char *street,
+                                     GError **error)
+{
+       GHashTable *address;
+       gboolean ret;
+
+       address = geoclue_address_details_new ();
+       if (country_code && (strlen (country_code) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_COUNTRYCODE),
+                                    g_strdup (country_code));
+               if (!country) {
+                       geoclue_address_details_set_country_from_code (address);
+               }
+       }
+       if (country && (strlen (country) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_COUNTRY),
+                                    g_strdup (country));
+       }
+       if (region && (strlen (region) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_REGION),
+                                    g_strdup (region));
+       }
+       if (locality && (strlen (locality) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_LOCALITY),
+                                    g_strdup (locality));
+       }
+       if (area && (strlen (area) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_AREA),
+                                    g_strdup (area));
+       }
+       if (postalcode && (strlen (postalcode) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_POSTALCODE),
+                                    g_strdup (postalcode));
+       }
+       if (street && (strlen (street) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_STREET),
+                                    g_strdup (street));
+       }
+
+       ret = geoclue_localnet_set_address (localnet,
+                                           address,
+                                           error);
+       g_hash_table_destroy (address);
+       return ret;
+}
+
+static gboolean
+get_address (GcIfaceAddress   *gc,
+             int              *timestamp,
+             GHashTable      **address,
+             GeoclueAccuracy **accuracy,
+             GError          **error)
+{
+       GeoclueLocalnet *localnet;
+       int i, ret_val;
+       char *mac = NULL;
+       Gateway *gw;
+
+       localnet = GEOCLUE_LOCALNET (gc);
+
+       /* we may be trying to read /proc/net/arp right after network connection.
+        * It's sometimes not up yet, try a couple of times */
+       for (i = 0; i < 5; i++) {
+               ret_val = get_mac_address (&mac);
+               if (ret_val < 0)
+                       return FALSE;
+               else if (ret_val == 1)
+                       break;
+               usleep (200);
+       }
+
+       if (!mac) {
+               g_warning ("Couldn't get current gateway mac address");
+               if (error) {
+                       g_set_error (error, GEOCLUE_ERROR,
+                                    GEOCLUE_ERROR_NOT_AVAILABLE, "Could not get current gateway mac address");
+               }
+               return FALSE;
+       }
+
+       gw = geoclue_localnet_find_gateway (localnet, mac);
+       g_free (mac);
+
+       if (timestamp) {
+               *timestamp = time(NULL);
+       }
+       if (address) {
+               if (gw) {
+                       *address = geoclue_address_details_copy (gw->address);
+               } else {
+                       *address = geoclue_address_details_new ();
+               }
+       }
+       if (accuracy) {
+               if (gw) {
+                       *accuracy = geoclue_accuracy_copy (gw->accuracy);
+               } else {
+                       *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0);
+               }
+       }
+       return TRUE;
+}
+
+static void
+geoclue_localnet_address_init (GcIfaceAddressClass *iface)
+{
+       iface->get_address = get_address;
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+       GeoclueLocalnet *localnet;
+
+       g_type_init ();
+
+       localnet = g_object_new (GEOCLUE_TYPE_LOCALNET, NULL);
+       localnet->loop = g_main_loop_new (NULL, TRUE);
+
+       g_main_loop_run (localnet->loop);
+
+       g_main_loop_unref (localnet->loop);
+       g_object_unref (localnet);
+
+       return 0;
+}
diff --git a/providers/localnet/geoclue-localnet.provider b/providers/localnet/geoclue-localnet.provider
new file mode 100755 (executable)
index 0000000..e306ea6
--- /dev/null
@@ -0,0 +1,7 @@
+[Geoclue Provider]
+Name=Localnet
+Service=org.freedesktop.Geoclue.Providers.Localnet
+Path=/org/freedesktop/Geoclue/Providers/Localnet
+Interfaces=org.freedesktop.Geoclue.Address
+Accuracy=Street
+Provides=ProvidesCacheableOnConnection
diff --git a/providers/localnet/geoclue-localnet.xml b/providers/localnet/geoclue-localnet.xml
new file mode 100755 (executable)
index 0000000..0154f99
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/">
+  <interface name="org.freedesktop.Geoclue.Localnet">
+    <method name="SetAddress">
+      <arg name="address" type="a{ss}" direction="in"/>
+    </method>
+    <method name="SetAddressFields">
+      <arg type="s" name="countrycode" direction="in"/>
+      <arg type="s" name="country" direction="in"/>
+      <arg type="s" name="region" direction="in"/>
+      <arg type="s" name="locality" direction="in"/>
+      <arg type="s" name="area" direction="in"/>
+      <arg type="s" name="postalcode" direction="in"/>
+      <arg type="s" name="street" direction="in"/>
+    </method>
+  </interface>
+</node>
diff --git a/providers/localnet/org.freedesktop.Geoclue.Providers.Localnet.service.in b/providers/localnet/org.freedesktop.Geoclue.Providers.Localnet.service.in
new file mode 100755 (executable)
index 0000000..7e75855
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Providers.Localnet
+Exec=@libexecdir@/geoclue-localnet
diff --git a/providers/manual/Makefile.am b/providers/manual/Makefile.am
new file mode 100644 (file)
index 0000000..b7ff8ac
--- /dev/null
@@ -0,0 +1,54 @@
+libexec_PROGRAMS = geoclue-manual
+
+noinst_DATA = \
+       geoclue-manual.xml
+
+nodist_geoclue_manual_SOURCES = \
+       geoclue-manual-glue.h
+
+BUILT_SOURCES =                        \
+       $(nodist_geoclue_manual_SOURCES)
+
+geoclue_manual_SOURCES =       \
+       geoclue-manual.c
+
+geoclue_manual_CFLAGS = \
+       -I$(top_srcdir)     \
+       -I$(top_builddir)   \
+       $(GEOCLUE_CFLAGS)
+
+geoclue_manual_LDADD = \
+       $(GEOCLUE_LIBS)    \
+       $(top_builddir)/geoclue/libgeoclue.la
+
+
+providersdir = $(datadir)/geoclue-providers
+providers_DATA = geoclue-manual.provider
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Providers.Manual.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+CLEANFILES = \
+       stamp-geoclue-manual-glue.h
+
+EXTRA_DIST =                   \
+       $(service_in_files)     \
+       $(providers_DATA)       \
+       $(noinst_DATA)
+
+DISTCLEANFILES =       \
+       $(service_DATA) \
+       $(nodist_geoclue_manual_SOURCES)
+
+%-glue.h: stamp-%-glue.h
+       @true
+
+stamp-geoclue-manual-glue.h: geoclue-manual.xml
+       $(DBUS_BINDING_TOOL) --prefix=geoclue_manual --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F) \
+       && echo timestamp > $(@F)
diff --git a/providers/manual/geoclue-manual.c b/providers/manual/geoclue-manual.c
new file mode 100644 (file)
index 0000000..b0a7922
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * Geoclue
+ * geoclue-manual.c - Manual address provider
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/** Geoclue manual provider
+ *
+ * This is an address provider which gets its address data from user
+ * input. No UI is included, any application may query the address from
+ * the user and submit it to manual provider through the D-Bus API:
+ *    org.freedesktop.Geoclue.Manual.SetAddress
+ *    org.freedesktop.Geoclue.Manual.SetAddressFields
+ *
+ * SetAddress allows setting the current address as a GeoclueAddress,
+ * while SetAddressFields is a convenience version with separate
+ * address fields. Shell example using SetAddressFields:
+ *
+ * dbus-send --print-reply --type=method_call \
+ *           --dest=org.freedesktop.Geoclue.Providers.Manual \
+ *           /org/freedesktop/Geoclue/Providers/Manual \
+ *           org.freedesktop.Geoclue.Manual.SetAddressFields \
+ *           int32:7200 \
+ *           string: \
+ *           string:"Finland" \
+ *           string: \
+ *           string:"Helsinki" \
+ *           string: \
+ *           string: \
+ *           string:"Solnantie 24"
+ *
+ * This would make the provider emit a AddressChanged signal with
+ * accuracy level GEOCLUE_ACCURACY_STREET. Unless new SetAddress* calls
+ * are made, provider will emit another signal in two hours (7200 sec),
+ * with empty address and GEOCLUE_ACCURACY_NONE.
+ **/
+
+#include <config.h>
+#include <string.h>
+#include <dbus/dbus-glib-bindings.h>
+#include <dbus/dbus.h>
+
+#include <geoclue/gc-provider.h>
+#include <geoclue/gc-iface-address.h>
+
+typedef struct {
+       GcProvider parent;
+
+       GMainLoop *loop;
+
+       guint event_id;
+
+       int timestamp;
+       GHashTable *address;
+       GeoclueAccuracy *accuracy;
+} GeoclueManual;
+
+typedef struct {
+       GcProviderClass parent_class;
+} GeoclueManualClass;
+
+#define GEOCLUE_TYPE_MANUAL (geoclue_manual_get_type ())
+#define GEOCLUE_MANUAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_MANUAL, GeoclueManual))
+
+static void geoclue_manual_address_init (GcIfaceAddressClass *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueManual, geoclue_manual, GC_TYPE_PROVIDER,
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS,
+                                                geoclue_manual_address_init))
+
+static gboolean
+geoclue_manual_set_address (GeoclueManual *manual,
+                            int valid_until,
+                            GHashTable *address,
+                            GError **error);
+
+static gboolean
+geoclue_manual_set_address_fields (GeoclueManual *manual,
+                                   int valid_until,
+                                   char *country_code,
+                                   char *country,
+                                   char *region,
+                                   char *locality,
+                                   char *area,
+                                   char *postalcode,
+                                   char *street,
+                                   GError **error);
+
+#include "geoclue-manual-glue.h"
+
+
+static GeoclueAccuracyLevel
+get_accuracy_for_address (GHashTable *address)
+{
+       if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_STREET)) {
+               return GEOCLUE_ACCURACY_LEVEL_STREET;
+       } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_POSTALCODE)) {
+               return GEOCLUE_ACCURACY_LEVEL_POSTALCODE;
+       } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_LOCALITY)) {
+               return GEOCLUE_ACCURACY_LEVEL_LOCALITY;
+       } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_REGION)) {
+               return GEOCLUE_ACCURACY_LEVEL_REGION;
+       } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_COUNTRY) ||
+                  g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_COUNTRYCODE)) {
+               return GEOCLUE_ACCURACY_LEVEL_COUNTRY;
+       }
+       return GEOCLUE_ACCURACY_LEVEL_NONE;
+}
+
+static gboolean
+get_status (GcIfaceGeoclue *gc,
+           GeoclueStatus  *status,
+           GError        **error)
+{
+       *status = GEOCLUE_STATUS_AVAILABLE;
+       return TRUE;
+}
+
+static void
+shutdown (GcProvider *provider)
+{
+       GeoclueManual *manual;
+
+       manual = GEOCLUE_MANUAL (provider);
+       g_main_loop_quit (manual->loop);
+}
+
+gboolean
+validity_ended (GeoclueManual *manual)
+{
+       manual->event_id = 0;
+       g_hash_table_remove_all (manual->address);
+       geoclue_accuracy_set_details (manual->accuracy,
+                                     GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0);
+
+       gc_iface_address_emit_address_changed (GC_IFACE_ADDRESS (manual),
+                                              manual->timestamp,
+                                              manual->address,
+                                              manual->accuracy);
+       return FALSE;
+}
+
+
+static void
+geoclue_manual_set_address_common (GeoclueManual *manual,
+                                   int valid_for,
+                                   GHashTable *address)
+{
+       if (manual->event_id > 0) {
+               g_source_remove (manual->event_id);
+       }
+
+       manual->timestamp = time (NULL);
+
+       g_hash_table_destroy (manual->address);
+       manual->address = address;
+
+       geoclue_accuracy_set_details (manual->accuracy,
+                                     get_accuracy_for_address (address),
+                                     0, 0);
+
+       gc_iface_address_emit_address_changed (GC_IFACE_ADDRESS (manual),
+                                              manual->timestamp,
+                                              manual->address,
+                                              manual->accuracy);
+
+       if (valid_for > 0) {
+               manual->event_id = g_timeout_add (valid_for * 1000,
+                                                 (GSourceFunc)validity_ended,
+                                                 manual);
+       }
+}
+
+static gboolean
+geoclue_manual_set_address (GeoclueManual *manual,
+                            int valid_for,
+                            GHashTable *address,
+                            GError **error)
+{
+       geoclue_manual_set_address_common (manual,
+                                          valid_for,
+                                          geoclue_address_details_copy (address));
+       return TRUE;
+}
+
+static gboolean
+geoclue_manual_set_address_fields (GeoclueManual *manual,
+                                   int valid_for,
+                                   char *country_code,
+                                   char *country,
+                                   char *region,
+                                   char *locality,
+                                   char *area,
+                                   char *postalcode,
+                                   char *street,
+                                   GError **error)
+{
+       GHashTable *address;
+
+       address = geoclue_address_details_new ();
+       if (country_code && (strlen (country_code) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_COUNTRYCODE),
+                                    g_strdup (country_code));
+       }
+       if (country && (strlen (country) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_COUNTRY),
+                                    g_strdup (country));
+       }
+       if (region && (strlen (region) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_REGION),
+                                    g_strdup (region));
+       }
+       if (locality && (strlen (locality) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_LOCALITY),
+                                    g_strdup (locality));
+       }
+       if (area && (strlen (area) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_AREA),
+                                    g_strdup (area));
+       }
+       if (postalcode && (strlen (postalcode) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_POSTALCODE),
+                                    g_strdup (postalcode));
+       }
+       if (street && (strlen (street) > 0)) {
+               g_hash_table_insert (address,
+                                    g_strdup (GEOCLUE_ADDRESS_KEY_STREET),
+                                    g_strdup (street));
+       }
+
+       geoclue_manual_set_address_common (manual,
+                                          valid_for,
+                                          address);
+       return TRUE;
+}
+
+
+static void
+finalize (GObject *object)
+{
+       GeoclueManual *manual;
+
+       manual = GEOCLUE_MANUAL (object);
+
+       g_hash_table_destroy (manual->address);
+       geoclue_accuracy_free (manual->accuracy);
+
+       ((GObjectClass *) geoclue_manual_parent_class)->finalize (object);
+}
+
+static void
+geoclue_manual_class_init (GeoclueManualClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+       GcProviderClass *p_class = (GcProviderClass *) klass;
+
+       o_class->finalize = finalize;
+
+       p_class->get_status = get_status;
+       p_class->shutdown = shutdown;
+
+       dbus_g_object_type_install_info (geoclue_manual_get_type (),
+                                        &dbus_glib_geoclue_manual_object_info);
+}
+
+static void
+geoclue_manual_init (GeoclueManual *manual)
+{
+       gc_provider_set_details (GC_PROVIDER (manual),
+                                "org.freedesktop.Geoclue.Providers.Manual",
+                                "/org/freedesktop/Geoclue/Providers/Manual",
+                                "Manual", "Manual provider");
+
+       manual->address = geoclue_address_details_new ();
+       manual->accuracy =
+               geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0);
+}
+
+static gboolean
+get_address (GcIfaceAddress   *gc,
+             int              *timestamp,
+             GHashTable      **address,
+             GeoclueAccuracy **accuracy,
+             GError          **error)
+{
+       GeoclueManual *manual = GEOCLUE_MANUAL (gc);
+
+
+       if (timestamp) {
+               *timestamp = manual->timestamp;
+       }
+       if (address) {
+               *address = geoclue_address_details_copy (manual->address);
+       }
+       if (accuracy) {
+               *accuracy = geoclue_accuracy_copy (manual->accuracy);
+       }
+
+       return TRUE;
+}
+
+static void
+geoclue_manual_address_init (GcIfaceAddressClass *iface)
+{
+       iface->get_address = get_address;
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+       GeoclueManual *manual;
+
+       g_type_init ();
+
+       manual = g_object_new (GEOCLUE_TYPE_MANUAL, NULL);
+       manual->loop = g_main_loop_new (NULL, TRUE);
+
+       g_main_loop_run (manual->loop);
+
+       g_main_loop_unref (manual->loop);
+       g_object_unref (manual);
+
+       return 0;
+}
diff --git a/providers/manual/geoclue-manual.provider b/providers/manual/geoclue-manual.provider
new file mode 100755 (executable)
index 0000000..c45a9da
--- /dev/null
@@ -0,0 +1,7 @@
+[Geoclue Provider]
+Name=Manual
+Service=org.freedesktop.Geoclue.Providers.Manual
+Path=/org/freedesktop/Geoclue/Providers/Manual
+Interfaces=org.freedesktop.Geoclue.Address
+Provides=ProvidesUpdates
+Accuracy=Street
diff --git a/providers/manual/geoclue-manual.xml b/providers/manual/geoclue-manual.xml
new file mode 100755 (executable)
index 0000000..9569a46
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/">
+  <interface name="org.freedesktop.Geoclue.Manual">
+    <method name="SetAddress">
+      <arg type="i" name="valid_for" direction="in"/>
+      <arg name="address" type="a{ss}" direction="in"/>
+    </method>
+    <method name="SetAddressFields">
+      <arg type="i" name="valid_for" direction="in"/>
+      <arg type="s" name="countrycode" direction="in"/>
+      <arg type="s" name="country" direction="in"/>
+      <arg type="s" name="region" direction="in"/>
+      <arg type="s" name="locality" direction="in"/>
+      <arg type="s" name="area" direction="in"/>
+      <arg type="s" name="postalcode" direction="in"/>
+      <arg type="s" name="street" direction="in"/>
+    </method>
+  </interface>
+</node>
diff --git a/providers/manual/org.freedesktop.Geoclue.Providers.Manual.service.in b/providers/manual/org.freedesktop.Geoclue.Providers.Manual.service.in
new file mode 100755 (executable)
index 0000000..79e74c1
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Providers.Manual
+Exec=@libexecdir@/geoclue-manual
diff --git a/providers/nominatim/Makefile.am b/providers/nominatim/Makefile.am
new file mode 100644 (file)
index 0000000..9fac2da
--- /dev/null
@@ -0,0 +1,35 @@
+libexec_PROGRAMS = \
+       geoclue-nominatim
+
+NOINST_H_FILES =               \
+       geoclue-nominatim.h
+
+geoclue_nominatim_SOURCES =    \
+       $(NOINST_H_FILES)       \
+       geoclue-nominatim.c
+
+geoclue_nominatim_CFLAGS = \
+       -I$(top_srcdir) \
+       -I$(top_builddir) \
+       $(GEOCLUE_CFLAGS)
+
+geoclue_nominatim_LDADD = \
+       $(GEOCLUE_LIBS) \
+       $(top_builddir)/geoclue/libgeoclue.la
+
+providersdir = $(datadir)/geoclue-providers
+providers_DATA = geoclue-nominatim.provider
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Providers.Nominatim.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+EXTRA_DIST =                   \
+       $(service_in_files)     \
+       $(providers_DATA)
+
+DISTCLEANFILES = \
+       $(service_DATA)
diff --git a/providers/nominatim/geoclue-nominatim.c b/providers/nominatim/geoclue-nominatim.c
new file mode 100755 (executable)
index 0000000..342b600
--- /dev/null
@@ -0,0 +1,763 @@
+/*
+ * Geoclue
+ * geoclue-nominatim.c - A nominatim.openstreetmap.org-based "Geocode" and
+ *                          "Reverse geocode" provider
+ *
+ * Copyright 2010 by Intel Corporation
+ *
+ * Author: Jussi Kukkonen <jku@linux.intel.com>
+ */
+
+/*
+ * The used web service APIs are documented at
+ * http://wiki.openstreetmap.org/wiki/Nominatim
+ *
+ */
+
+#include <config.h>
+
+#include <time.h>
+#include <string.h>
+#include <dbus/dbus-glib-bindings.h>
+
+#include <geoclue/gc-provider.h>
+#include <geoclue/geoclue-address-details.h>
+#include <geoclue/geoclue-landmark.h>
+#include <geoclue/geoclue-error.h>
+#include <geoclue/gc-iface-geocode.h>
+#include <geoclue/gc-iface-poi.h>
+#include <geoclue/gc-iface-reverse-geocode.h>
+#include "geoclue-nominatim.h"
+
+
+#define GEOCLUE_NOMINATIM_DBUS_SERVICE "org.freedesktop.Geoclue.Providers.Nominatim"
+#define GEOCLUE_NOMINATIM_DBUS_PATH "/org/freedesktop/Geoclue/Providers/Nominatim"
+
+#define GEOCODE_URL "http://nominatim.openstreetmap.org/search"
+#define REV_GEOCODE_URL "http://nominatim.openstreetmap.org/reverse"
+#define POI_URL "http://nominatim.openstreetmap.org/search"
+
+#define NOMINATIM_HOUSE "//reversegeocode/addressparts/house"
+#define NOMINATIM_ROAD "//reversegeocode/addressparts/road"
+#define NOMINATIM_VILLAGE "//reversegeocode/addressparts/village"
+#define NOMINATIM_SUBURB "//reversegeocode/addressparts/suburb"
+#define NOMINATIM_CITY "//reversegeocode/addressparts/city"
+#define NOMINATIM_POSTCODE "//reversegeocode/addressparts/postcode"
+#define NOMINATIM_COUNTY "//reversegeocode/addressparts/county"
+#define NOMINATIM_COUNTRY "//reversegeocode/addressparts/country"
+#define NOMINATIM_COUNTRYCODE "//reversegeocode/addressparts/country_code"
+
+#define NOMINATIM_LAT "//searchresults/place[1]/@lat"
+#define NOMINATIM_LON "//searchresults/place[1]/@lon"
+#define NOMINATIM_LATLON_HOUSE "//searchresults/place[1]/house"
+#define NOMINATIM_LATLON_ROAD "//searchresults/place[1]/road"
+#define NOMINATIM_LATLON_VILLAGE "//searchresults/place[1]/village"
+#define NOMINATIM_LATLON_SUBURB "//searchresults/place[1]/suburb"
+#define NOMINATIM_LATLON_POSTCODE "//searchresults/place[1]/postcode"
+#define NOMINATIM_LATLON_CITY "//searchresults/place[1]/city"
+#define NOMINATIM_LATLON_COUNTY "//searchresults/place[1]/county"
+#define NOMINATIM_LATLON_COUNTRY "//searchresults/place[1]/country"
+#define NOMINATIM_LATLON_COUNTRYCODE "//searchresults/place[1]/countrycode"
+
+#define NOMINATIM_SEARCH                       "//searchresults/place[%d]"
+#define NOMINATIM_SEARCH_ID                    NOMINATIM_SEARCH"/@place_id"
+#define NOMINATIM_SEARCH_RANK                  NOMINATIM_SEARCH"/@place_rank"
+#define NOMINATIM_SEARCH_BOUNDINGBOX           NOMINATIM_SEARCH"/@boudingbox"
+#define NOMINATIM_SEARCH_DISPLAY_NAME          NOMINATIM_SEARCH"/@display_name"
+#define NOMINATIM_SEARCH_ICON                  NOMINATIM_SEARCH"/@icon"
+#define NOMINATIM_SEARCH_LAT                   NOMINATIM_SEARCH"/@lat"
+#define NOMINATIM_SEARCH_LON                   NOMINATIM_SEARCH"/@lon"
+#define NOMINATIM_SEARCH_HOUSE                         NOMINATIM_SEARCH"/house"
+#define NOMINATIM_SEARCH_ROAD                  NOMINATIM_SEARCH"/road"
+#define NOMINATIM_SEARCH_VILLAGE               NOMINATIM_SEARCH"/village"
+#define NOMINATIM_SEARCH_SUBURB                NOMINATIM_SEARCH"/suburb"
+#define NOMINATIM_SEARCH_POSTCODE              NOMINATIM_SEARCH"/postcode"
+#define NOMINATIM_SEARCH_CITY                  NOMINATIM_SEARCH"/city"
+#define NOMINATIM_SEARCH_COUNTY                NOMINATIM_SEARCH"/county"
+#define NOMINATIM_SEARCH_COUNTRY               NOMINATIM_SEARCH"/country"
+#define NOMINATIM_SEARCH_COUNTRYCODE           NOMINATIM_SEARCH"/countrycode"
+
+
+
+
+static void geoclue_nominatim_init (GeoclueNominatim *obj);
+static void geoclue_nominatim_geocode_init (GcIfaceGeocodeClass *iface);
+static void geoclue_nominatim_reverse_geocode_init (GcIfaceReverseGeocodeClass *iface);
+static void geoclue_nominatim_poi_init (GcIfacePoiClass *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueNominatim, geoclue_nominatim, GC_TYPE_PROVIDER,
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_GEOCODE,
+                                                geoclue_nominatim_geocode_init)
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_REVERSE_GEOCODE,
+                                                geoclue_nominatim_reverse_geocode_init)
+                        G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POI,
+                                               geoclue_nominatim_poi_init))
+
+/* Geoclue interface implementation */
+
+static gboolean
+geoclue_nominatim_get_status (GcIfaceGeoclue *iface,
+                              GeoclueStatus  *status,
+                              GError        **error)
+{
+       /* Assumption that we are available so long as the
+          providers requirements are met: ie network is up */
+       *status = GEOCLUE_STATUS_AVAILABLE;
+
+       return TRUE;
+}
+
+static void
+shutdown (GcProvider *provider)
+{
+       GeoclueNominatim *obj = GEOCLUE_NOMINATIM (provider);
+
+       g_main_loop_quit (obj->loop);
+}
+
+
+static void
+search_string_append (GString *str, const char *val)
+{
+       if (!val || strlen (val) == 0) {
+               return;
+       }
+
+       if (str->len != 0) {
+               g_string_append (str, ", ");
+       }
+       g_string_append (str, val);
+}
+
+static GeoclueAccuracy*
+get_geocode_accuracy (GcWebService *geocoder)
+{
+       char *str;
+       GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE;
+
+       if (gc_web_service_get_string (geocoder, &str, NOMINATIM_LATLON_HOUSE)) {
+               level = GEOCLUE_ACCURACY_LEVEL_DETAILED;
+       } else if (gc_web_service_get_string (geocoder, &str,
+                                             NOMINATIM_LATLON_ROAD)) {
+               level = GEOCLUE_ACCURACY_LEVEL_STREET;
+       } else if (gc_web_service_get_string (geocoder, &str,
+                                             NOMINATIM_LATLON_SUBURB) ||
+                  gc_web_service_get_string (geocoder, &str,
+                                             NOMINATIM_LATLON_POSTCODE) ||
+                  gc_web_service_get_string (geocoder, &str,
+                                             NOMINATIM_LATLON_VILLAGE)) {
+               level = GEOCLUE_ACCURACY_LEVEL_POSTALCODE;
+       } else if (gc_web_service_get_string (geocoder, &str,
+                                             NOMINATIM_LATLON_CITY)) {
+               level = GEOCLUE_ACCURACY_LEVEL_LOCALITY;
+       } else if (gc_web_service_get_string (geocoder, &str,
+                                             NOMINATIM_LATLON_COUNTY)) {
+               level = GEOCLUE_ACCURACY_LEVEL_REGION;
+       } else if (gc_web_service_get_string (geocoder, &str,
+                                             NOMINATIM_LATLON_COUNTRY) ||
+                  gc_web_service_get_string (geocoder, &str,
+                                             NOMINATIM_LATLON_COUNTRYCODE)) {
+               level = GEOCLUE_ACCURACY_LEVEL_COUNTRY;
+       }
+
+       return geoclue_accuracy_new (level, 0, 0);
+}
+
+/* Geocode interface implementation */
+static gboolean
+geoclue_nominatim_address_to_position (GcIfaceGeocode        *iface,
+                                       GHashTable            *address,
+                                       GeocluePositionFields *fields,
+                                       double                *latitude,
+                                       double                *longitude,
+                                       double                *altitude,
+                                       GeoclueAccuracy      **accuracy,
+                                       GError               **error)
+{
+       GeoclueNominatim *obj = GEOCLUE_NOMINATIM (iface);
+       gchar *country, *region, *locality, *postalcode, *street;
+       GString *str;
+
+       country = g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_COUNTRY);
+       locality = g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_LOCALITY);
+       postalcode = g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_POSTALCODE);
+       region = g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_REGION);
+       street = g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_STREET);
+
+       str = g_string_new ("");
+       search_string_append (str, street);
+       search_string_append (str, locality);
+       search_string_append (str, region);
+       search_string_append (str, postalcode);
+       search_string_append (str, country);
+
+       if (!gc_web_service_query (obj->geocoder, error,
+                                  "q", str->str,
+                                  "format", "xml",
+                                  "polygon", "0",
+                                  "addressdetails", "1",
+                                  (char *)0)) {
+               g_string_free (str, TRUE);
+               return FALSE;
+       }
+       g_string_free (str, TRUE);
+
+       *fields = GEOCLUE_POSITION_FIELDS_NONE;
+       if (latitude && gc_web_service_get_double (obj->geocoder,
+                                                  latitude, NOMINATIM_LAT)) {
+               *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE;
+       }
+
+       if (longitude &&  gc_web_service_get_double (obj->geocoder,
+                                                    longitude, NOMINATIM_LON)) {
+               *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE;
+       }
+
+       if (accuracy) {
+               *accuracy = get_geocode_accuracy (obj->geocoder);
+       }
+
+       return TRUE;
+}
+
+static gboolean
+geoclue_nominatim_freeform_address_to_position (GcIfaceGeocode        *iface,
+                                                const char            *address,
+                                                GeocluePositionFields *fields,
+                                                double                *latitude,
+                                                double                *longitude,
+                                                double                *altitude,
+                                                GeoclueAccuracy      **accuracy,
+                                                GError               **error)
+{
+       GeoclueNominatim *obj = GEOCLUE_NOMINATIM (iface);
+
+       if (!gc_web_service_query (obj->geocoder, error,
+                                  "q", address,
+                                  "format", "xml",
+                                  "polygon", "0",
+                                  "addressdetails", "1",
+                                  (char *)0)) {
+               return FALSE;
+       }
+
+       *fields = GEOCLUE_POSITION_FIELDS_NONE;
+       if (latitude && gc_web_service_get_double (obj->geocoder,
+                                                  latitude, NOMINATIM_LAT)) {
+               *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE;
+       }
+
+       if (longitude &&  gc_web_service_get_double (obj->geocoder,
+                                                    longitude, NOMINATIM_LON)) {
+               *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE;
+       }
+
+       if (accuracy) {
+               *accuracy = get_geocode_accuracy (obj->geocoder);
+       }
+
+       return TRUE;
+}
+
+/* ReverseGeocode interface implementation */
+
+static gboolean
+geoclue_nominatim_position_to_address (GcIfaceReverseGeocode  *iface,
+                                       double                  latitude,
+                                       double                  longitude,
+                                       GeoclueAccuracy        *position_accuracy,
+                                       GHashTable            **address,
+                                       GeoclueAccuracy       **address_accuracy,
+                                       GError                **error)
+{
+       GeoclueNominatim *obj = GEOCLUE_NOMINATIM (iface);
+       gchar *locality = NULL;
+       gchar *region = NULL;
+       gchar *country = NULL;
+       gchar *countrycode = NULL;
+       gchar *area = NULL;
+       gchar *street = NULL;
+       gchar *postcode = NULL;
+
+       GeoclueAccuracyLevel in_acc = GEOCLUE_ACCURACY_LEVEL_DETAILED;
+       gchar lat[G_ASCII_DTOSTR_BUF_SIZE];
+       gchar lon[G_ASCII_DTOSTR_BUF_SIZE];
+
+       if (!address) {
+               return TRUE;
+       }
+
+       g_ascii_dtostr (lat, G_ASCII_DTOSTR_BUF_SIZE, latitude);
+       g_ascii_dtostr (lon, G_ASCII_DTOSTR_BUF_SIZE, longitude);
+       if (!gc_web_service_query (obj->rev_geocoder, error,
+                                  "lat", lat,
+                                  "lon", lon,
+                                  "format", "xml",
+                                  "zoom", "18", /* could set this based on position_accuracy */
+                               "addressdetails", "1",
+                                  (char *)0)) {
+               return FALSE;
+       }
+
+       if (position_accuracy) {
+               geoclue_accuracy_get_details (position_accuracy, &in_acc, NULL, NULL);
+       }
+
+       *address = geoclue_address_details_new ();
+
+       if (in_acc >= GEOCLUE_ACCURACY_LEVEL_COUNTRY &&
+           gc_web_service_get_string (obj->rev_geocoder,
+                                      &countrycode, NOMINATIM_COUNTRYCODE)) {
+               geoclue_address_details_insert (*address,
+                                               GEOCLUE_ADDRESS_KEY_COUNTRYCODE,
+                                               countrycode);
+               g_free (countrycode);
+               geoclue_address_details_set_country_from_code (*address);
+       }
+       if (!g_hash_table_lookup (*address, GEOCLUE_ADDRESS_KEY_COUNTRY) &&
+           in_acc >= GEOCLUE_ACCURACY_LEVEL_COUNTRY &&
+           gc_web_service_get_string (obj->rev_geocoder,
+                                      &country, NOMINATIM_COUNTRY)) {
+               geoclue_address_details_insert (*address,
+                                               GEOCLUE_ADDRESS_KEY_COUNTRY,
+                                               country);
+               g_free (country);
+       }
+       if (in_acc >= GEOCLUE_ACCURACY_LEVEL_REGION &&
+           gc_web_service_get_string (obj->rev_geocoder,
+                                      &region, NOMINATIM_COUNTY)) {
+               geoclue_address_details_insert (*address,
+                                               GEOCLUE_ADDRESS_KEY_REGION,
+                                               region);
+               g_free (region);
+       }
+       if (in_acc >= GEOCLUE_ACCURACY_LEVEL_LOCALITY &&
+           gc_web_service_get_string (obj->rev_geocoder,
+                                      &locality, NOMINATIM_CITY)) {
+               geoclue_address_details_insert (*address,
+                                               GEOCLUE_ADDRESS_KEY_LOCALITY,
+                                               locality);
+               g_free (locality);
+       }
+       if (in_acc >= GEOCLUE_ACCURACY_LEVEL_POSTALCODE &&
+           gc_web_service_get_string (obj->rev_geocoder,
+                                      &area, NOMINATIM_VILLAGE)) {
+               geoclue_address_details_insert (*address,
+                                               GEOCLUE_ADDRESS_KEY_AREA,
+                                               area);
+               g_free (area);
+       }
+       if (in_acc >= GEOCLUE_ACCURACY_LEVEL_POSTALCODE &&
+           gc_web_service_get_string (obj->rev_geocoder,
+                                      &postcode, NOMINATIM_POSTCODE)) {
+               geoclue_address_details_insert (*address,
+                                               GEOCLUE_ADDRESS_KEY_POSTALCODE,
+                                               postcode);
+               g_free (postcode);
+       }
+       if (in_acc >= GEOCLUE_ACCURACY_LEVEL_STREET &&
+           gc_web_service_get_string (obj->rev_geocoder,
+                                      &street, NOMINATIM_ROAD)) {
+               char *nr;
+
+               if (gc_web_service_get_string (obj->rev_geocoder,
+                                              &nr, NOMINATIM_HOUSE)) {
+                       char *full_street = g_strdup_printf ("%s %s", street, nr);
+                       geoclue_address_details_insert (*address,
+                                                       GEOCLUE_ADDRESS_KEY_STREET,
+                                                       full_street);
+                       g_free (nr);
+                       g_free (full_street);
+               } else  {
+                       geoclue_address_details_insert (*address,
+                                                       GEOCLUE_ADDRESS_KEY_STREET,
+                                                       street);
+               }
+               g_free (street);
+       }
+
+       if (address_accuracy) {
+               GeoclueAccuracyLevel level = geoclue_address_details_get_accuracy_level (*address);
+               *address_accuracy = geoclue_accuracy_new (level, 0.0, 0.0);
+       }
+       return TRUE;
+}
+
+gboolean _parsing_boundary (char *boundary_src, gdouble *top, gdouble *left, gdouble *bottom, gdouble *right)
+{
+       g_return_val_if_fail (boundary_src, FALSE);
+
+       char *ptr = NULL;
+
+       ptr = strtok (boundary_src, ",");
+       if (!ptr) return FALSE;
+       *top = atof (ptr);
+
+       ptr = strtok (NULL, ",");
+       if (!ptr) return FALSE;
+       *left = atof (ptr);
+
+       ptr = strtok (NULL, ",");
+       if (!ptr) return FALSE;
+       *bottom = atof (ptr);
+
+       ptr = strtok (NULL, ",");
+       if (!ptr) return FALSE;
+       *right = atof (ptr);
+
+       return TRUE;
+}
+
+gboolean _get_landmark_data (GeoclueNominatim *obj, int index, GeoclueLandmark *landmark_info)
+{
+       g_return_val_if_fail (index > -1, FALSE);
+       g_return_val_if_fail (landmark_info, FALSE);
+
+       gdouble left = 0.0, top = 0.0, right = 0.0, bottom = 0.0;
+       gboolean ret = FALSE;
+
+       gchar buf[128] = {0,};
+       gchar *str = NULL;
+
+
+       snprintf(buf, 128, NOMINATIM_SEARCH_ID, index);
+       if (!gc_web_service_get_string(obj->poi, &str, buf)) {
+               return FALSE;
+       }
+
+       if (str) {
+               landmark_info->id = atoi (str);
+               g_free(str);
+       }
+
+       snprintf(buf, 128, NOMINATIM_SEARCH_RANK, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->rank = atoi (str);
+               g_free(str);
+       }
+
+       snprintf(buf, 128, NOMINATIM_SEARCH_ICON, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->icon = g_strdup(str);
+               g_free (str);
+       }
+       snprintf(buf, 128, NOMINATIM_SEARCH_DISPLAY_NAME, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->name = g_strdup(str);
+               g_free (str);
+       }
+
+       snprintf(buf, 128, NOMINATIM_SEARCH_BOUNDINGBOX, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               ret = _parsing_boundary (str, &top, &left, &bottom, &right);
+               if (ret) {
+                       landmark_info->boundary_left = left;
+                       landmark_info->boundary_top = top;
+                       landmark_info->boundary_right = right;
+                       landmark_info->boundary_bottom = bottom;
+               }
+       }
+
+       snprintf(buf, 128, NOMINATIM_SEARCH_LAT, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->lat = atof (str);
+       }
+
+       snprintf(buf, 128, NOMINATIM_SEARCH_LON, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->lon = atof (str);
+       }
+
+       snprintf(buf, 128, NOMINATIM_SEARCH_HOUSE, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->house = g_strdup(str);
+               g_free(str);
+       }
+       snprintf(buf, 128, NOMINATIM_SEARCH_ROAD, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->road = g_strdup(str);
+               g_free(str);
+       }
+
+       snprintf(buf, 128, NOMINATIM_SEARCH_VILLAGE, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->village = g_strdup(str);
+               g_free(str);
+       }
+
+       snprintf(buf, 128, NOMINATIM_SEARCH_SUBURB, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->suburb = g_strdup(str);
+               g_free(str);
+       }
+
+       snprintf(buf, 128, NOMINATIM_SEARCH_POSTCODE, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->postcode = g_strdup(str);
+               g_free(str);
+       }
+       snprintf(buf, 128, NOMINATIM_SEARCH_CITY, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->city = g_strdup(str);
+               g_free(str);
+       }
+
+       snprintf(buf, 128, NOMINATIM_SEARCH_COUNTY, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->county = g_strdup(str);
+               g_free(str);
+       }
+
+       snprintf(buf, 128, NOMINATIM_SEARCH_COUNTRY, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->country = g_strdup(str);
+               g_free(str);
+       }
+
+       snprintf(buf, 128, NOMINATIM_SEARCH_COUNTRYCODE, index);
+       if (gc_web_service_get_string(obj->poi, &str, buf)) {
+               landmark_info->country_code = g_strdup(str);
+               g_free(str);
+       }
+
+       return TRUE;
+}
+
+
+/* Poi interface implementation */
+static gboolean
+geoclue_nominatim_poi_search_by_position (GcIfacePoi   *iface,
+                                       const char      *keyword,
+                                       const char      *lang,
+                                       const char      *country_code,
+                                       int             limit,
+                                       double          left,
+                                       double          top,
+                                       double          right,
+                                       double          bottom,
+                                       int             *count,
+                                       GPtrArray       **landmark,
+                                       GError          **error)
+{
+       g_return_val_if_fail (landmark, FALSE);
+
+       GeoclueNominatim *obj = GEOCLUE_NOMINATIM (iface);
+       *landmark = NULL;
+
+       int index = 1;
+       gboolean ret = FALSE;
+       gchar str_limit [6] = {0, };
+       GeoclueLandmark landmark_data = {0, };
+
+
+       snprintf(str_limit, 6, "%d", limit);
+
+       if (left || top || right || bottom) {
+               /* Viewbox is available */
+               gchar viewbox[64] = {0, };
+
+               /* VIEWBOX FORMAT (LEFT_TOP_LONGITUDE,LEFT_TOP_LATITUDE, RIGHT_BOTTOM_LONGITUDE, RIGHT_BOTTOM_LATITUDE */
+               snprintf(viewbox, 64, "%d,%d,%d,%d", top, left, bottom, right);
+
+               if (country_code) {
+                       if (!gc_web_service_query (obj->poi, error,
+                                               "q", keyword,
+                                               "accept-language", lang,
+                                               "countrycodes", country_code,
+                                               "limit", str_limit,
+                                               "viewbox", viewbox,
+                                               "format", "xml",
+                                               "bounded", "1",
+                                               "polygon", "0",
+                                               "addressdetails", "1",
+                                               (char *)0)) {
+                               return FALSE;
+                       }
+               }
+               else {
+                       if (!gc_web_service_query (obj->poi, error,
+                                               "q", keyword,
+                                               "accept-language", lang,
+                                               "limit", str_limit,
+                                               "viewbox", viewbox,
+                                               "format", "xml",
+                                               "bounded", "1",
+                                               "polygon", "0",
+                                               "addressdetails", "1",
+                                               (char *)0)) {
+                               return FALSE;
+                       }
+               }
+       }
+       else {
+               /* There is no viewbox. */
+               if (country_code) {
+                       if (!gc_web_service_query (obj->poi, error,
+                                               "q", keyword,
+                                               "accept-language", lang,
+                                               "countrycodes", country_code,
+                                               "limit", str_limit,
+                                               "format", "xml",
+                                               "bounded", "0",
+                                               "polygon", "0",
+                                               "addressdetails", "1",
+                                               (char *)0)) {
+                               return FALSE;
+                       }
+               }
+               else {
+                       if (!gc_web_service_query (obj->poi, error,
+                                               "q", keyword,
+                                               "accept-language", lang,
+                                               "limit", str_limit,
+                                               "format", "xml",
+                                               "bounded", "0",
+                                               "polygon", "0",
+                                               "addressdetails", "1",
+                                               (char *)0)) {
+                               return FALSE;
+                       }
+               }
+       }
+
+       *landmark = g_ptr_array_new();
+
+       while (1) {
+               ret = _get_landmark_data (obj, index, &landmark_data);
+               if (ret == FALSE) {
+                       index--;
+                       break;
+               }
+
+               GValue v_poi = {0, };
+               g_value_init (&v_poi, GEOCLUE_LANDMARK);
+               g_value_take_boxed (&v_poi, dbus_g_type_specialized_construct (GEOCLUE_LANDMARK));
+
+               dbus_g_type_struct_set(&v_poi,
+                               0, landmark_data.id,
+                               1, landmark_data.rank,
+                               2, landmark_data.lat,
+                               3, landmark_data.lon,
+                               4, landmark_data.boundary_left,
+                               5, landmark_data.boundary_top,
+                               6, landmark_data.boundary_right,
+                               7, landmark_data.boundary_bottom,
+                               8, landmark_data.name,
+                               9, landmark_data.icon,
+                               10, landmark_data.house,
+                               11, landmark_data.road,
+                               12, landmark_data.village,
+                               13, landmark_data.suburb,
+                               14, landmark_data.city,
+                               15, landmark_data.county,
+                               16, landmark_data.country,
+                               17, landmark_data.country_code,
+                               G_MAXUINT);
+
+               g_ptr_array_add (*landmark, g_value_get_boxed(&v_poi));
+
+               index++;
+       }
+
+       *count = index;
+
+       return TRUE;
+}
+
+static void
+geoclue_nominatim_finalize (GObject *obj)
+{
+       ((GObjectClass *) geoclue_nominatim_parent_class)->finalize (obj);
+}
+
+static void
+geoclue_nominatim_dispose (GObject *obj)
+{
+       GeoclueNominatim *self = (GeoclueNominatim *) obj;
+
+       if (self->geocoder) {
+               g_object_unref (self->geocoder);
+               self->geocoder = NULL;
+       }
+
+       if (self->rev_geocoder) {
+               g_object_unref (self->rev_geocoder);
+               self->rev_geocoder = NULL;
+       }
+
+       if (self->poi) {
+               g_object_unref (self->poi);
+               self->poi = NULL;
+       }
+
+       ((GObjectClass *) geoclue_nominatim_parent_class)->dispose (obj);
+}
+
+/* Initialization */
+
+static void
+geoclue_nominatim_class_init (GeoclueNominatimClass *klass)
+{
+       GcProviderClass *p_class = (GcProviderClass *)klass;
+       GObjectClass *o_class = (GObjectClass *)klass;
+
+       p_class->shutdown = shutdown;
+       p_class->get_status = geoclue_nominatim_get_status;
+
+       o_class->finalize = geoclue_nominatim_finalize;
+       o_class->dispose = geoclue_nominatim_dispose;
+}
+
+static void
+geoclue_nominatim_init (GeoclueNominatim *obj)
+{
+       gc_provider_set_details (GC_PROVIDER (obj),
+                                GEOCLUE_NOMINATIM_DBUS_SERVICE,
+                                GEOCLUE_NOMINATIM_DBUS_PATH,
+                                "Nominatim", "Nominatim (OpenStreetMap geocoder) provider");
+
+       obj->geocoder = g_object_new (GC_TYPE_WEB_SERVICE, NULL);
+       gc_web_service_set_base_url (obj->geocoder, GEOCODE_URL);
+
+       obj->rev_geocoder = g_object_new (GC_TYPE_WEB_SERVICE, NULL);
+       gc_web_service_set_base_url (obj->rev_geocoder, REV_GEOCODE_URL);
+
+       obj->poi = g_object_new (GC_TYPE_WEB_SERVICE, NULL);
+       gc_web_service_set_base_url (obj->poi, GEOCODE_URL);
+}
+
+static void
+geoclue_nominatim_geocode_init (GcIfaceGeocodeClass *iface)
+{
+       iface->address_to_position = geoclue_nominatim_address_to_position;
+       iface->freeform_address_to_position = geoclue_nominatim_freeform_address_to_position;
+}
+
+static void
+geoclue_nominatim_poi_init (GcIfacePoiClass *iface)
+{
+       iface->search_by_position = geoclue_nominatim_poi_search_by_position;
+}
+
+static void
+geoclue_nominatim_reverse_geocode_init (GcIfaceReverseGeocodeClass *iface)
+{
+       iface->position_to_address = geoclue_nominatim_position_to_address;
+}
+
+int
+main()
+{
+       GeoclueNominatim *obj;
+
+       g_type_init();
+       obj = g_object_new (GEOCLUE_TYPE_NOMINATIM, NULL);
+       obj->loop = g_main_loop_new (NULL, TRUE);
+
+       g_main_loop_run (obj->loop);
+
+       g_main_loop_unref (obj->loop);
+       g_object_unref (obj);
+
+       return 0;
+}
diff --git a/providers/nominatim/geoclue-nominatim.h b/providers/nominatim/geoclue-nominatim.h
new file mode 100755 (executable)
index 0000000..5fbbd98
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Geoclue
+ * geoclue-nominatim.h - A Geocode/ReverseGeocode provider for nominatim.openstreetmap.org
+ *
+ * Author: Jussi Kukkonen <jku@linux.intel.com>
+ */
+
+#ifndef _GEOCLUE_NOMINATIM
+#define _GEOCLUE_NOMINATIM
+
+#include <glib-object.h>
+#include <geoclue/gc-web-service.h>
+
+G_BEGIN_DECLS
+
+
+#define GEOCLUE_TYPE_NOMINATIM (geoclue_nominatim_get_type ())
+
+#define GEOCLUE_NOMINATIM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_NOMINATIM, GeoclueNominatim))
+#define GEOCLUE_NOMINATIM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEOCLUE_TYPE_NOMINATIM, GeoclueNominatimClass))
+#define GEOCLUE_IS_NOMINATIM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_NOMINATIM))
+#define GEOCLUE_IS_NOMINATIM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEOCLUE_TYPE_NOMINATIM))
+
+typedef struct _GeoclueNominatim {
+       GcProvider parent;
+       GMainLoop *loop;
+
+       GcWebService *geocoder;
+       GcWebService *rev_geocoder;
+       GcWebService *poi;
+} GeoclueNominatim;
+
+typedef struct _GeoclueNominatimClass {
+       GcProviderClass parent_class;
+} GeoclueNominatimClass;
+
+typedef struct _GeocluePOIData {
+       gint id;
+       gint rank;
+       gdouble lat;
+       gdouble lon;
+       gdouble boundary_left;
+       gdouble boundary_top;
+       gdouble boudnary_right;
+       gdouble boundary_bottom;
+       gchar *name;
+       gchar *icon;
+       gchar *house;
+       gchar *road;
+       gchar *village;
+       gchar *suburb;
+       gchar *city;
+       gchar *county;
+       gchar *country;
+       gchar *country_code;
+} GeocluePOIData;
+
+GType geoclue_nominatim_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/providers/nominatim/geoclue-nominatim.provider b/providers/nominatim/geoclue-nominatim.provider
new file mode 100755 (executable)
index 0000000..618c60a
--- /dev/null
@@ -0,0 +1,7 @@
+[Geoclue Provider]
+Name=Nominatim (OpenStreetMap geocoder) Provider
+Service=org.freedesktop.Geoclue.Providers.Nominatim
+Path=/org/freedesktop/Geoclue/Providers/Nominatim
+Requires=RequiresNetwork
+Accuracy=Street
+Interfaces=org.freedesktop.Geoclue.Geocode;org.freedesktop.Geoclue.ReverseGeocode;org.freedesktop.Geoclue.Poi
diff --git a/providers/nominatim/org.freedesktop.Geoclue.Providers.Nominatim.service.in b/providers/nominatim/org.freedesktop.Geoclue.Providers.Nominatim.service.in
new file mode 100755 (executable)
index 0000000..b628568
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Providers.Nominatim
+Exec=@libexecdir@/geoclue-nominatim
diff --git a/providers/plazes/Makefile.am b/providers/plazes/Makefile.am
new file mode 100644 (file)
index 0000000..1cfa1cb
--- /dev/null
@@ -0,0 +1,31 @@
+libexec_PROGRAMS =     \
+       geoclue-plazes
+
+geoclue_plazes_SOURCES = \
+       geoclue-plazes.c
+
+geoclue_plazes_CFLAGS = \
+       -I$(top_srcdir) \
+       -I$(top_builddir) \
+       $(GEOCLUE_CFLAGS)
+
+geoclue_plazes_LDADD = \
+       $(GEOCLUE_LIBS) \
+       $(top_builddir)/geoclue/libgeoclue.la
+
+providersdir = $(datadir)/geoclue-providers
+providers_DATA = geoclue-plazes.provider
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Providers.Plazes.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+EXTRA_DIST =                   \
+       $(service_in_files)     \
+       $(providers_DATA)
+
+DISTCLEANFILES = \
+       $(service_DATA)
diff --git a/providers/plazes/geoclue-plazes.c b/providers/plazes/geoclue-plazes.c
new file mode 100644 (file)
index 0000000..d12b4a1
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * Geoclue
+ * geoclue-plazes.c - A plazes.com-based Address/Position provider
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib-object.h>
+#include <dbus/dbus-glib-bindings.h>
+
+#include <geoclue/gc-web-service.h>
+#include <geoclue/gc-provider.h>
+#include <geoclue/geoclue-error.h>
+#include <geoclue/gc-iface-position.h>
+#include <geoclue/gc-iface-address.h>
+
+#define GEOCLUE_DBUS_SERVICE_PLAZES "org.freedesktop.Geoclue.Providers.Plazes"
+#define GEOCLUE_DBUS_PATH_PLAZES "/org/freedesktop/Geoclue/Providers/Plazes"
+#define PLAZES_URL "http://plazes.com/suggestions.xml"
+#define PLAZES_KEY_MAC "mac_address"
+#define PLAZES_LAT_XPATH "//plaze/latitude"
+#define PLAZES_LON_XPATH "//plaze/longitude"
+
+#define GEOCLUE_TYPE_PLAZES (geoclue_plazes_get_type ())
+#define GEOCLUE_PLAZES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_PLAZES, GeocluePlazes))
+
+typedef struct _GeocluePlazes {
+       GcProvider parent;
+       GMainLoop *loop;
+       GcWebService *web_service;
+       GeoclueStatus last_status;
+} GeocluePlazes;
+
+typedef struct _GeocluePlazesClass {
+       GcProviderClass parent_class;
+} GeocluePlazesClass;
+
+
+static void geoclue_plazes_init (GeocluePlazes *plazes);
+static void geoclue_plazes_position_init (GcIfacePositionClass  *iface);
+static void geoclue_plazes_address_init (GcIfaceAddressClass  *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GeocluePlazes, geoclue_plazes, GC_TYPE_PROVIDER,
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION,
+                                                geoclue_plazes_position_init)
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS,
+                                                geoclue_plazes_address_init))
+
+
+/* Geoclue interface implementation */
+static gboolean
+geoclue_plazes_get_status (GcIfaceGeoclue *iface,
+                          GeoclueStatus  *status,
+                          GError        **error)
+{
+       GeocluePlazes *plazes = GEOCLUE_PLAZES (iface);
+
+       *status = plazes->last_status;
+       return TRUE;
+}
+
+static void
+shutdown (GcProvider *provider)
+{
+       GeocluePlazes *plazes = GEOCLUE_PLAZES (provider);
+       g_main_loop_quit (plazes->loop);
+}
+
+static void
+geoclue_plazes_set_status (GeocluePlazes *self, GeoclueStatus status)
+{
+       if (status != self->last_status) {
+               self->last_status = status;
+               gc_iface_geoclue_emit_status_changed (GC_IFACE_GEOCLUE (self), status);
+    }
+}
+
+/* Parse /proc/net/route to get default gateway address and then parse
+ * /proc/net/arp to find matching mac address.
+ *
+ * There are some problems with this. First, it's IPv4 only.
+ * Second, there must be a way to do this with ioctl, but that seemed really
+ * complicated... even /usr/sbin/arp parses /proc/net/arp
+ *
+ * returns:
+ *   1 : on success
+ *   0 : no success, no errors
+ *  <0 : error
+ */
+int
+get_mac_address (char **mac)
+{
+       char *content;
+       char **lines, **entry;
+       GError *error = NULL;
+       char *route_gateway = NULL;
+
+       g_assert (*mac == NULL);
+
+       if (!g_file_get_contents ("/proc/net/route", &content, NULL, &error)) {
+               g_warning ("Failed to read /proc/net/route: %s", error->message);
+               g_error_free (error);
+               return -1;
+       }
+
+       lines = g_strsplit (content, "\n", 0);
+       g_free (content);
+       entry = lines + 1;
+
+       while (*entry && strlen (*entry) > 0) {
+               char dest[9];
+               char gateway[9];
+               if (sscanf (*entry,
+                               "%*s %8[0-9A-Fa-f] %8[0-9A-Fa-f] %*s",
+                               dest, gateway) != 2) {
+                       g_warning ("Failed to parse /proc/net/route entry '%s'", *entry);
+               } else if (strcmp (dest, "00000000") == 0) {
+                       route_gateway = g_strdup (gateway);
+                       break;
+               }
+               entry++;
+       }
+       g_strfreev (lines);
+
+       if (!route_gateway) {
+               g_warning ("Failed to find default route in /proc/net/route");
+               return -1;
+       }
+
+       if (!g_file_get_contents ("/proc/net/arp", &content, NULL, &error)) {
+               g_warning ("Failed to read /proc/net/arp: %s", error->message);
+               g_error_free (error);
+               return -1;
+       }
+
+       lines = g_strsplit (content, "\n", 0);
+       g_free (content);
+       entry = lines+1;
+       while (*entry && strlen (*entry) > 0) {
+               char hwa[100];
+               char *arp_gateway;
+               int ip[4];
+
+               if (sscanf(*entry,
+                          "%d.%d.%d.%d 0x%*x 0x%*x %100s %*s %*s\n",
+                          &ip[0], &ip[1], &ip[2], &ip[3], hwa) != 5) {
+                       g_warning ("Failed to parse /proc/net/arp entry '%s'", *entry);
+               } else {
+                       arp_gateway = g_strdup_printf ("%02X%02X%02X%02X", ip[3], ip[2], ip[1], ip[0]);
+                       if (strcmp (arp_gateway, route_gateway) == 0) {
+                               g_free (arp_gateway);
+                               *mac = g_strdup (hwa);
+                               break;
+                       }
+                       g_free (arp_gateway);
+
+               }
+               entry++;
+       }
+       g_free (route_gateway);
+       g_strfreev (lines);
+
+       return *mac ? 1 : 0;
+}
+
+
+/* Position interface implementation */
+
+static gboolean
+geoclue_plazes_get_position (GcIfacePosition        *iface,
+                             GeocluePositionFields  *fields,
+                             int                    *timestamp,
+                             double                 *latitude,
+                             double                 *longitude,
+                             double                 *altitude,
+                             GeoclueAccuracy       **accuracy,
+                             GError                **error)
+{
+       GeocluePlazes *plazes;
+       int i, ret_val;
+       char *mac = NULL;
+
+       plazes = (GEOCLUE_PLAZES (iface));
+
+       *fields = GEOCLUE_POSITION_FIELDS_NONE;
+       if (timestamp) {
+               *timestamp = time (NULL);
+       }
+
+       /* we may be trying to read /proc/net/arp right after network connection.
+        * It's sometimes not up yet, try a couple of times */
+       for (i = 0; i < 5; i++) {
+               ret_val = get_mac_address (&mac);
+               if (ret_val < 0)
+                       return FALSE;
+               else if (ret_val == 1)
+                       break;
+               usleep (200);
+       }
+
+       if (mac == NULL) {
+               g_set_error (error, GEOCLUE_ERROR,
+                            GEOCLUE_ERROR_NOT_AVAILABLE,
+                            "Router mac address query failed");
+               geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ERROR);
+               return FALSE;
+       }
+
+    geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ACQUIRING);
+
+       if (!gc_web_service_query (plazes->web_service, error,
+                                  PLAZES_KEY_MAC, mac,
+                                  (char *)0)) {
+               g_free (mac);
+        // did not get a reply; we can try again later
+               geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_AVAILABLE);
+               g_set_error (error, GEOCLUE_ERROR,
+                            GEOCLUE_ERROR_NOT_AVAILABLE,
+                            "Did not get reply from server");
+               return FALSE;
+       }
+
+       if (latitude && gc_web_service_get_double (plazes->web_service,
+                                                  latitude, PLAZES_LAT_XPATH)) {
+               *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE;
+       }
+       if (longitude && gc_web_service_get_double (plazes->web_service,
+                                                   longitude, PLAZES_LON_XPATH)) {
+               *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE;
+       }
+
+       if (accuracy) {
+        /* Educated guess. Plazes are typically hand pointed on
+         * a map, or geocoded from address, so should be fairly
+         * accurate */
+        *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_STREET, 0, 0);
+       }
+
+    if (!(*fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
+         *fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)) {
+
+        // we got a reply, but could not exploit it. It would probably be the
+        // same next time.
+               geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ERROR);
+               g_set_error (error, GEOCLUE_ERROR,
+                            GEOCLUE_ERROR_NOT_AVAILABLE,
+                            "Could not understand reply from server");
+               return FALSE;
+    }
+
+       geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_AVAILABLE);
+
+       return TRUE;
+}
+
+/* Address interface implementation */
+
+static gboolean
+geoclue_plazes_get_address (GcIfaceAddress   *iface,
+                            int              *timestamp,
+                            GHashTable      **address,
+                            GeoclueAccuracy **accuracy,
+                            GError          **error)
+{
+
+       GeocluePlazes *plazes = GEOCLUE_PLAZES (iface);
+       int i, ret_val;
+       char *mac = NULL;
+
+       GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE;
+
+       if (timestamp) {
+               *timestamp = time (NULL);
+       }
+
+       /* we may be trying to read /proc/net/arp right after network connection.
+        * It's sometimes not up yet, try a couple of times */
+       for (i = 0; i < 5; i++) {
+               ret_val = get_mac_address (&mac);
+               if (ret_val < 0)
+                       return FALSE;
+               else if (ret_val == 1)
+                       break;
+               usleep (200);
+       }
+
+       if (mac == NULL) {
+               g_set_error (error, GEOCLUE_ERROR,
+                            GEOCLUE_ERROR_NOT_AVAILABLE,
+                            "Router mac address query failed");
+               geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ERROR);
+               return FALSE;
+       }
+
+    geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ACQUIRING);
+
+       if (!gc_web_service_query (plazes->web_service, error,
+                                  PLAZES_KEY_MAC, mac,
+                                  (char *)0)) {
+               g_free (mac);
+               geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_AVAILABLE);
+               g_set_error (error, GEOCLUE_ERROR,
+                            GEOCLUE_ERROR_NOT_AVAILABLE,
+                            "Did not get reply from server");
+               return FALSE;
+       }
+
+       if (address) {
+               char *str;
+
+               *address = geoclue_address_details_new ();
+
+               if (gc_web_service_get_string (plazes->web_service,
+                                              &str, "//plaze/country")) {
+                       geoclue_address_details_insert (*address,
+                                                       GEOCLUE_ADDRESS_KEY_COUNTRY,
+                                                       str);
+                       g_free (str);
+                       level = GEOCLUE_ACCURACY_LEVEL_COUNTRY;
+               }
+               if (gc_web_service_get_string (plazes->web_service,
+                                              &str, "//plaze/country_code")) {
+                       geoclue_address_details_insert (*address,
+                                                       GEOCLUE_ADDRESS_KEY_COUNTRYCODE,
+                                                       str);
+                       g_free (str);
+                       level = GEOCLUE_ACCURACY_LEVEL_COUNTRY;
+               }
+               if (gc_web_service_get_string (plazes->web_service,
+                                              &str, "//plaze/city")) {
+                       geoclue_address_details_insert (*address,
+                                                       GEOCLUE_ADDRESS_KEY_LOCALITY,
+                                                       str);
+                       g_free (str);
+                       level = GEOCLUE_ACCURACY_LEVEL_LOCALITY;
+               }
+               if (gc_web_service_get_string (plazes->web_service,
+                                              &str, "//plaze/zip_code")) {
+                       geoclue_address_details_insert (*address,
+                                                       GEOCLUE_ADDRESS_KEY_POSTALCODE,
+                                                       str);
+                       g_free (str);
+                       level = GEOCLUE_ACCURACY_LEVEL_POSTALCODE;
+               }
+               if (gc_web_service_get_string (plazes->web_service,
+                                              &str, "//plaze/address")) {
+                       geoclue_address_details_insert (*address,
+                                                       GEOCLUE_ADDRESS_KEY_STREET,
+                                                       str);
+                       g_free (str);
+                       level = GEOCLUE_ACCURACY_LEVEL_STREET;
+               }
+       }
+
+    if (level == GEOCLUE_ACCURACY_LEVEL_NONE) {
+        // we got a reply, but could not exploit it. It would probably be the
+        // same next time.
+               geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ERROR);
+               g_set_error (error, GEOCLUE_ERROR,
+                            GEOCLUE_ERROR_NOT_AVAILABLE,
+                            "Could not understand reply from server");
+               return FALSE;
+    }
+
+       if (accuracy) {
+               *accuracy = geoclue_accuracy_new (level, 0, 0);
+       }
+
+       return TRUE;
+}
+
+static void
+geoclue_plazes_finalize (GObject *obj)
+{
+       GeocluePlazes *plazes = GEOCLUE_PLAZES (obj);
+
+       g_object_unref (plazes->web_service);
+
+       ((GObjectClass *) geoclue_plazes_parent_class)->finalize (obj);
+}
+
+
+/* Initialization */
+
+static void
+geoclue_plazes_class_init (GeocluePlazesClass *klass)
+{
+       GcProviderClass *p_class = (GcProviderClass *)klass;
+       GObjectClass *o_class = (GObjectClass *)klass;
+
+       p_class->shutdown = shutdown;
+       p_class->get_status = geoclue_plazes_get_status;
+
+       o_class->finalize = geoclue_plazes_finalize;
+}
+
+static void
+geoclue_plazes_init (GeocluePlazes *plazes)
+{
+       gc_provider_set_details (GC_PROVIDER (plazes),
+                                GEOCLUE_DBUS_SERVICE_PLAZES,
+                                GEOCLUE_DBUS_PATH_PLAZES,
+                                "Plazes", "Plazes.com based provider, uses gateway mac address to locate");
+
+       plazes->web_service = g_object_new (GC_TYPE_WEB_SERVICE, NULL);
+       gc_web_service_set_base_url (plazes->web_service, PLAZES_URL);
+    geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_AVAILABLE);
+}
+
+static void
+geoclue_plazes_position_init (GcIfacePositionClass  *iface)
+{
+       iface->get_position = geoclue_plazes_get_position;
+}
+
+static void
+geoclue_plazes_address_init (GcIfaceAddressClass  *iface)
+{
+       iface->get_address = geoclue_plazes_get_address;
+}
+
+int
+main()
+{
+       g_type_init();
+
+       GeocluePlazes *o = g_object_new (GEOCLUE_TYPE_PLAZES, NULL);
+       o->loop = g_main_loop_new (NULL, TRUE);
+
+       g_main_loop_run (o->loop);
+
+       g_main_loop_unref (o->loop);
+       g_object_unref (o);
+
+       return 0;
+}
diff --git a/providers/plazes/geoclue-plazes.provider b/providers/plazes/geoclue-plazes.provider
new file mode 100755 (executable)
index 0000000..6790ea9
--- /dev/null
@@ -0,0 +1,8 @@
+[Geoclue Provider]
+Name=Plazes
+Service=org.freedesktop.Geoclue.Providers.Plazes
+Path=/org/freedesktop/Geoclue/Providers/Plazes
+Accuracy=Street
+Requires=RequiresNetwork
+Provides=ProvidesCacheableOnConnection
+Interfaces=org.freedesktop.Geoclue.Position;org.freedesktop.Geoclue.Address
diff --git a/providers/plazes/org.freedesktop.Geoclue.Providers.Plazes.service.in b/providers/plazes/org.freedesktop.Geoclue.Providers.Plazes.service.in
new file mode 100755 (executable)
index 0000000..e65e672
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Providers.Plazes
+Exec=@libexecdir@/geoclue-plazes
diff --git a/providers/skyhook/Makefile.am b/providers/skyhook/Makefile.am
new file mode 100644 (file)
index 0000000..a7d3f1c
--- /dev/null
@@ -0,0 +1,33 @@
+libexec_PROGRAMS =     \
+       geoclue-skyhook
+
+geoclue_skyhook_SOURCES = \
+       geoclue-skyhook.c
+
+geoclue_skyhook_CFLAGS = \
+       -I$(top_srcdir) \
+       -I$(top_builddir) \
+       $(GEOCLUE_CFLAGS) \
+       $(SKYHOOK_CFLAGS)
+
+geoclue_skyhook_LDADD = \
+       $(GEOCLUE_LIBS) \
+       $(SKYHOOK_LIBS) \
+       $(top_builddir)/geoclue/libgeoclue.la
+
+providersdir = $(datadir)/geoclue-providers
+providers_DATA = geoclue-skyhook.provider
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Providers.Skyhook.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+EXTRA_DIST =                   \
+       $(service_in_files)     \
+       $(providers_DATA)
+
+DISTCLEANFILES = \
+       $(service_DATA)
diff --git a/providers/skyhook/geoclue-skyhook.c b/providers/skyhook/geoclue-skyhook.c
new file mode 100644 (file)
index 0000000..3a37a82
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * Geoclue
+ * geoclue-skyhook.c - A skyhook.com-based Address/Position provider
+ *
+ * Author: Bastien Nocera <hadess@hadess.net>
+ * Copyright 2009 Bastien Nocera
+ */
+
+#include <config.h>
+
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib-object.h>
+#include <dbus/dbus-glib-bindings.h>
+#include <libsoup/soup.h>
+#include <libxml/xpathInternals.h>
+
+#include <geoclue/gc-web-service.h>
+#include <geoclue/gc-provider.h>
+#include <geoclue/geoclue-error.h>
+#include <geoclue/gc-iface-position.h>
+
+#define GEOCLUE_DBUS_SERVICE_SKYHOOK "org.freedesktop.Geoclue.Providers.Skyhook"
+#define GEOCLUE_DBUS_PATH_SKYHOOK "/org/freedesktop/Geoclue/Providers/Skyhook"
+#define SKYHOOK_URL "https://api.skyhookwireless.com/wps2/location"
+#define SKYHOOK_LAT_XPATH "//prefix:latitude"
+#define SKYHOOK_LON_XPATH "//prefix:longitude"
+#define USER_AGENT "Geoclue "VERSION
+
+#define GEOCLUE_TYPE_SKYHOOK (geoclue_skyhook_get_type ())
+#define GEOCLUE_SKYHOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_SKYHOOK, GeoclueSkyhook))
+
+#define QUERY "<?xml version=\'1.0\'?><LocationRQ xmlns=\'http://skyhookwireless.com/wps/2005\' version=\'2.6\' street-address-lookup=\'full\'><authentication version=\'2.0\'><simple><username>beta</username><realm>js.loki.com</realm></simple></authentication><access-point><mac>%s</mac><signal-strength>-50</signal-strength></access-point></LocationRQ>"
+
+typedef struct _GeoclueSkyhook {
+       GcProvider parent;
+       GMainLoop *loop;
+       SoupSession *session;
+} GeoclueSkyhook;
+
+typedef struct _GeoclueSkyhookClass {
+       GcProviderClass parent_class;
+} GeoclueSkyhookClass;
+
+
+static void geoclue_skyhook_init (GeoclueSkyhook *skyhook);
+static void geoclue_skyhook_position_init (GcIfacePositionClass  *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueSkyhook, geoclue_skyhook, GC_TYPE_PROVIDER,
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION,
+                                                geoclue_skyhook_position_init))
+
+
+/* Geoclue interface implementation */
+static gboolean
+geoclue_skyhook_get_status (GcIfaceGeoclue *iface,
+                          GeoclueStatus  *status,
+                          GError        **error)
+{
+       /* Assume available so long as all the requirements are satisfied
+          ie: Network is available */
+       *status = GEOCLUE_STATUS_AVAILABLE;
+       return TRUE;
+}
+
+static void
+_shutdown (GcProvider *provider)
+{
+       GeoclueSkyhook *skyhook = GEOCLUE_SKYHOOK (provider);
+       g_main_loop_quit (skyhook->loop);
+}
+
+#define MAC_LEN 18
+
+static char *
+get_mac_address (void)
+       {
+       /* this is an ugly hack, but it seems there is no easy
+        * ioctl-based way to get the mac address of the router. This
+        * implementation expects the system to have netstat, grep and awk
+        * */
+
+       FILE *in;
+       char mac[MAC_LEN];
+       int i;
+
+       /*for some reason netstat or /proc/net/arp isn't always ready
+        * when a connection is already up... Try a couple of times */
+       for (i=0; i<10; i++) {
+               if (!(in = popen ("ROUTER_IP=`netstat -rn | grep '^0.0.0.0 ' | awk '{ print $2 }'` && grep \"^$ROUTER_IP \" /proc/net/arp | awk '{print $4}'", "r"))) {
+                       g_warning ("popen failed");
+                       return NULL;
+               }
+
+               if (!(fgets (mac, MAC_LEN, in))) {
+                       if (errno != ENOENT && errno != EAGAIN) {
+                               g_debug ("error %d", errno);
+                               return NULL;
+                       }
+                       /* try again */
+                       pclose (in);
+                       g_debug ("trying again...");
+                       g_usleep (200);
+                       continue;
+               }
+               pclose (in);
+               return g_strdup (mac);
+       }
+       return NULL;
+}
+
+static char *
+create_post_query (void)
+{
+       char *mac, *query;
+       char **split;
+
+       mac = get_mac_address ();
+       if (mac == NULL)
+               return NULL;
+       /* Remove the ":" */
+       split = g_strsplit (mac, ":", -1);
+       g_free (mac);
+       if (split == NULL)
+               return NULL;
+       mac = g_strjoinv ("", split);
+       g_strfreev (split);
+
+       query = g_strdup_printf (QUERY, mac);
+       g_free (mac);
+
+       return query;
+}
+
+static gboolean
+get_double (xmlXPathContext *xpath_ctx, char *xpath, gdouble *value)
+{
+       xmlXPathObject *obj = NULL;
+
+       obj = xmlXPathEvalExpression (BAD_CAST (xpath), xpath_ctx);
+       if (obj &&
+           (!obj->nodesetval || xmlXPathNodeSetIsEmpty (obj->nodesetval))) {
+               xmlXPathFreeObject (obj);
+               return FALSE;
+       }
+       *value = xmlXPathCastNodeSetToNumber (obj->nodesetval);
+       xmlXPathFreeObject (obj);
+       return TRUE;
+}
+
+static gboolean
+parse_response (const char *body, gdouble *latitude, gdouble *longitude)
+{
+       xmlDocPtr doc;
+       xmlXPathContext *xpath_ctx;
+       gboolean ret = TRUE;
+
+       doc = xmlParseDoc (BAD_CAST (body));
+       if (!doc)
+               return FALSE;
+
+       xpath_ctx = xmlXPathNewContext(doc);
+       if (!xpath_ctx) {
+               xmlFreeDoc (doc);
+               return FALSE;
+       }
+       xmlXPathRegisterNs (xpath_ctx, BAD_CAST ("prefix"), BAD_CAST("http://skyhookwireless.com/wps/2005"));
+       if (get_double (xpath_ctx, SKYHOOK_LAT_XPATH, latitude) == FALSE) {
+               ret = FALSE;
+       } else if (get_double (xpath_ctx, SKYHOOK_LON_XPATH, longitude) == FALSE) {
+               ret = FALSE;
+       }
+       xmlXPathFreeContext (xpath_ctx);
+       xmlFreeDoc (doc);
+
+       return ret;
+}
+
+/* Position interface implementation */
+
+static gboolean
+geoclue_skyhook_get_position (GcIfacePosition        *iface,
+                             GeocluePositionFields  *fields,
+                             int                    *timestamp,
+                             double                 *latitude,
+                             double                 *longitude,
+                             double                 *altitude,
+                             GeoclueAccuracy       **accuracy,
+                             GError                **error)
+{
+       GeoclueSkyhook *skyhook;
+       char *query;
+       SoupMessage *msg;
+
+       skyhook = (GEOCLUE_SKYHOOK (iface));
+
+       *fields = GEOCLUE_POSITION_FIELDS_NONE;
+       if (timestamp)
+               *timestamp = time (NULL);
+
+       query = create_post_query ();
+       if (query == NULL) {
+               g_set_error (error, GEOCLUE_ERROR,
+                            GEOCLUE_ERROR_NOT_AVAILABLE,
+                            "Router mac address query failed");
+               /* TODO: set status == error ? */
+               return FALSE;
+       }
+
+       msg = soup_message_new ("POST", SKYHOOK_URL);
+       soup_message_headers_append (msg->request_headers, "User-Agent", USER_AGENT);
+       soup_message_set_request (msg,
+                                 "text/xml",
+                                 SOUP_MEMORY_TAKE,
+                                 query,
+                                 strlen (query));
+       soup_session_send_message (skyhook->session, msg);
+       if (msg->response_body == NULL || msg->response_body->data == NULL) {
+               g_object_unref (msg);
+               g_set_error (error, GEOCLUE_ERROR,
+                            GEOCLUE_ERROR_NOT_AVAILABLE,
+                            "Failed to query web service");
+               return FALSE;
+       }
+
+       if (strstr (msg->response_body->data, "<error>") != NULL) {
+               g_object_unref (msg);
+               g_set_error (error, GEOCLUE_ERROR,
+                            GEOCLUE_ERROR_NOT_AVAILABLE,
+                            "Web service returned an error");
+               return FALSE;
+       }
+
+       if (parse_response (msg->response_body->data, latitude, longitude) == FALSE) {
+               g_object_unref (msg);
+               g_set_error (error, GEOCLUE_ERROR,
+                            GEOCLUE_ERROR_NOT_AVAILABLE,
+                            "Couldn't parse response from web service");
+               return FALSE;
+       }
+
+       if (latitude)
+               *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE;
+       if (longitude)
+               *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE;
+
+       if (accuracy) {
+               if (*fields == GEOCLUE_POSITION_FIELDS_NONE) {
+                       *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE,
+                                                         0, 0);
+               } else {
+                       /* Educated guess. Skyhook are typically hand pointed on
+                        * a map, or geocoded from address, so should be fairly
+                        * accurate */
+                       *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_STREET,
+                                                         0, 0);
+               }
+       }
+
+       return TRUE;
+}
+
+static void
+geoclue_skyhook_finalize (GObject *obj)
+{
+       GeoclueSkyhook *skyhook = GEOCLUE_SKYHOOK (obj);
+
+       g_object_unref (skyhook->session);
+
+       ((GObjectClass *) geoclue_skyhook_parent_class)->finalize (obj);
+}
+
+
+/* Initialization */
+
+static void
+geoclue_skyhook_class_init (GeoclueSkyhookClass *klass)
+{
+       GcProviderClass *p_class = (GcProviderClass *)klass;
+       GObjectClass *o_class = (GObjectClass *)klass;
+
+       p_class->shutdown = _shutdown;
+       p_class->get_status = geoclue_skyhook_get_status;
+
+       o_class->finalize = geoclue_skyhook_finalize;
+}
+
+static void
+geoclue_skyhook_init (GeoclueSkyhook *skyhook)
+{
+       gc_provider_set_details (GC_PROVIDER (skyhook),
+                                GEOCLUE_DBUS_SERVICE_SKYHOOK,
+                                GEOCLUE_DBUS_PATH_SKYHOOK,
+                                "Skyhook", "Skyhook.com based provider, uses gateway mac address to locate");
+       skyhook->session = soup_session_sync_new ();
+}
+
+static void
+geoclue_skyhook_position_init (GcIfacePositionClass  *iface)
+{
+       iface->get_position = geoclue_skyhook_get_position;
+}
+
+int
+main()
+{
+       g_type_init();
+       g_thread_init (NULL);
+
+       GeoclueSkyhook *o = g_object_new (GEOCLUE_TYPE_SKYHOOK, NULL);
+       o->loop = g_main_loop_new (NULL, TRUE);
+
+       g_main_loop_run (o->loop);
+
+       g_main_loop_unref (o->loop);
+       g_object_unref (o);
+
+       return 0;
+}
diff --git a/providers/skyhook/geoclue-skyhook.provider b/providers/skyhook/geoclue-skyhook.provider
new file mode 100644 (file)
index 0000000..dbbe2b2
--- /dev/null
@@ -0,0 +1,8 @@
+[Geoclue Provider]
+Name=Plazes
+Service=org.freedesktop.Geoclue.Providers.Skyhook
+Path=/org/freedesktop/Geoclue/Providers/Skyhook
+Accuracy=Street
+Requires=RequiresNetwork
+Provides=ProvidesCacheableOnConnection
+Interfaces=org.freedesktop.Geoclue.Position
diff --git a/providers/skyhook/org.freedesktop.Geoclue.Providers.Skyhook.service.in b/providers/skyhook/org.freedesktop.Geoclue.Providers.Skyhook.service.in
new file mode 100755 (executable)
index 0000000..ff4ff74
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Providers.Skyhook
+Exec=@libexecdir@/geoclue-skyhook
diff --git a/providers/yahoo/Makefile.am b/providers/yahoo/Makefile.am
new file mode 100644 (file)
index 0000000..720d1cf
--- /dev/null
@@ -0,0 +1,31 @@
+libexec_PROGRAMS = \
+       geoclue-yahoo
+
+geoclue_yahoo_SOURCES = \
+       geoclue-yahoo.c
+
+geoclue_yahoo_CFLAGS = \
+       -I$(top_srcdir) \
+       -I$(top_builddir) \
+       $(GEOCLUE_CFLAGS)
+
+geoclue_yahoo_LDADD = \
+       $(GEOCLUE_LIBS) \
+       $(top_builddir)/geoclue/libgeoclue.la
+
+providersdir = $(datadir)/geoclue-providers
+providers_DATA = geoclue-yahoo.provider
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Providers.Yahoo.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+EXTRA_DIST =                   \
+       $(service_in_files)     \
+       $(providers_DATA)
+
+DISTCLEANFILES = \
+       $(service_DATA)
diff --git a/providers/yahoo/geoclue-yahoo.c b/providers/yahoo/geoclue-yahoo.c
new file mode 100755 (executable)
index 0000000..92211e5
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Geoclue
+ * geoclue-yahoo.c - A "local.yahooapis.com"-based Geocode-provider which
+ * converts from street address to position.
+ *
+ * Copyright 2008 by Garmin Ltd. or its subsidiaries
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <geoclue/gc-provider.h>
+#include <geoclue/gc-web-service.h>
+#include <geoclue/geoclue-error.h>
+#include <geoclue/gc-iface-geocode.h>
+
+#define YAHOO_GEOCLUE_APP_ID "zznSbDjV34HRU5CXQc4D3qE1DzCsJTaKvWTLhNJxbvI_JTp1hIncJ4xTSJFRgjE-"
+#define YAHOO_BASE_URL "http://api.local.yahoo.com/MapsService/V1/geocode"
+#define GEOCLUE_TYPE_YAHOO (geoclue_yahoo_get_type ())
+#define GEOCLUE_YAHOO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_YAHOO, GeoclueYahoo))
+
+typedef struct _GeoclueYahoo {
+       GcProvider parent;
+       GMainLoop *loop;
+
+       GcWebService *web_service;
+} GeoclueYahoo;
+
+typedef struct _GeoclueYahooClass {
+       GcProviderClass parent_class;
+} GeoclueYahooClass;
+
+
+static void geoclue_yahoo_init (GeoclueYahoo *obj);
+static void geoclue_yahoo_geocode_init (GcIfaceGeocodeClass *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueYahoo, geoclue_yahoo, GC_TYPE_PROVIDER,
+                         G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_GEOCODE,
+                                                geoclue_yahoo_geocode_init))
+
+
+/* Geoclue interface implementation */
+
+static gboolean
+geoclue_yahoo_get_status (GcIfaceGeoclue *iface,
+                          GeoclueStatus  *status,
+                          GError        **error)
+{
+       /* Assumption that we are available so long as the
+          providers requirements are met: ie network is up */
+       *status = GEOCLUE_STATUS_AVAILABLE;
+
+       return TRUE;
+}
+
+static void
+shutdown (GcProvider *provider)
+{
+       GeoclueYahoo *yahoo = GEOCLUE_YAHOO (provider);
+
+       g_main_loop_quit (yahoo->loop);
+}
+
+
+static char *
+get_address_value (GHashTable *address, char *key)
+{
+       char *value;
+
+       value = g_strdup (g_hash_table_lookup (address, key));
+       if (!value) {
+               value = g_strdup ("");
+       }
+       return value;
+}
+
+static GeoclueAccuracyLevel
+get_query_accuracy_level (GeoclueYahoo *yahoo)
+{
+       char *precision = NULL;
+       GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE;
+
+       gc_web_service_get_string (yahoo->web_service,
+                                                          &precision, "//yahoo:Result/attribute::precision");
+       if (precision) {
+               if ((strcmp (precision, "street") == 0) ||
+                       (strcmp (precision, "address") == 0)) {
+                       level = GEOCLUE_ACCURACY_LEVEL_STREET;
+               } else if ((strcmp (precision, "zip") == 0) ||
+                                  (strcmp (precision, "city") == 0)) {
+                       level = GEOCLUE_ACCURACY_LEVEL_LOCALITY;
+               } else if ((strcmp (precision, "zip+2") == 0) ||
+                                  (strcmp (precision, "zip+4") == 0)) {
+                       level = GEOCLUE_ACCURACY_LEVEL_POSTALCODE;
+               } else if (strcmp (precision, "state") == 0) {
+                       level = GEOCLUE_ACCURACY_LEVEL_REGION;
+               } else if (strcmp (precision, "country") == 0) {
+                       level = GEOCLUE_ACCURACY_LEVEL_COUNTRY;
+               }
+               g_free (precision);
+       }
+       return level;
+}
+
+/* Geocode interface implementation */
+static gboolean
+geoclue_yahoo_address_to_position (GcIfaceGeocode        *iface,
+                                   GHashTable            *address,
+                                   GeocluePositionFields *fields,
+                                   double                *latitude,
+                                   double                *longitude,
+                                   double                *altitude,
+                                   GeoclueAccuracy      **accuracy,
+                                   GError               **error)
+{
+       GeoclueYahoo *yahoo;
+       char *street, *postalcode, *locality, *region;
+
+       yahoo = GEOCLUE_YAHOO (iface);
+
+       *fields = GEOCLUE_POSITION_FIELDS_NONE;
+
+       /* weird: the results are all over the globe, but country is not an input parameter... */
+       street = get_address_value (address, GEOCLUE_ADDRESS_KEY_STREET);
+       postalcode = get_address_value (address, GEOCLUE_ADDRESS_KEY_POSTALCODE);
+       locality = get_address_value (address, GEOCLUE_ADDRESS_KEY_LOCALITY);
+       region = get_address_value (address, GEOCLUE_ADDRESS_KEY_REGION);
+
+       if (!gc_web_service_query (yahoo->web_service, error,
+                                  "appid", YAHOO_GEOCLUE_APP_ID,
+                                  "street", street,
+                                  "zip", postalcode,
+                                  "city", locality,
+                                  "state", region,
+                                  (char *)0)) {
+               return FALSE;
+       }
+
+       if (latitude) {
+               if (gc_web_service_get_double (yahoo->web_service,
+                                              latitude, "//yahoo:Latitude")) {
+                       *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE;
+               }
+       }
+       if (longitude) {
+               if (gc_web_service_get_double (yahoo->web_service,
+                                              longitude, "//yahoo:Longitude")) {
+                       *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE;
+               }
+       }
+
+       if (accuracy) {
+               *accuracy = geoclue_accuracy_new (get_query_accuracy_level (yahoo),
+                                                 0, 0);
+       }
+
+       g_free (street);
+       g_free (postalcode);
+       g_free (locality);
+       g_free (region);
+
+       return TRUE;
+}
+
+static gboolean
+geoclue_yahoo_freeform_address_to_position (GcIfaceGeocode        *iface,
+                                            const char            *address,
+                                            GeocluePositionFields *fields,
+                                            double                *latitude,
+                                            double                *longitude,
+                                            double                *altitude,
+                                            GeoclueAccuracy      **accuracy,
+                                            GError               **error)
+{
+       GeoclueYahoo *yahoo;
+
+       yahoo = GEOCLUE_YAHOO (iface);
+
+       *fields = GEOCLUE_POSITION_FIELDS_NONE;
+
+       if (!gc_web_service_query (yahoo->web_service, error,
+                                  "appid", YAHOO_GEOCLUE_APP_ID,
+                                  "location", address,
+                                  (char *)0)) {
+               return FALSE;
+       }
+
+       if (latitude) {
+               if (gc_web_service_get_double (yahoo->web_service,
+                                              latitude, "//yahoo:Latitude")) {
+                       *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE;
+               }
+       }
+       if (longitude) {
+               if (gc_web_service_get_double (yahoo->web_service,
+                                              longitude, "//yahoo:Longitude")) {
+                       *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE;
+               }
+       }
+
+       if (accuracy) {
+               *accuracy = geoclue_accuracy_new (get_query_accuracy_level (yahoo),
+                                                 0, 0);
+       }
+
+       return TRUE;
+}
+
+static void
+geoclue_yahoo_dispose (GObject *obj)
+{
+       GeoclueYahoo *yahoo = (GeoclueYahoo *) obj;
+
+       if (yahoo->web_service) {
+               g_object_unref (yahoo->web_service);
+               yahoo->web_service = NULL;
+       }
+
+       ((GObjectClass *) geoclue_yahoo_parent_class)->dispose (obj);
+}
+
+/* Initialization */
+
+static void
+geoclue_yahoo_class_init (GeoclueYahooClass *klass)
+{
+       GcProviderClass *p_class = (GcProviderClass *)klass;
+       GObjectClass *o_class = (GObjectClass *)klass;
+
+       p_class->shutdown = shutdown;
+       p_class->get_status = geoclue_yahoo_get_status;
+
+       o_class->dispose = geoclue_yahoo_dispose;
+}
+
+static void
+geoclue_yahoo_init (GeoclueYahoo *yahoo)
+{
+       gc_provider_set_details (GC_PROVIDER (yahoo),
+                                "org.freedesktop.Geoclue.Providers.Yahoo",
+                                "/org/freedesktop/Geoclue/Providers/Yahoo",
+                                "Yahoo", "Geocode provider that uses the Yahoo! Maps web services API");
+
+       yahoo->web_service = g_object_new (GC_TYPE_WEB_SERVICE, NULL);
+       gc_web_service_set_base_url (yahoo->web_service, YAHOO_BASE_URL);
+       gc_web_service_add_namespace (yahoo->web_service, "yahoo", "urn:yahoo:maps");
+}
+
+
+static void
+geoclue_yahoo_geocode_init (GcIfaceGeocodeClass *iface)
+{
+       iface->address_to_position = geoclue_yahoo_address_to_position;
+       iface->freeform_address_to_position =
+                       geoclue_yahoo_freeform_address_to_position;
+}
+
+int
+main()
+{
+       GeoclueYahoo *yahoo;
+
+       g_type_init();
+       yahoo = g_object_new (GEOCLUE_TYPE_YAHOO, NULL);
+       yahoo->loop = g_main_loop_new (NULL, TRUE);
+
+       g_main_loop_run (yahoo->loop);
+
+       g_main_loop_unref (yahoo->loop);
+       g_object_unref (yahoo);
+
+       return 0;
+}
diff --git a/providers/yahoo/geoclue-yahoo.provider b/providers/yahoo/geoclue-yahoo.provider
new file mode 100755 (executable)
index 0000000..01c92bd
--- /dev/null
@@ -0,0 +1,7 @@
+[Geoclue Provider]
+Name=Yahoo
+Service=org.freedesktop.Geoclue.Providers.Yahoo
+Path=/org/freedesktop/Geoclue/Providers/Yahoo
+Requires=RequiresNetwork
+Accuracy=Street
+Interfaces=org.freedesktop.Geoclue.Geocode
diff --git a/providers/yahoo/org.freedesktop.Geoclue.Providers.Yahoo.service.in b/providers/yahoo/org.freedesktop.Geoclue.Providers.Yahoo.service.in
new file mode 100755 (executable)
index 0000000..3f348e3
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Providers.Yahoo
+Exec=@libexecdir@/geoclue-yahoo
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..4a8b331
--- /dev/null
@@ -0,0 +1,71 @@
+libexec_PROGRAMS = geoclue-master
+
+geoclue_master_CFLAGS =                \
+       -I$(top_srcdir)         \
+       -I$(srcdir)             \
+       -I$(top_builddir)       \
+       -DGEOCLUE_PROVIDERS_DIR=\""$(datadir)/geoclue-providers"\" \
+       $(GEOCLUE_CFLAGS) \
+       $(MASTER_CFLAGS) \
+       $(CONNECTIVITY_CFLAGS)
+
+geoclue_master_LDADD =         \
+       $(top_builddir)/geoclue/libgeoclue.la   \
+       $(GEOCLUE_LIBS) \
+       $(MASTER_LIBS)  \
+       $(CONNECTIVITY_LIBS)
+
+NOINST_H_FILES =               \
+       main.h                  \
+       master.h                \
+       master-provider.h               \
+       client.h                \
+       connectivity.h          \
+       connectivity-networkmanager.h   \
+       connectivity-conic.h
+
+geoclue_master_SOURCES =       \
+       $(NOINST_H_FILES)       \
+       client.c                \
+       main.c                  \
+       master.c                \
+       master-provider.c       \
+       connectivity.c          \
+       connectivity-networkmanager.c   \
+       connectivity-conic.c
+
+BUILT_SOURCES =                        \
+       gc-iface-master-glue.h  \
+       gc-iface-master-client-glue.h
+
+%-glue.h: stamp-%-glue.h
+       @true
+stamp-gc-iface-master-glue.h: ../interfaces/gc-iface-master.xml
+       $(DBUS_BINDING_TOOL) --prefix=gc_iface_master --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F)     \
+       && echo timestamp > $(@F)
+
+stamp-gc-iface-master-client-glue.h: ../interfaces/gc-iface-master-client.xml
+       $(DBUS_BINDING_TOOL) --prefix=gc_iface_master_client --mode=glib-server $< > xgen-$(@F) \
+       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
+       && rm -f xgen-$(@F)     \
+       && echo timestamp > $(@F)
+
+servicedir = $(DBUS_SERVICES_DIR)
+service_in_files = org.freedesktop.Geoclue.Master.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+EXTRA_DIST =                   \
+       $(service_in_files)
+
+CLEANFILES =                           \
+       $(BUILT_SOURCES)                \
+       stamp-gc-iface-master-glue.h    \
+       stamp-gc-iface-master-client-glue.h
+
+DISTCLEANFILES = \
+       $(service_DATA)
diff --git a/src/client.c b/src/client.c
new file mode 100644 (file)
index 0000000..a40c983
--- /dev/null
@@ -0,0 +1,970 @@
+/*
+ * Geoclue
+ * client.c - Geoclue Master Client
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ *          Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2007-2008 by Garmin Ltd. or its subsidiaries
+ *                2008 OpenedHand Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/** TODO
+ *
+ *     might want to write a testing-provider with a gui for
+ *     choosing what to emit...
+ *
+ **/
+
+
+#include <config.h>
+
+#include <geoclue/geoclue-error.h>
+#include <geoclue/geoclue-marshal.h>
+
+#include <geoclue/gc-provider.h>
+#include <geoclue/gc-iface-position.h>
+#include <geoclue/gc-iface-address.h>
+
+#include "client.h"
+
+#define GEOCLUE_POSITION_INTERFACE_NAME "org.freedesktop.Geoclue.Position"
+#define GEOCLUE_ADDRESS_INTERFACE_NAME "org.freedesktop.Geoclue.Address"
+
+enum {
+       ADDRESS_PROVIDER_CHANGED,
+       POSITION_PROVIDER_CHANGED,
+       LAST_SIGNAL
+};
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+
+enum {
+       POSITION_CHANGED, /* signal id of current provider */
+       ADDRESS_CHANGED, /* signal id of current provider */
+       LAST_PRIVATE_SIGNAL
+};
+
+typedef struct _GcMasterClientPrivate {
+       guint32 signals[LAST_PRIVATE_SIGNAL];
+
+       GeoclueAccuracyLevel min_accuracy;
+       int min_time;
+       gboolean require_updates;
+       GeoclueResourceFlags allowed_resources;
+
+       gboolean position_started;
+       GcMasterProvider *position_provider;
+       GList *position_providers;
+       gboolean position_provider_choice_in_progress;
+
+       gboolean address_started;
+       GcMasterProvider *address_provider;
+       GList *address_providers;
+       gboolean address_provider_choice_in_progress;
+
+} GcMasterClientPrivate;
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GC_TYPE_MASTER_CLIENT, GcMasterClientPrivate))
+
+
+
+static gboolean gc_iface_master_client_set_requirements (GcMasterClient       *client,
+                                                         GeoclueAccuracyLevel  min_accuracy,
+                                                         int                   min_time,
+                                                         gboolean              require_updates,
+                                                         GeoclueResourceFlags  allowed_resources,
+                                                         GError              **error);
+static gboolean gc_iface_master_client_position_start (GcMasterClient *client, GError **error);
+static gboolean gc_iface_master_client_address_start (GcMasterClient *client, GError **error);
+static gboolean gc_iface_master_client_get_address_provider (GcMasterClient  *client,
+                                                             char           **name,
+                                                             char           **description,
+                                                             char           **service,
+                                                             char           **path,
+                                                             GError         **error);
+static gboolean gc_iface_master_client_get_position_provider (GcMasterClient  *client,
+                                                              char           **name,
+                                                              char           **description,
+                                                              char           **service,
+                                                              char           **path,
+                                                              GError         **error);
+
+static void gc_master_client_geoclue_init (GcIfaceGeoclueClass *iface);
+static void gc_master_client_position_init (GcIfacePositionClass *iface);
+static void gc_master_client_address_init (GcIfaceAddressClass *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GcMasterClient, gc_master_client, G_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE(GC_TYPE_IFACE_GEOCLUE,
+                                               gc_master_client_geoclue_init)
+                        G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION,
+                                               gc_master_client_position_init)
+                        G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS,
+                                               gc_master_client_address_init))
+
+#include "gc-iface-master-client-glue.h"
+
+
+static gboolean status_change_requires_provider_change (GList            *provider_list,
+                                                        GcMasterProvider *current_provider,
+                                                        GcMasterProvider *changed_provider,
+                                                        GeoclueStatus     status);
+static void gc_master_client_emit_position_changed (GcMasterClient *client);
+static void gc_master_client_emit_address_changed (GcMasterClient *client);
+static gboolean gc_master_client_choose_position_provider (GcMasterClient  *client,
+                                                           GList           *providers);
+static gboolean gc_master_client_choose_address_provider (GcMasterClient  *client,
+                                                          GList           *providers);
+
+
+static void
+status_changed (GcMasterProvider *provider,
+                GeoclueStatus     status,
+                GcMasterClient   *client)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+
+       g_debug ("client: provider %s status changed: %d", gc_master_provider_get_name (provider), status);
+
+       /* change providers if needed (and if we're not choosing provider already) */
+
+       if (!priv->position_provider_choice_in_progress &&
+           status_change_requires_provider_change (priv->position_providers,
+                                                   priv->position_provider,
+                                                   provider, status) &&
+           gc_master_client_choose_position_provider (client,
+                                                      priv->position_providers)) {
+
+               /* we have a new position provider, force-emit position_changed */
+               gc_master_client_emit_position_changed (client);
+       }
+
+       if (!priv->address_provider_choice_in_progress &&
+           status_change_requires_provider_change (priv->address_providers,
+                                                   priv->address_provider,
+                                                   provider, status) &&
+           gc_master_client_choose_address_provider (client,
+                                                     priv->address_providers)) {
+
+               /* we have a new address provider, force-emit address_changed */
+               gc_master_client_emit_address_changed (client);
+       }
+}
+
+static void
+accuracy_changed (GcMasterProvider     *provider,
+                  GcInterfaceFlags      interface,
+                  GeoclueAccuracyLevel  level,
+                  GcMasterClient       *client)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+       GcInterfaceAccuracy *accuracy_data;
+
+       accuracy_data = g_new0 (GcInterfaceAccuracy, 1);
+       g_debug ("client: %s accuracy changed (%d)",
+                gc_master_provider_get_name (provider), level);
+
+       accuracy_data->interface = interface;
+       accuracy_data->accuracy_level = priv->min_accuracy;
+       switch (interface) {
+               case GC_IFACE_POSITION:
+                       priv->position_providers =
+                               g_list_sort_with_data (priv->position_providers,
+                                                      (GCompareDataFunc)gc_master_provider_compare,
+                                                      accuracy_data);
+                       if (priv->position_provider_choice_in_progress) {
+                               g_debug ("        ...but provider choice in progress");
+                       } else if (gc_master_client_choose_position_provider (client,
+                                                                             priv->position_providers)) {
+                               gc_master_client_emit_position_changed (client);
+                       }
+                       break;
+
+               case GC_IFACE_ADDRESS:
+                       priv->address_providers =
+                               g_list_sort_with_data (priv->address_providers,
+                                                      (GCompareDataFunc)gc_master_provider_compare,
+                                                      accuracy_data);
+                       if (priv->address_provider_choice_in_progress) {
+                               g_debug ("        ...but provider choice in progress");
+                       } else if (gc_master_client_choose_address_provider (client,
+                                                                     priv->address_providers)) {
+                               gc_master_client_emit_address_changed (client);
+                       }
+                       break;
+
+               default:
+                       g_assert_not_reached ();
+       }
+       g_free (accuracy_data);
+}
+
+static void
+position_changed (GcMasterProvider     *provider,
+                  GeocluePositionFields fields,
+                  int                   timestamp,
+                  double                latitude,
+                  double                longitude,
+                  double                altitude,
+                  GeoclueAccuracy      *accuracy,
+                  GcMasterClient       *client)
+{
+       gc_iface_position_emit_position_changed
+               (GC_IFACE_POSITION (client),
+                fields,
+                timestamp,
+                latitude, longitude, altitude,
+                accuracy);
+}
+
+static void
+address_changed (GcMasterProvider     *provider,
+                 int                   timestamp,
+                 GHashTable           *details,
+                 GeoclueAccuracy      *accuracy,
+                 GcMasterClient       *client)
+{
+       gc_iface_address_emit_address_changed
+               (GC_IFACE_ADDRESS (client),
+                timestamp,
+                details,
+                accuracy);
+}
+
+/*if changed_provider status changes, do we need to choose a new provider? */
+static gboolean
+status_change_requires_provider_change (GList            *provider_list,
+                                        GcMasterProvider *current_provider,
+                                        GcMasterProvider *changed_provider,
+                                        GeoclueStatus     status)
+{
+       if (!provider_list) {
+               return FALSE;
+
+       } else if (current_provider == NULL) {
+               return (status == GEOCLUE_STATUS_AVAILABLE);
+
+       } else if (current_provider == changed_provider) {
+               return (status != GEOCLUE_STATUS_AVAILABLE);
+
+       }else if (status != GEOCLUE_STATUS_AVAILABLE) {
+               return FALSE;
+
+       }
+
+       while (provider_list) {
+               GcMasterProvider *p = provider_list->data;
+               if (p == current_provider) {
+                       /* not interested in worse-than-current providers */
+                       return FALSE;
+               }
+               if (p == changed_provider) {
+                       /* changed_provider is better than current */
+                       return (status == GEOCLUE_STATUS_AVAILABLE);
+               }
+               provider_list = provider_list->next;
+       }
+       return FALSE;
+}
+
+static void
+gc_master_client_connect_common_signals (GcMasterClient *client, GList *providers)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+       GList *l;
+
+       /* connect to common signals if the provider is not already connected */
+       l = providers;
+       while (l) {
+               GcMasterProvider *p = l->data;
+               if (!g_list_find (priv->address_providers, p) &&
+                   !g_list_find (priv->position_providers, p)) {
+                       g_debug ("client: connecting to '%s' accuracy-changed and status-changed", gc_master_provider_get_name (p));
+                       g_signal_connect (G_OBJECT (p),
+                                         "status-changed",
+                                         G_CALLBACK (status_changed),
+                                         client);
+                       g_signal_connect (G_OBJECT (p),
+                                         "accuracy-changed",
+                                         G_CALLBACK (accuracy_changed),
+                                         client);
+               }
+               l = l->next;
+       }
+}
+
+static void
+gc_master_client_unsubscribe_providers (GcMasterClient *client, GList *provider_list, GcInterfaceFlags iface)
+{
+       while (provider_list) {
+               GcMasterProvider *provider = provider_list->data;
+
+               gc_master_provider_unsubscribe (provider, client, iface);
+               provider_list = provider_list->next;
+       }
+
+}
+
+/* get_best_provider will return the best provider with status == GEOCLUE_STATUS_AVAILABLE.
+ * It will also "subscribe" to that provider and all better ones, and unsubscribe from worse.*/
+static GcMasterProvider *
+gc_master_client_get_best_provider (GcMasterClient    *client,
+                                    GList            **provider_list,
+                                    GcInterfaceFlags   iface)
+{
+       GList *l = *provider_list;
+       /* TODO: should maybe choose a acquiring provider if better ones are are not available */
+
+       g_debug ("client: choosing best provider");
+
+       while (l) {
+               GcMasterProvider *provider = l->data;
+
+               g_debug ("        ...trying provider %s", gc_master_provider_get_name (provider));
+               if (gc_master_provider_subscribe (provider, client, iface)) {
+                       /* provider was started, so accuracy may have changed
+                          (which re-sorts provider lists), restart provider selection */
+                       /* TODO re-think this: restarting provider selection leads to potentially
+                          never-ending looping */
+                       g_debug ("        ...started %s (status %d), re-starting provider selection",
+                                gc_master_provider_get_name (provider),
+                                gc_master_provider_get_status (provider));
+                       l = *provider_list;
+                       continue;
+               }
+               /* provider did not need to be started */
+
+               /* TODO: currently returning even providers that are worse than priv->min_accuracy,
+                * if nothing else is available */
+               if (gc_master_provider_get_status (provider) == GEOCLUE_STATUS_AVAILABLE) {
+                       /* unsubscribe from all providers worse than this */
+                       gc_master_client_unsubscribe_providers (client, l->next, iface);
+                       return provider;
+               }
+               l = l->next;
+       }
+
+       /* no provider found */
+       gc_master_client_unsubscribe_providers (client, *provider_list, iface);
+       return NULL;
+}
+
+static void
+gc_master_client_emit_position_changed (GcMasterClient *client)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+       GeocluePositionFields fields;
+       int timestamp;
+       double latitude, longitude, altitude;
+       GeoclueAccuracy *accuracy = NULL;
+       GError *error = NULL;
+
+
+       if (priv->position_provider == NULL) {
+               accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0.0, 0.0);
+               gc_iface_position_emit_position_changed
+                       (GC_IFACE_POSITION (client),
+                        GEOCLUE_POSITION_FIELDS_NONE,
+                        time (NULL),
+                        0.0, 0.0, 0.0,
+                        accuracy);
+               geoclue_accuracy_free (accuracy);
+               return;
+       }
+
+       fields = gc_master_provider_get_position
+               (priv->position_provider,
+                &timestamp,
+                &latitude, &longitude, &altitude,
+                &accuracy,
+                &error);
+       if (error) {
+               /*TODO what now?*/
+               g_warning ("client: failed to get position from %s: %s",
+                          gc_master_provider_get_name (priv->position_provider),
+                          error->message);
+               g_error_free (error);
+               return;
+       }
+       gc_iface_position_emit_position_changed
+               (GC_IFACE_POSITION (client),
+                fields,
+                timestamp,
+                latitude, longitude, altitude,
+                accuracy);
+}
+
+static void
+gc_master_client_emit_address_changed (GcMasterClient *client)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+       int timestamp;
+       GHashTable *details = NULL;
+       GeoclueAccuracy *accuracy = NULL;
+       GError *error = NULL;
+
+       if (priv->address_provider == NULL) {
+               accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0.0, 0.0);
+               details = g_hash_table_new (g_str_hash, g_str_equal);
+               gc_iface_address_emit_address_changed
+                       (GC_IFACE_ADDRESS (client),
+                        time (NULL),
+                        details,
+                        accuracy);
+               g_hash_table_destroy (details);
+               geoclue_accuracy_free (accuracy);
+               return;
+       }
+       if (!gc_master_provider_get_address
+               (priv->address_provider,
+                &timestamp,
+                &details,
+                &accuracy,
+                &error)) {
+               /*TODO what now?*/
+               g_warning ("client: failed to get address from %s: %s",
+                          gc_master_provider_get_name (priv->address_provider),
+                          error->message);
+               g_error_free (error);
+               return;
+       }
+       gc_iface_address_emit_address_changed
+               (GC_IFACE_ADDRESS (client),
+                timestamp,
+                details,
+                accuracy);
+}
+
+/* return true if a _new_ provider was chosen */
+static gboolean
+gc_master_client_choose_position_provider (GcMasterClient *client,
+                                           GList *providers)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+       GcMasterProvider *new_p;
+
+       /* choose and start provider */
+       priv->position_provider_choice_in_progress = TRUE;
+       new_p = gc_master_client_get_best_provider (client,
+                                                   &priv->position_providers,
+                                                   GC_IFACE_POSITION);
+       priv->position_provider_choice_in_progress = FALSE;
+
+       if (priv->position_provider && new_p == priv->position_provider) {
+               return FALSE;
+       }
+
+       if (priv->signals[POSITION_CHANGED] > 0) {
+               g_signal_handler_disconnect (priv->position_provider,
+                                            priv->signals[POSITION_CHANGED]);
+               priv->signals[POSITION_CHANGED] = 0;
+       }
+
+       priv->position_provider = new_p;
+
+       if (priv->position_provider == NULL) {
+               g_debug ("client: position provider changed (to NULL)");
+               g_signal_emit (client, signals[POSITION_PROVIDER_CHANGED], 0,
+                              NULL, NULL, NULL, NULL);
+               return TRUE;
+       }
+
+       g_debug ("client: position provider changed (to %s)", gc_master_provider_get_name (priv->position_provider));
+       g_signal_emit (client, signals[POSITION_PROVIDER_CHANGED], 0,
+                      gc_master_provider_get_name (priv->position_provider),
+                      gc_master_provider_get_description (priv->position_provider),
+                      gc_master_provider_get_service (priv->position_provider),
+                      gc_master_provider_get_path (priv->position_provider));
+       priv->signals[POSITION_CHANGED] =
+               g_signal_connect (G_OBJECT (priv->position_provider),
+                                 "position-changed",
+                                 G_CALLBACK (position_changed),
+                                 client);
+       return TRUE;
+}
+
+/* return true if a _new_ provider was chosen */
+static gboolean
+gc_master_client_choose_address_provider (GcMasterClient *client,
+                                          GList *providers)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+       GcMasterProvider *new_p;
+
+
+       /* choose and start provider */
+       priv->address_provider_choice_in_progress = TRUE;
+       new_p = gc_master_client_get_best_provider (client,
+                                                   &priv->address_providers,
+                                                   GC_IFACE_ADDRESS);
+       priv->address_provider_choice_in_progress = FALSE;
+
+       if (priv->address_provider != NULL && new_p == priv->address_provider) {
+               /* keep using the same provider */
+               return FALSE;
+       }
+
+       if (priv->address_provider && priv->signals[ADDRESS_CHANGED] > 0) {
+               g_signal_handler_disconnect (priv->address_provider,
+                                            priv->signals[ADDRESS_CHANGED]);
+               priv->signals[ADDRESS_CHANGED] = 0;
+       }
+
+       priv->address_provider = new_p;
+
+       if (priv->address_provider == NULL) {
+               g_debug ("client: address provider changed (to NULL)");
+               g_signal_emit (client, signals[ADDRESS_PROVIDER_CHANGED], 0,
+                              NULL, NULL, NULL, NULL);
+               return TRUE;
+       }
+
+       g_debug ("client: address provider changed (to %s)", gc_master_provider_get_name (priv->address_provider));
+       g_signal_emit (client, signals[ADDRESS_PROVIDER_CHANGED], 0,
+                      gc_master_provider_get_name (priv->address_provider),
+                      gc_master_provider_get_description (priv->address_provider),
+                      gc_master_provider_get_service (priv->address_provider),
+                      gc_master_provider_get_path (priv->address_provider));
+       priv->signals[ADDRESS_CHANGED] =
+               g_signal_connect (G_OBJECT (priv->address_provider),
+                                 "address-changed",
+                                 G_CALLBACK (address_changed),
+                                 client);
+       return TRUE;
+}
+
+static void
+gc_master_provider_set_position_providers (GcMasterClient *client,
+                                           GList *providers)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+       GcInterfaceAccuracy *accuracy_data;
+
+       accuracy_data = g_new0(GcInterfaceAccuracy, 1);
+       accuracy_data->interface = GC_IFACE_POSITION;
+       accuracy_data->accuracy_level = priv->min_accuracy;
+
+       gc_master_client_connect_common_signals (client, providers);
+       priv->position_providers =
+               g_list_sort_with_data (providers,
+                                      (GCompareDataFunc)gc_master_provider_compare,
+                                      accuracy_data);
+
+       g_free (accuracy_data);
+}
+
+static void
+gc_master_provider_set_address_providers (GcMasterClient *client,
+                                           GList *providers)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+       GcInterfaceAccuracy *accuracy_data;
+
+       accuracy_data = g_new0(GcInterfaceAccuracy, 1);
+       accuracy_data->interface = GC_IFACE_ADDRESS;
+       accuracy_data->accuracy_level = priv->min_accuracy;
+
+       gc_master_client_connect_common_signals (client, providers);
+       priv->address_providers =
+               g_list_sort_with_data (providers,
+                                      (GCompareDataFunc)gc_master_provider_compare,
+                                      accuracy_data);
+
+       g_free (accuracy_data);
+}
+
+static void
+gc_master_client_init_position_providers (GcMasterClient *client)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+       GList *providers;
+
+       if (!priv->position_started) {
+               return;
+       }
+
+       /* TODO: free priv->position_providers */
+
+       providers = gc_master_get_providers (GC_IFACE_POSITION,
+                                            priv->min_accuracy,
+                                            priv->require_updates,
+                                            priv->allowed_resources,
+                                            NULL);
+       g_debug ("client: %d position providers matching requirements found, now choosing current provider",
+                g_list_length (providers));
+
+       gc_master_provider_set_position_providers (client, providers);
+       gc_master_client_choose_position_provider (client, priv->position_providers);
+}
+static void
+gc_master_client_init_address_providers (GcMasterClient *client)
+{
+       GList *providers;
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+
+       if (!priv->address_started) {
+               return;
+       }
+
+       /* TODO: free priv->address_providers */
+
+       providers = gc_master_get_providers (GC_IFACE_ADDRESS,
+                                            priv->min_accuracy,
+                                            priv->require_updates,
+                                            priv->allowed_resources,
+                                            NULL);
+       g_debug ("client: %d address providers matching requirements found, now choosing current provider",
+                g_list_length (providers));
+
+       gc_master_provider_set_address_providers (client, providers);
+       gc_master_client_choose_address_provider (client, priv->address_providers);
+}
+
+static gboolean
+gc_iface_master_client_set_requirements (GcMasterClient        *client,
+                                        GeoclueAccuracyLevel   min_accuracy,
+                                        int                    min_time,
+                                        gboolean               require_updates,
+                                        GeoclueResourceFlags   allowed_resources,
+                                        GError               **error)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+
+       priv->min_accuracy = min_accuracy;
+       priv->min_time = min_time;
+       priv->require_updates = require_updates;
+       priv->allowed_resources = allowed_resources;
+
+       gc_master_client_init_position_providers (client);
+       gc_master_client_init_address_providers (client);
+
+       return TRUE;
+}
+
+
+static gboolean
+gc_iface_master_client_position_start (GcMasterClient *client,
+                                       GError         **error)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+
+       if (priv->position_providers) {
+               if (error) {
+                       *error = g_error_new (GEOCLUE_ERROR,
+                                             GEOCLUE_ERROR_FAILED,
+                                             "Position interface already started");
+               }
+               return FALSE;
+       }
+
+       priv->position_started = TRUE;
+
+       gc_master_client_init_position_providers (client);
+
+       return TRUE;
+}
+
+static gboolean
+gc_iface_master_client_address_start (GcMasterClient *client,
+                                      GError         **error)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+
+       if (priv->address_providers) {
+               if (error) {
+                       *error = g_error_new (GEOCLUE_ERROR,
+                                             GEOCLUE_ERROR_FAILED,
+                                             "Address interface already started");
+               }
+               return FALSE;
+       }
+
+       priv->address_started = TRUE;
+       gc_master_client_init_address_providers (client);
+       return TRUE;
+}
+
+static void
+get_master_provider_details (GcMasterProvider  *provider,
+                             char             **name,
+                             char             **description,
+                             char             **service,
+                             char             **path)
+{
+       if (name) {
+               if (!provider) {
+                       *name = NULL;
+               } else {
+                       *name = g_strdup (gc_master_provider_get_name (provider));
+               }
+       }
+       if (description) {
+               if (!provider) {
+                       *description = NULL;
+               } else {
+                       *description = g_strdup (gc_master_provider_get_description (provider));
+               }
+       }
+       if (service) {
+               if (!provider) {
+                       *service = NULL;
+               } else {
+                       *service = g_strdup (gc_master_provider_get_service (provider));
+               }
+       }
+       if (path) {
+               if (!provider) {
+                       *path = NULL;
+               } else {
+                       *path = g_strdup (gc_master_provider_get_path (provider));
+               }
+       }
+}
+
+
+static gboolean
+gc_iface_master_client_get_address_provider (GcMasterClient  *client,
+                                             char           **name,
+                                             char           **description,
+                                             char           **service,
+                                             char           **path,
+                                             GError         **error)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+
+       get_master_provider_details (priv->address_provider,
+                                    name, description, service, path);
+       return TRUE;
+}
+
+static gboolean
+gc_iface_master_client_get_position_provider (GcMasterClient  *client,
+                                              char           **name,
+                                              char           **description,
+                                              char           **service,
+                                              char           **path,
+                                              GError         **error)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+
+       get_master_provider_details (priv->position_provider,
+                                    name, description, service, path);
+       return TRUE;
+}
+
+static void
+finalize (GObject *object)
+{
+       GcMasterClient *client = GC_MASTER_CLIENT (object);
+       GcMasterClientPrivate *priv = GET_PRIVATE (object);
+
+       /* do not free contents of the lists, Master takes care of them */
+       if (priv->position_providers) {
+               gc_master_client_unsubscribe_providers (client, priv->position_providers, GC_IFACE_ALL);
+               g_list_free (priv->position_providers);
+               priv->position_providers = NULL;
+       }
+       if (priv->address_providers) {
+               gc_master_client_unsubscribe_providers (client, priv->address_providers, GC_IFACE_ALL);
+               g_list_free (priv->address_providers);
+               priv->address_providers = NULL;
+       }
+
+       ((GObjectClass *) gc_master_client_parent_class)->finalize (object);
+}
+
+static void
+gc_master_client_class_init (GcMasterClientClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+
+       g_type_class_add_private (klass, sizeof (GcMasterClientPrivate));
+
+       signals[ADDRESS_PROVIDER_CHANGED] =
+               g_signal_new ("address-provider-changed",
+                             G_OBJECT_CLASS_TYPE (klass),
+                             G_SIGNAL_RUN_LAST, 0,
+                             NULL, NULL,
+                             geoclue_marshal_VOID__STRING_STRING_STRING_STRING,
+                             G_TYPE_NONE, 4,
+                             G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+       signals[POSITION_PROVIDER_CHANGED] =
+               g_signal_new ("position-provider-changed",
+                             G_OBJECT_CLASS_TYPE (klass),
+                             G_SIGNAL_RUN_LAST, 0,
+                             NULL, NULL,
+                             geoclue_marshal_VOID__STRING_STRING_STRING_STRING,
+                             G_TYPE_NONE, 4,
+                             G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+       dbus_g_object_type_install_info (gc_master_client_get_type (),
+                                        &dbus_glib_gc_iface_master_client_object_info);
+
+
+}
+
+static void
+gc_master_client_init (GcMasterClient *client)
+{
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+
+       priv->position_provider_choice_in_progress = FALSE;
+       priv->address_provider_choice_in_progress = FALSE;
+
+       priv->position_started = FALSE;
+       priv->position_provider = NULL;
+       priv->position_providers = NULL;
+
+       priv->address_started = FALSE;
+       priv->address_provider = NULL;
+       priv->address_providers = NULL;
+}
+
+static gboolean
+get_position (GcIfacePosition       *iface,
+             GeocluePositionFields *fields,
+             int                   *timestamp,
+             double                *latitude,
+             double                *longitude,
+             double                *altitude,
+             GeoclueAccuracy      **accuracy,
+             GError               **error)
+{
+       GcMasterClient *client = GC_MASTER_CLIENT (iface);
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+
+       if (priv->position_provider == NULL) {
+               if (error) {
+                       *error = g_error_new (GEOCLUE_ERROR,
+                                             GEOCLUE_ERROR_NOT_AVAILABLE,
+                                             "Geoclue master client has no usable Position providers");
+               }
+               return FALSE;
+       }
+
+       *fields = gc_master_provider_get_position
+               (priv->position_provider,
+                timestamp,
+                latitude, longitude, altitude,
+                accuracy,
+                error);
+       return (!*error);
+}
+
+static gboolean
+get_address (GcIfaceAddress   *iface,
+             int              *timestamp,
+             GHashTable      **address,
+             GeoclueAccuracy **accuracy,
+             GError          **error)
+{
+       GcMasterClient *client = GC_MASTER_CLIENT (iface);
+       GcMasterClientPrivate *priv = GET_PRIVATE (client);
+
+       if (priv->address_provider == NULL) {
+               if (error) {
+                       *error = g_error_new (GEOCLUE_ERROR,
+                                             GEOCLUE_ERROR_NOT_AVAILABLE,
+                                             "Geoclue master client has no usable Address providers");
+               }
+               return FALSE;
+       }
+
+       return gc_master_provider_get_address
+               (priv->address_provider,
+                timestamp,
+                address,
+                accuracy,
+                error);
+}
+
+static gboolean
+get_status (GcIfaceGeoclue *geoclue,
+            GeoclueStatus  *status,
+            GError        **error)
+{
+       /* not really meaningful */
+       *status = GEOCLUE_STATUS_AVAILABLE;
+       return TRUE;
+}
+
+static gboolean
+set_options (GcIfaceGeoclue *geoclue,
+             GHashTable     *options,
+             GError        **error)
+{
+       /* not meaningful, options come from master */
+
+       /* It is not an error to not have a SetOptions implementation */
+       return TRUE;
+}
+
+static gboolean
+get_provider_info (GcIfaceGeoclue  *geoclue,
+                  gchar          **name,
+                  gchar          **description,
+                  GError         **error)
+{
+       if (name) {
+               *name = g_strdup ("Geoclue Master");
+       }
+       if (description) {
+               *description = g_strdup ("Meta-provider that internally uses what ever provider is the best ");
+       }
+       return TRUE;
+}
+
+static void
+add_reference (GcIfaceGeoclue *geoclue,
+               DBusGMethodInvocation *context)
+{
+       /* TODO implement if needed */
+       dbus_g_method_return (context);
+}
+
+static void
+remove_reference (GcIfaceGeoclue *geoclue,
+                  DBusGMethodInvocation *context)
+{
+       /* TODO implement if needed */
+       dbus_g_method_return (context);
+}
+
+static void
+gc_master_client_geoclue_init (GcIfaceGeoclueClass *iface)
+{
+       iface->get_provider_info = get_provider_info;
+       iface->get_status = get_status;
+       iface->set_options = set_options;
+       iface->add_reference = add_reference;
+       iface->remove_reference = remove_reference;
+}
+
+static void
+gc_master_client_position_init (GcIfacePositionClass *iface)
+{
+       iface->get_position = get_position;
+}
+
+static void
+gc_master_client_address_init (GcIfaceAddressClass *iface)
+{
+       iface->get_address = get_address;
+}
diff --git a/src/client.h b/src/client.h
new file mode 100755 (executable)
index 0000000..712ece6
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Geoclue
+ * client.h - Master process client
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007-2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _CLIENT_H_
+#define _CLIENT_H_
+
+#include <glib-object.h>
+#include <geoclue/geoclue-accuracy.h>
+
+#include "master.h"
+#include "master-provider.h"
+
+#define GC_TYPE_MASTER_CLIENT (gc_master_client_get_type ())
+#define GC_MASTER_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_MASTER_CLIENT, GcMasterClient))
+
+typedef struct {
+       GObject parent;
+} GcMasterClient;
+
+typedef struct {
+       GObjectClass parent_class;
+} GcMasterClientClass;
+
+GType gc_master_client_get_type (void);
+
+#endif
diff --git a/src/connectivity-conic.c b/src/connectivity-conic.c
new file mode 100755 (executable)
index 0000000..14bc152
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Geoclue
+ * geoclue-conic.c
+ *
+ * Authors: Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+#include <config.h>
+
+#ifdef HAVE_CONIC
+
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <conicconnectionevent.h>
+#include "connectivity-conic.h"
+
+static void geoclue_conic_connectivity_init (GeoclueConnectivityInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueConic, geoclue_conic, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GEOCLUE_TYPE_CONNECTIVITY,
+                                                geoclue_conic_connectivity_init))
+
+
+/* GeoclueConnectivity iface method */
+static int
+get_status (GeoclueConnectivity *iface)
+{
+       GeoclueConic *conic = GEOCLUE_CONIC (iface);
+
+       return conic->status;
+}
+
+
+static void
+finalize (GObject *object)
+{
+       /* free everything */
+
+       ((GObjectClass *) geoclue_conic_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       GeoclueConic *self = GEOCLUE_CONIC (object);
+
+       g_object_unref (self->conic);
+       ((GObjectClass *) geoclue_conic_parent_class)->dispose (object);
+}
+
+static void
+geoclue_conic_class_init (GeoclueConicClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+}
+
+
+static GeoclueNetworkStatus
+conicstatus_to_geocluenetworkstatus (ConIcConnectionStatus status)
+{
+       switch (status) {
+               case CON_IC_STATUS_CONNECTED:
+                       return GEOCLUE_CONNECTIVITY_ONLINE;
+               case CON_IC_STATUS_DISCONNECTED:
+               case CON_IC_STATUS_DISCONNECTING:
+                       return GEOCLUE_CONNECTIVITY_OFFLINE;
+               default:
+                       g_warning ("Uknown ConIcConnectionStatus: %d", status);
+                       return GEOCLUE_CONNECTIVITY_UNKNOWN;
+               break;
+       }
+}
+
+static void
+geoclue_conic_state_changed (ConIcConnection *connection,
+                             ConIcConnectionEvent *event,
+                             gpointer userdata)
+{
+       GeoclueConic *self = GEOCLUE_CONIC (userdata);
+       ConIcConnectionStatus status = con_ic_connection_event_get_status (event);
+       GeoclueNetworkStatus gc_status;
+
+       g_debug ("conic change");
+       gc_status = conicstatus_to_geocluenetworkstatus (status);
+       if (gc_status != self->status) {
+               self->status = gc_status;
+               geoclue_connectivity_emit_status_changed (GEOCLUE_CONNECTIVITY (self),
+                                                         self->status);
+       }
+}
+
+static void
+geoclue_conic_init (GeoclueConic *self)
+{
+       DBusConnection *system_bus = NULL;
+
+       self->status = GEOCLUE_CONNECTIVITY_UNKNOWN;
+
+       /* Need to run dbus_connection_setup_with_g_main(),
+        * otherwise conic signals will not fire... */
+       system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);
+       if (!system_bus) {
+               g_warning ("D-Bus system bus not available, connection signals not connected.");
+               return;
+       }
+       dbus_connection_setup_with_g_main (system_bus, NULL);
+
+       self->conic = con_ic_connection_new();
+       if (self->conic == NULL) {
+               g_warning ("Creating new ConicConnection failed");
+               return;
+       }
+
+       g_signal_connect (G_OBJECT (self->conic),
+                         "connection-event",
+                         G_CALLBACK (geoclue_conic_state_changed),
+                         self);
+
+       /* this should result in a connection-event signal with current
+        * connection status. Weird API.*/
+       g_object_set (G_OBJECT (self->conic),
+                     "automatic-connection-events",
+                     TRUE, NULL);
+}
+
+
+static void
+geoclue_conic_connectivity_init (GeoclueConnectivityInterface *iface)
+{
+       iface->get_status = get_status;
+}
+
+#endif /* HAVE_CONIC*/
diff --git a/src/connectivity-conic.h b/src/connectivity-conic.h
new file mode 100755 (executable)
index 0000000..f7733cd
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Geoclue
+ * connectivity-conic.h
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _CONNECTIVITY_CONIC_H
+#define _CONNECTIVITY_CONIC_H
+
+#include <glib-object.h>
+#include <conicconnection.h>
+#include "connectivity.h"
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_CONIC (geoclue_conic_get_type ())
+#define GEOCLUE_CONIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_CONIC, GeoclueConic))
+
+typedef struct {
+       GObject parent;
+
+       /* private */
+       GeoclueNetworkStatus status;
+       ConIcConnection *conic;
+} GeoclueConic;
+
+typedef struct {
+       GObjectClass parent_class;
+} GeoclueConicClass;
+
+GType geoclue_conic_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/connectivity-networkmanager.c b/src/connectivity-networkmanager.c
new file mode 100644 (file)
index 0000000..4d6b3f3
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Geoclue
+ * geoclue-networkmanager.c
+ *
+ * Authors: Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+#include <config.h>
+
+#ifdef HAVE_NETWORK_MANAGER
+
+
+#include <dbus/dbus-glib.h>
+#include <NetworkManager.h> /*for DBus strings */
+
+#ifdef HAVE_NETWORK_MANAGER
+#include <nm-client.h>
+#include <nm-device-wifi.h>
+#endif
+
+#include "connectivity-networkmanager.h"
+
+static void geoclue_networkmanager_connectivity_init (GeoclueConnectivityInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueNetworkManager, geoclue_networkmanager, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GEOCLUE_TYPE_CONNECTIVITY,
+                                                geoclue_networkmanager_connectivity_init))
+
+
+/* GeoclueConnectivity iface method */
+static int
+get_status (GeoclueConnectivity *iface)
+{
+       GeoclueNetworkManager *nm = GEOCLUE_NETWORKMANAGER (iface);
+
+       return nm->status;
+}
+
+static char *
+get_ap_mac (GeoclueConnectivity *iface)
+{
+       GeoclueNetworkManager *self = GEOCLUE_NETWORKMANAGER (iface);
+
+       return self->cache_ap_mac;
+}
+
+static void
+get_best_ap (GeoclueNetworkManager *self, NMDevice *device)
+{
+       const GPtrArray *aps;
+       guint i;
+
+       aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device));
+       if (aps == NULL || aps->len == 0)
+               return;
+       for (i = 0; i < aps->len; i++) {
+               NMAccessPoint *ap = NM_ACCESS_POINT (g_ptr_array_index (aps, i));
+               int strength;
+
+               strength = nm_access_point_get_strength (ap);
+               if (strength > self->ap_strength) {
+                       g_free (self->cache_ap_mac);
+                       self->cache_ap_mac = g_strdup (nm_access_point_get_hw_address (ap));
+                       self->ap_strength = strength;
+               }
+       }
+}
+
+static void
+cache_ap_mac (GeoclueNetworkManager *self)
+{
+       const GPtrArray *devices;
+       guint i;
+
+       g_free (self->cache_ap_mac);
+       self->cache_ap_mac = NULL;
+       self->ap_strength = 0;
+
+       devices = nm_client_get_devices (self->client);
+       if (devices == NULL) {
+            g_warning ("NetworkManager found no devices.");
+            return;
+       }
+
+       for (i = 0; i < devices->len; i++) {
+               NMDevice *device = g_ptr_array_index (devices, i);
+               if (NM_IS_DEVICE_WIFI (device)) {
+                       get_best_ap (self, device);
+               }
+       }
+}
+
+static void
+finalize (GObject *object)
+{
+       /* free everything */
+
+       ((GObjectClass *) geoclue_networkmanager_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       GeoclueNetworkManager *self = GEOCLUE_NETWORKMANAGER (object);
+
+       dbus_g_connection_unref (self->connection);
+       g_free (self->cache_ap_mac);
+       self->cache_ap_mac = NULL;
+       g_object_unref (self->client);
+       self->client = NULL;
+       ((GObjectClass *) geoclue_networkmanager_parent_class)->dispose (object);
+}
+
+static void
+geoclue_networkmanager_class_init (GeoclueNetworkManagerClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+}
+
+static GeoclueNetworkStatus
+nmstate_to_geocluenetworkstatus (NMState status)
+{
+       switch (status) {
+               case NM_STATE_UNKNOWN:
+                       return GEOCLUE_CONNECTIVITY_UNKNOWN;
+               case NM_STATE_ASLEEP:
+               case NM_STATE_DISCONNECTED:
+                       return GEOCLUE_CONNECTIVITY_OFFLINE;
+               case NM_STATE_CONNECTING:
+                       return GEOCLUE_CONNECTIVITY_ACQUIRING;
+               case NM_STATE_CONNECTED:
+                       return GEOCLUE_CONNECTIVITY_ONLINE;
+               default:
+                       g_warning ("Unknown NMStatus: %d", status);
+                       return GEOCLUE_CONNECTIVITY_UNKNOWN;
+       }
+}
+
+static void
+geoclue_networkmanager_state_changed (DBusGProxy *proxy,
+                                      NMState status,
+                                      gpointer userdata)
+{
+       GeoclueNetworkManager *self = GEOCLUE_NETWORKMANAGER (userdata);
+       GeoclueNetworkStatus gc_status;
+
+       gc_status = nmstate_to_geocluenetworkstatus (status);
+
+       if (gc_status != self->status) {
+               cache_ap_mac (self);
+               self->status = gc_status;
+               geoclue_connectivity_emit_status_changed (GEOCLUE_CONNECTIVITY (self),
+                                                         self->status);
+       }
+}
+
+
+#define NM_DBUS_SIGNAL_STATE_CHANGE "StateChange"
+
+static void
+geoclue_networkmanager_init (GeoclueNetworkManager *self)
+{
+       GError *error = NULL;
+       DBusGProxy *proxy;
+       NMState state;
+
+       self->status = GEOCLUE_CONNECTIVITY_UNKNOWN;
+
+       self->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+       if (self->connection == NULL) {
+               g_warning ("%s was unable to create a connection to D-Bus: %s",
+                          G_OBJECT_TYPE_NAME (self), error->message);
+               g_error_free (error);
+               return;
+       }
+
+       proxy = dbus_g_proxy_new_for_name (self->connection,
+                                          NM_DBUS_SERVICE,
+                                          NM_DBUS_PATH,
+                                          NM_DBUS_INTERFACE);
+       dbus_g_proxy_add_signal (proxy, NM_DBUS_SIGNAL_STATE_CHANGE,
+                                G_TYPE_UINT, G_TYPE_INVALID);
+       dbus_g_proxy_connect_signal (proxy, NM_DBUS_SIGNAL_STATE_CHANGE,
+                                    G_CALLBACK (geoclue_networkmanager_state_changed),
+                                    self, NULL);
+
+       if (dbus_g_proxy_call (proxy, "state", &error,
+                              G_TYPE_INVALID,
+                              G_TYPE_UINT, &state, G_TYPE_INVALID)){
+               self->status = nmstate_to_geocluenetworkstatus (state);
+       } else {
+               g_warning ("Could not get connectivity state from NetworkManager: %s", error->message);
+               g_error_free (error);
+       }
+
+       self->client = nm_client_new ();
+       cache_ap_mac (self);
+}
+
+
+static void
+geoclue_networkmanager_connectivity_init (GeoclueConnectivityInterface *iface)
+{
+       iface->get_status = get_status;
+       iface->get_ap_mac = get_ap_mac;
+}
+
+#endif /* HAVE_NETWORK_MANAGER */
diff --git a/src/connectivity-networkmanager.h b/src/connectivity-networkmanager.h
new file mode 100644 (file)
index 0000000..762822a
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Geoclue
+ * connectivity-networkmanager.h
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _CONNECTIVITY_NETWORKMANAGER_H
+#define _CONNECTIVITY_NETWORKMANAGER_H
+
+#include <glib-object.h>
+#include <nm-client.h>
+#include "connectivity.h"
+
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_NETWORKMANAGER (geoclue_networkmanager_get_type ())
+#define GEOCLUE_NETWORKMANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_NETWORKMANAGER, GeoclueNetworkManager))
+
+typedef struct {
+       GObject parent;
+
+       /* private */
+       GeoclueNetworkStatus status;
+       DBusGConnection *connection;
+       NMClient *client;
+       char *cache_ap_mac;
+       int ap_strength;
+} GeoclueNetworkManager;
+
+typedef struct {
+       GObjectClass parent_class;
+} GeoclueNetworkManagerClass;
+
+GType geoclue_networkmanager_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/connectivity.c b/src/connectivity.c
new file mode 100644 (file)
index 0000000..97ba408
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Geoclue
+ * geoclue-connectivity.c
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+#include <glib.h>
+#include "connectivity.h"
+
+enum {
+       STATUS_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+static void
+geoclue_connectivity_base_init (gpointer klass)
+{
+       static gboolean initialized = FALSE;
+
+       if (initialized) {
+               return;
+       }
+
+       initialized = TRUE;
+       signals[STATUS_CHANGED] = g_signal_new ("status-changed",
+                                 G_OBJECT_CLASS_TYPE (klass),
+                                 G_SIGNAL_RUN_LAST,
+                                 G_STRUCT_OFFSET (GeoclueConnectivityInterface,
+                                                  status_changed),
+                                 NULL, NULL,
+                                 g_cclosure_marshal_VOID__INT,
+                                 G_TYPE_NONE, 1, G_TYPE_INT);
+}
+
+GType
+geoclue_connectivity_get_type (void)
+{
+       static GType type = 0;
+
+       if (!type) {
+               const GTypeInfo info = {
+                       sizeof (GeoclueConnectivityInterface),
+                       geoclue_connectivity_base_init,
+                       NULL,
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                                              "GeoclueConnectivity",
+                                              &info, 0);
+       }
+
+       return type;
+}
+
+GeoclueNetworkStatus
+geoclue_connectivity_get_status (GeoclueConnectivity *self)
+{
+       return GEOCLUE_CONNECTIVITY_GET_INTERFACE (self)->get_status (self);
+}
+
+char *
+geoclue_connectivity_get_ap_mac (GeoclueConnectivity *self)
+{
+       if (GEOCLUE_CONNECTIVITY_GET_INTERFACE (self)->get_ap_mac != NULL)
+               return GEOCLUE_CONNECTIVITY_GET_INTERFACE (self)->get_ap_mac (self);
+       return NULL;
+}
+
+void
+geoclue_connectivity_emit_status_changed (GeoclueConnectivity *self,
+                                          GeoclueNetworkStatus status)
+{
+       g_signal_emit (self, signals[STATUS_CHANGED], 0, status);
+}
diff --git a/src/connectivity.h b/src/connectivity.h
new file mode 100644 (file)
index 0000000..7a835e0
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Geoclue
+ * geoclue-connectivity.h
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GEOCLUE_CONNECTIVITY_H
+#define _GEOCLUE_CONNECTIVITY_H
+
+#include <glib-object.h>
+#include <geoclue/geoclue-types.h>
+
+G_BEGIN_DECLS
+
+
+#define GEOCLUE_TYPE_CONNECTIVITY (geoclue_connectivity_get_type ())
+#define GEOCLUE_CONNECTIVITY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_CONNECTIVITY, GeoclueConnectivity))
+#define GEOCLUE_IS_CONNECTIVITY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_CONNECTIVITY))
+#define GEOCLUE_CONNECTIVITY_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GEOCLUE_TYPE_CONNECTIVITY, GeoclueConnectivityInterface))
+
+typedef struct _GeoclueConnectivity GeoclueConnectivity;
+typedef struct _GeoclueConnectivityInterface GeoclueConnectivityInterface;
+
+struct _GeoclueConnectivityInterface {
+       GTypeInterface parent;
+
+       /* signals */
+       void (* status_changed) (GeoclueConnectivity *self,
+                                GeoclueNetworkStatus status);
+
+       /* vtable */
+       int (*get_status) (GeoclueConnectivity *self);
+       char * (*get_ap_mac) (GeoclueConnectivity *self);
+};
+
+GType geoclue_connectivity_get_type (void);
+
+
+GeoclueNetworkStatus geoclue_connectivity_get_status (GeoclueConnectivity *self);
+
+char *geoclue_connectivity_get_ap_mac (GeoclueConnectivity *self);
+
+void
+geoclue_connectivity_emit_status_changed (GeoclueConnectivity *self,
+                                          GeoclueNetworkStatus status);
+
+G_END_DECLS
+
+#endif
diff --git a/src/main.c b/src/main.c
new file mode 100644 (file)
index 0000000..79b94c6
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Geoclue
+ * main.c - Master process
+ *
+ * Author: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+
+#include <gconf/gconf-client.h>
+
+#include <dbus/dbus-protocol.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-bindings.h>
+
+#include "master.h"
+
+static GMainLoop *mainloop;
+static GHashTable *options;
+static GcMaster *master;
+
+
+#define GEOCLUE_GCONF_TOP "/apps/geoclue/master"
+#define GEOCLUE_MASTER_NAME "org.freedesktop.Geoclue.Master"
+
+static void
+gconf_key_changed (GConfClient *client,
+                  guint cnxn_id,
+                  GConfEntry *entry,
+                  gpointer user_data)
+{
+       const char *key, *value;
+       GConfValue *v;
+
+       key = gconf_entry_get_key (entry);
+       v = gconf_entry_get_value (entry);
+       if (v->type != GCONF_VALUE_STRING)
+               return;
+       value = gconf_value_get_string (v);
+
+       g_message ("gconf key changed %s", key);
+
+       /* Don't add empty strings in the hashtable */
+       if (value != NULL && value[0] == '\0')
+               value = NULL;
+
+       g_hash_table_insert (options, g_path_get_basename (key),
+                            g_strdup (value));
+
+       g_signal_emit_by_name (G_OBJECT (master), "options-changed", options);
+}
+
+static GHashTable *
+load_options (void)
+{
+        GHashTable *ht = NULL;
+        GConfClient *client = gconf_client_get_default ();
+        GSList *entries, *e;
+        GError *error = NULL;
+
+        gconf_client_add_dir (client, GEOCLUE_GCONF_TOP,
+                             GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
+
+        entries = gconf_client_all_entries (client, GEOCLUE_GCONF_TOP, &error);
+        if (error != NULL) {
+                g_warning ("Error loading master options: %s", error->message);
+                g_error_free (error);
+                return NULL;
+        }
+
+        /* Setup keys monitoring */
+       gconf_client_notify_add (client, GEOCLUE_GCONF_TOP,
+                                (GConfClientNotifyFunc) gconf_key_changed,
+                                NULL, NULL, NULL);
+
+        ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+        g_print ("Master options:\n");
+        for (e = entries; e; e = e->next) {
+                GConfEntry *entry = e->data;
+                const char *key, *value;
+                GConfValue *v;
+
+                key = gconf_entry_get_key (entry);
+                v = gconf_entry_get_value (entry);
+                if (v->type != GCONF_VALUE_STRING)
+                       continue;
+                value = gconf_value_get_string (v);
+
+                if (value != NULL && value[0] == '\0')
+                       value = NULL;
+
+                g_print ("  %s = %s\n", key, value);
+                g_hash_table_insert (ht, g_path_get_basename (key),
+                                     g_strdup (value));
+                 gconf_entry_free (entry);
+         }
+         g_slist_free (entries);
+
+         return ht;
+ }
+
+GHashTable *
+geoclue_get_main_options (void)
+{
+        return options;
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+       DBusGConnection *conn;
+       DBusGProxy *proxy;
+       GError *error = NULL;
+       guint32 request_name_ret;
+
+       g_type_init ();
+
+       mainloop = g_main_loop_new (NULL, FALSE);
+
+       conn = dbus_g_bus_get (GEOCLUE_DBUS_BUS, &error);
+       if (!conn) {
+               g_error ("Error getting bus: %s", error->message);
+               return 1;
+       }
+
+       proxy = dbus_g_proxy_new_for_name (conn,
+                                          DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS);
+       if (!org_freedesktop_DBus_request_name (proxy, GEOCLUE_MASTER_NAME,
+                                               0, &request_name_ret, &error)) {
+               g_error ("Error registering D-Bus service %s: %s",
+                        GEOCLUE_MASTER_NAME, error->message);
+               return 1;
+       }
+
+       /* Just quit if master is already running */
+       if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+               return 1;
+       }
+
+        /* Load options */
+        options = load_options ();
+
+       master = g_object_new (GC_TYPE_MASTER, NULL);
+       dbus_g_connection_register_g_object (conn,
+                                            "/org/freedesktop/Geoclue/Master",
+                                            G_OBJECT (master));
+
+       g_main_loop_run (mainloop);
+       return 0;
+}
diff --git a/src/main.h b/src/main.h
new file mode 100755 (executable)
index 0000000..fc7d97d
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Geoclue
+ * main.h
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007-2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+#include <glib.h>
+
+GHashTable *geoclue_get_main_options (void);
+
+#endif
diff --git a/src/master-provider.c b/src/master-provider.c
new file mode 100644 (file)
index 0000000..ac3675c
--- /dev/null
@@ -0,0 +1,1310 @@
+/*
+ * Geoclue
+ * master-provider.c - Provider object for master and master client
+ *
+ * Author: Jussi Kukkonen <jku@o-hand.com>
+ *
+ * Copyright 2007-2008 by Garmin Ltd. or its subsidiaries
+ *                2008 OpenedHand Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ *  Provider object for GcMaster. Takes care of cacheing
+ *  queried data.
+ *
+ *  Should probably start/stop the actual providers as needed
+ *  in the future
+ *
+ *  Cache could also be used to save "stale" data for situations when
+ *  current data is not available (MasterClient api would have to
+ *  have a "allowOldData" setting)
+ *
+ * TODO:
+ *     figure out what to do if get_* returns GEOCLUE_ERROR_NOT_AVAILABLE.
+ *     Should try again, but when?
+ *
+ *     implement velocity
+ *
+ *     implement other (non-updating) ifaces
+ **/
+
+#include <string.h>
+
+#include "main.h"
+#include "master-provider.h"
+#include <geoclue/geoclue-position.h>
+#include <geoclue/geoclue-address.h>
+#include <geoclue/geoclue-marshal.h>
+
+typedef enum _GeoclueProvideFlags {
+       GEOCLUE_PROVIDE_NONE = 0,
+       GEOCLUE_PROVIDE_UPDATES = 1 << 0,                       /* will send *-changed signals */
+       GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION = 1 << 1,       /* data can be queried on new connection, and cached until connection ends */
+} GeoclueProvideFlags;
+
+typedef struct _GcPositionCache {
+       int timestamp;
+       GeocluePositionFields fields;
+       double latitude;
+       double longitude;
+       double altitude;
+       GeoclueAccuracy *accuracy;
+       GError *error;
+} GcPositionCache;
+
+typedef struct _GcAddressCache {
+       int timestamp;
+       GHashTable *details;
+       GeoclueAccuracy *accuracy;
+       GError *error;
+} GcAddressCache;
+
+typedef struct _GcMasterProviderPrivate {
+       char *name;
+       char *description;
+
+       char *service;
+       char *path;
+       GcInterfaceFlags interfaces;
+
+       GList *position_clients; /* list of clients currently using this provider */
+       GList *address_clients;
+
+       GeoclueAccuracyLevel expected_accuracy;
+
+       GeoclueResourceFlags required_resources;
+       GeoclueProvideFlags provides;
+
+       GeoclueStatus master_status; /* net_status and status affect this */
+       GeoclueNetworkStatus net_status;
+
+       GeoclueStatus status; /* cached status from actual provider */
+
+       GeocluePosition *position;
+       GcPositionCache position_cache;
+
+       GeoclueAddress *address;
+       GcAddressCache address_cache;
+
+} GcMasterProviderPrivate;
+
+enum {
+       STATUS_CHANGED,
+       ACCURACY_CHANGED,
+       POSITION_CHANGED,
+       ADDRESS_CHANGED,
+       NMEA_CHANGED,
+       LAST_SIGNAL
+};
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GC_TYPE_MASTER_PROVIDER, GcMasterProviderPrivate))
+
+G_DEFINE_TYPE (GcMasterProvider, gc_master_provider, G_TYPE_OBJECT)
+
+static void
+copy_error (GError **target, GError *source)
+{
+       if (*target) {
+               g_error_free (*target);
+               *target = NULL;
+       }
+       if (source) {
+               *target = g_error_copy (source);
+
+               /* If the error type is a D-Bus remote exception,
+                * don't lose the "magic" sauce after the message string.
+                * See the code in gerror_to_dbus_error_message() in dbus-glib */
+               if (source->domain == DBUS_GERROR &&
+                   source->code == DBUS_GERROR_REMOTE_EXCEPTION) {
+                       int len;
+                       g_free ((*target)->message);
+                       len = strlen (source->message);
+                       len += strlen (source->message + len + 1);
+                       len += 2;
+                       (*target)->message = g_memdup (source->message, len);
+               }
+       }
+}
+
+static GeoclueProvider*
+gc_master_provider_get_provider (GcMasterProvider *master_provider)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (master_provider);
+
+       if (priv->address) {
+               return GEOCLUE_PROVIDER (priv->address);
+       }
+       if (priv->position) {
+               return GEOCLUE_PROVIDER (priv->position);
+       }
+       return NULL;
+}
+
+static gboolean
+gc_master_provider_is_running (GcMasterProvider *master_provider)
+{
+       return (gc_master_provider_get_provider (master_provider) != NULL);
+}
+
+static void
+gc_master_provider_handle_new_position_accuracy (GcMasterProvider *provider,
+                                                 GeoclueAccuracy  *accuracy)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+       GeoclueAccuracyLevel old_level;
+       GeoclueAccuracyLevel new_level = GEOCLUE_ACCURACY_LEVEL_NONE;
+       double new_hor_acc, new_vert_acc;
+
+       geoclue_accuracy_get_details (priv->position_cache.accuracy,
+                                     &old_level, NULL, NULL);
+       if (accuracy) {
+               geoclue_accuracy_get_details (accuracy,
+                                             &new_level, &new_hor_acc, &new_vert_acc);
+       }
+       geoclue_accuracy_set_details (priv->position_cache.accuracy,
+                                     new_level, new_hor_acc, new_vert_acc);
+
+       if (old_level != new_level) {
+               g_signal_emit (provider, signals[ACCURACY_CHANGED], 0,
+                              GC_IFACE_POSITION, new_level);
+       }
+}
+
+static void
+gc_master_provider_handle_new_address_accuracy (GcMasterProvider *provider,
+                                                GeoclueAccuracy  *accuracy)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+       GeoclueAccuracyLevel old_level;
+       GeoclueAccuracyLevel new_level = GEOCLUE_ACCURACY_LEVEL_NONE;
+       double new_hor_acc, new_vert_acc;
+
+       geoclue_accuracy_get_details (priv->address_cache.accuracy,
+                                     &old_level, NULL, NULL);
+       if (accuracy) {
+               geoclue_accuracy_get_details (accuracy,
+                                             &new_level, &new_hor_acc, &new_vert_acc);
+       }
+       geoclue_accuracy_set_details (priv->address_cache.accuracy,
+                                     new_level, new_hor_acc, new_vert_acc);
+
+       if (old_level != new_level) {
+               g_signal_emit (provider, signals[ACCURACY_CHANGED], 0,
+                              GC_IFACE_ADDRESS, new_level);
+       }
+}
+
+static void
+gc_master_provider_set_position (GcMasterProvider      *provider,
+                                 GeocluePositionFields  fields,
+                                 int                    timestamp,
+                                 double                 latitude,
+                                 double                 longitude,
+                                 double                 altitude,
+                                 GeoclueAccuracy       *accuracy,
+                                 GError                *error)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+
+       priv->position_cache.timestamp = timestamp;
+       priv->position_cache.fields = fields;
+       priv->position_cache.latitude = latitude;
+       priv->position_cache.longitude = longitude;
+       priv->position_cache.altitude = altitude;
+
+       copy_error (&priv->position_cache.error, error);
+
+       /* emit accuracy-changed if needed, so masterclient can re-choose providers
+        * before we emit position-changed */
+       gc_master_provider_handle_new_position_accuracy (provider, accuracy);
+
+       if (!error) {
+               g_signal_emit (provider, signals[POSITION_CHANGED], 0,
+                              fields, timestamp,
+                              latitude, longitude, altitude,
+                              priv->position_cache.accuracy);
+       }
+}
+
+static void
+gc_master_provider_set_address (GcMasterProvider *provider,
+                                int               timestamp,
+                                GHashTable       *details,
+                                GeoclueAccuracy  *accuracy,
+                                GError           *error)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+
+       priv->address_cache.timestamp = timestamp;
+
+       g_hash_table_destroy (priv->address_cache.details);
+       if (details) {
+               priv->address_cache.details = geoclue_address_details_copy (details);
+       }else {
+               priv->address_cache.details = geoclue_address_details_new ();
+       }
+       copy_error (&priv->address_cache.error, error);
+
+       /* emit accuracy-changed if needed, so masterclient can re-choose providers
+        * before we emit position-changed */
+       gc_master_provider_handle_new_address_accuracy (provider, accuracy);
+
+       if (!error) {
+               g_signal_emit (provider, signals[ADDRESS_CHANGED], 0,
+                              priv->address_cache.timestamp,
+                              priv->address_cache.details,
+                              priv->address_cache.accuracy);
+       }
+}
+
+
+
+static GeoclueResourceFlags
+parse_resource_strings (char **flags)
+{
+       GeoclueResourceFlags resources = GEOCLUE_RESOURCE_NONE;
+       int i;
+
+       for (i = 0; flags[i]; i++) {
+               if (strcmp (flags[i], "RequiresNetwork") == 0) {
+                       resources |= GEOCLUE_RESOURCE_NETWORK;
+               } else if (strcmp (flags[i], "RequiresCell") == 0) {
+                       resources |= GEOCLUE_RESOURCE_CELL;
+               } else if (strcmp (flags[i], "RequiresGPS") == 0) {
+                       resources |= GEOCLUE_RESOURCE_GPS;
+               }
+       }
+
+       return resources;
+}
+
+static GeoclueProvideFlags
+parse_provide_strings (char **flags)
+{
+       GeoclueProvideFlags provides = GEOCLUE_PROVIDE_NONE;
+       int i;
+
+       for (i = 0; flags[i]; i++) {
+               if (strcmp (flags[i], "ProvidesUpdates") == 0) {
+                       provides |= GEOCLUE_PROVIDE_UPDATES;
+               } else if (strcmp (flags[i], "ProvidesCacheableOnConnection") == 0) {
+                       provides |= GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION;
+               }
+       }
+
+       return provides;
+}
+
+static GcInterfaceFlags
+parse_interface_strings (char **strs)
+{
+       GcInterfaceFlags ifaces = GC_IFACE_GEOCLUE;
+       int i;
+
+       for (i = 0; strs[i]; i++) {
+               if (strcmp (strs[i], GEOCLUE_POSITION_INTERFACE_NAME) == 0) {
+                       ifaces |= GC_IFACE_POSITION;
+               } else if (strcmp (strs[i], GEOCLUE_ADDRESS_INTERFACE_NAME) == 0) {
+                       ifaces |= GC_IFACE_ADDRESS;
+               }
+       }
+       return ifaces;
+}
+
+static GeoclueAccuracyLevel
+parse_accuracy_string (char *str)
+{
+       GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE;
+       if (!str || strcmp (str, "None") == 0) {
+               level = GEOCLUE_ACCURACY_LEVEL_NONE;
+       } else if (strcmp (str, "Country") == 0) {
+               level = GEOCLUE_ACCURACY_LEVEL_COUNTRY;
+       } else if (strcmp (str, "Region") == 0) {
+               level = GEOCLUE_ACCURACY_LEVEL_REGION;
+       } else if (strcmp (str, "Locality") == 0) {
+               level = GEOCLUE_ACCURACY_LEVEL_LOCALITY;
+       } else if (strcmp (str, "Postalcode") == 0) {
+               level = GEOCLUE_ACCURACY_LEVEL_POSTALCODE;
+       } else if  (strcmp (str, "Street") == 0) {
+               level = GEOCLUE_ACCURACY_LEVEL_STREET;
+       } else if  (strcmp (str, "Detailed") == 0) {
+               level = GEOCLUE_ACCURACY_LEVEL_DETAILED;
+       } else {
+               g_warning ("'%s' is not a recognised accuracy level value", str);
+       }
+       return level;
+}
+
+static void
+gc_master_provider_handle_error (GcMasterProvider *provider, GError *error)
+{
+       GcMasterProviderPrivate *priv;
+
+       g_assert (error);
+
+       priv = GET_PRIVATE (provider);
+       g_debug ("%s handling error %d", priv->name, error->code);
+
+       /* web service providers that are unavailable */
+       if (priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION &&
+           error->code == GEOCLUE_ERROR_NOT_AVAILABLE) {
+               priv->master_status = GEOCLUE_STATUS_UNAVAILABLE;
+               /* TODO set timer to re-check availability */
+       }
+}
+
+/* Sets master_status based on provider status and net_status
+ * Should be called whenever priv->status or priv->net_status change */
+static void
+gc_master_provider_handle_status_change (GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+
+       GeoclueStatus new_master_status;
+
+       /* calculate new master status */
+       if (priv->required_resources & GEOCLUE_RESOURCE_NETWORK ||
+           priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION) {
+               switch (priv->net_status) {
+                       case GEOCLUE_CONNECTIVITY_UNKNOWN:
+                               /* falling through */
+                       case GEOCLUE_CONNECTIVITY_OFFLINE:
+                               new_master_status = GEOCLUE_STATUS_UNAVAILABLE;
+                               break;
+                       case GEOCLUE_CONNECTIVITY_ACQUIRING:
+                               if (priv->status == GEOCLUE_STATUS_AVAILABLE){
+                                       new_master_status = GEOCLUE_STATUS_ACQUIRING;
+                               } else {
+                                       new_master_status = priv->status;
+                               }
+                               break;
+                       case GEOCLUE_CONNECTIVITY_ONLINE:
+                               new_master_status = priv->status;
+                               break;
+                       default:
+                               g_assert_not_reached ();
+               }
+
+       } else {
+               new_master_status = priv->status;
+       }
+
+       if (new_master_status != priv->master_status) {
+               priv->master_status = new_master_status;
+
+               g_signal_emit (provider, signals[STATUS_CHANGED], 0, new_master_status);
+       }
+}
+
+
+static void
+gc_master_provider_update_cache (GcMasterProvider *master_provider)
+{
+       GcMasterProviderPrivate *priv;
+
+       priv = GET_PRIVATE (master_provider);
+
+       if ((!(priv->provides & GEOCLUE_PROVIDE_UPDATES)) ||
+           (!gc_master_provider_get_provider (master_provider))) {
+               /* non-cacheable provider or provider not running */
+               return;
+       }
+
+       g_debug ("%s: Updating cache ", priv->name);
+       priv->master_status = GEOCLUE_STATUS_ACQUIRING;
+       g_signal_emit (master_provider, signals[STATUS_CHANGED], 0, priv->master_status);
+
+       if (priv->position) {
+               int timestamp;
+               double lat, lon, alt;
+               GeocluePositionFields fields;
+               GeoclueAccuracy *accuracy = NULL;
+               GError *error = NULL;
+
+               fields = geoclue_position_get_position (priv->position,
+                                                       &timestamp,
+                                                       &lat, &lon, &alt,
+                                                       &accuracy,
+                                                       &error);
+               if (error){
+                       g_warning ("Error updating position cache: %s", error->message);
+                       gc_master_provider_handle_error (master_provider, error);
+               }
+               gc_master_provider_set_position (master_provider,
+                                                fields, timestamp,
+                                                lat, lon, alt,
+                                                accuracy, error);
+       }
+
+       if (priv->address) {
+               int timestamp;
+               GHashTable *details = NULL;
+               GeoclueAccuracy *accuracy = NULL;
+               GError *error = NULL;
+
+               if (!geoclue_address_get_address (priv->address,
+                                                 &timestamp,
+                                                 &details,
+                                                 &accuracy,
+                                                 &error)) {
+                       g_warning ("Error updating address cache: %s", error->message);
+                       gc_master_provider_handle_error (master_provider, error);
+               }
+               gc_master_provider_set_address (master_provider,
+                                               timestamp,
+                                               details,
+                                               accuracy,
+                                               error);
+       }
+
+       gc_master_provider_handle_status_change (master_provider);
+}
+
+/* signal handlers for the actual providers signals */
+
+static void
+provider_status_changed (GeoclueProvider  *provider,
+                         GeoclueStatus     status,
+                         GcMasterProvider *master_provider)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (master_provider);
+
+       priv->status = status;
+       gc_master_provider_handle_status_change (master_provider);
+}
+
+static void
+position_changed (GeocluePosition      *position,
+                  GeocluePositionFields fields,
+                  int                   timestamp,
+                  double                latitude,
+                  double                longitude,
+                  double                altitude,
+                  GeoclueAccuracy      *accuracy,
+                  GcMasterProvider     *provider)
+{
+       /* is there a situation when we'd need to check against cache
+        * if data has really changed? probably not */
+       gc_master_provider_set_position (provider,
+                                        fields, timestamp,
+                                        latitude, longitude, altitude,
+                                        accuracy, NULL);
+}
+
+static void
+address_changed (GeoclueAddress   *address,
+                 int               timestamp,
+                 GHashTable       *details,
+                 GeoclueAccuracy  *accuracy,
+                 GcMasterProvider *provider)
+{
+       /* is there a situation when we'd need to check against cache
+        * if data has really changed? probably not */
+       gc_master_provider_set_address (provider,
+                                       timestamp,
+                                       details,
+                                        accuracy,
+                                        NULL);
+}
+
+
+static void
+finalize (GObject *object)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (object);
+
+       geoclue_accuracy_free (priv->position_cache.accuracy);
+       geoclue_accuracy_free (priv->address_cache.accuracy);
+       if (priv->position_cache.error) {
+               g_error_free (priv->position_cache.error);
+       }
+       if (priv->address_cache.error) {
+               g_error_free (priv->address_cache.error);
+       }
+
+       g_free (priv->name);
+       g_free (priv->description);
+       g_free (priv->service);
+       g_free (priv->path);
+
+       g_free (priv->position_clients);
+       g_free (priv->address_clients);
+
+       G_OBJECT_CLASS (gc_master_provider_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (object);
+
+       if (priv->position) {
+               g_object_unref (priv->position);
+               priv->position = NULL;
+       }
+
+       if (priv->address) {
+               g_object_unref (priv->address);
+               priv->address = NULL;
+       }
+       if (priv->address_cache.details) {
+               g_hash_table_destroy (priv->address_cache.details);
+               priv->address_cache.details = NULL;
+       }
+
+       G_OBJECT_CLASS (gc_master_provider_parent_class)->dispose (object);
+}
+
+static void
+gc_master_provider_class_init (GcMasterProviderClass *klass)
+{
+       GObjectClass *o_class = (GObjectClass *) klass;
+
+       o_class->finalize = finalize;
+       o_class->dispose = dispose;
+
+       g_type_class_add_private (klass, sizeof (GcMasterProviderPrivate));
+
+       signals[STATUS_CHANGED] = g_signal_new ("status-changed",
+                                                 G_TYPE_FROM_CLASS (klass),
+                                                 G_SIGNAL_RUN_FIRST |
+                                                 G_SIGNAL_NO_RECURSE,
+                                                 G_STRUCT_OFFSET (GcMasterProviderClass, status_changed),
+                                                 NULL, NULL,
+                                                 g_cclosure_marshal_VOID__INT,
+                                                 G_TYPE_NONE, 1,
+                                                 G_TYPE_INT);
+       signals[ACCURACY_CHANGED] = g_signal_new ("accuracy-changed",
+                                                 G_TYPE_FROM_CLASS (klass),
+                                                 G_SIGNAL_RUN_FIRST |
+                                                 G_SIGNAL_NO_RECURSE,
+                                                 G_STRUCT_OFFSET (GcMasterProviderClass, accuracy_changed),
+                                                 NULL, NULL,
+                                                 geoclue_marshal_VOID__INT_INT,
+                                                 G_TYPE_NONE, 2,
+                                                 G_TYPE_INT, G_TYPE_INT);
+       signals[POSITION_CHANGED] = g_signal_new ("position-changed",
+                                                 G_TYPE_FROM_CLASS (klass),
+                                                 G_SIGNAL_RUN_FIRST |
+                                                 G_SIGNAL_NO_RECURSE,
+                                                 G_STRUCT_OFFSET (GcMasterProviderClass, position_changed),
+                                                 NULL, NULL,
+                                                 geoclue_marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE_BOXED,
+                                                 G_TYPE_NONE, 6,
+                                                 G_TYPE_INT, G_TYPE_INT,
+                                                 G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE,
+                                                 G_TYPE_POINTER);
+       signals[ADDRESS_CHANGED] = g_signal_new ("address-changed",
+                                                G_TYPE_FROM_CLASS (klass),
+                                                G_SIGNAL_RUN_FIRST |
+                                                G_SIGNAL_NO_RECURSE,
+                                                G_STRUCT_OFFSET (GcMasterProviderClass, address_changed),
+                                                NULL, NULL,
+                                                geoclue_marshal_VOID__INT_BOXED_BOXED,
+                                                G_TYPE_NONE, 3,
+                                                G_TYPE_INT,
+                                                G_TYPE_POINTER,
+                                                G_TYPE_POINTER);
+}
+
+static void
+gc_master_provider_init (GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+
+       priv->position_clients = NULL;
+       priv->address_clients = NULL;
+
+       priv->master_status = GEOCLUE_STATUS_UNAVAILABLE;
+
+       priv->position = NULL;
+       priv->position_cache.accuracy =
+               geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0 ,0);
+       priv->position_cache.error = NULL;
+
+       priv->address = NULL;
+       priv->address_cache.accuracy =
+               geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0 ,0);
+       priv->address_cache.details = geoclue_address_details_new ();
+       priv->address_cache.error = NULL;
+}
+
+#if DEBUG_INFO
+static void
+gc_master_provider_dump_position (GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv;
+       GeocluePositionFields fields;
+       int time;
+       double lat, lon, alt;
+       GError *error = NULL;
+
+       priv = GET_PRIVATE (provider);
+
+
+       g_print ("     Position Information:\n");
+       g_print ("     ---------------------\n");
+
+       fields = gc_master_provider_get_position (provider,
+                                                 &time,
+                                                 &lat, &lon, &alt,
+                                                 NULL, &error);
+       if (error) {
+               g_print ("      Error: %s", error->message);
+               g_error_free (error);
+               return;
+       }
+       g_print ("       Timestamp: %d\n", time);
+       g_print ("       Latitude: %.2f %s\n", lat,
+                fields & GEOCLUE_POSITION_FIELDS_LATITUDE ? "" : "(not set)");
+       g_print ("       Longitude: %.2f %s\n", lon,
+                fields & GEOCLUE_POSITION_FIELDS_LONGITUDE ? "" : "(not set)");
+       g_print ("       Altitude: %.2f %s\n", alt,
+                fields & GEOCLUE_POSITION_FIELDS_ALTITUDE ? "" : "(not set)");
+
+}
+
+static void
+dump_address_key_and_value (char *key, char *value, GHashTable *target)
+{
+       g_print ("       %s: %s\n", key, value);
+}
+
+static void
+gc_master_provider_dump_address (GcMasterProvider *provider)
+{
+       int time;
+       GHashTable *details;
+       GError *error = NULL;
+
+       g_print ("     Address Information:\n");
+       g_print ("     --------------------\n");
+       if (!gc_master_provider_get_address (provider,
+                                            &time,
+                                            &details,
+                                            NULL, &error)) {
+               g_print ("      Error: %s", error->message);
+               g_error_free (error);
+               return;
+       }
+       g_print ("       Timestamp: %d\n", time);
+       g_hash_table_foreach (details, (GHFunc)dump_address_key_and_value, NULL);
+
+}
+
+static void
+gc_master_provider_dump_required_resources (GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv;
+
+       priv = GET_PRIVATE (provider);
+       g_print ("   Requires\n");
+       if (priv->required_resources & GEOCLUE_RESOURCE_GPS) {
+               g_print ("      - GPS\n");
+       }
+
+       if (priv->required_resources & GEOCLUE_RESOURCE_NETWORK) {
+               g_print ("      - Network\n");
+       }
+}
+
+static void
+gc_master_provider_dump_provides (GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv;
+
+       priv = GET_PRIVATE (provider);
+       g_print ("   Provides\n");
+       if (priv->provides & GEOCLUE_PROVIDE_UPDATES) {
+               g_print ("      - Updates\n");
+       }
+       if (priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION) {
+               g_print ("      - Cacheable on network connection\n");
+       }
+}
+
+static void
+gc_master_provider_dump_provider_details (GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv;
+
+       priv = GET_PRIVATE (provider);
+       g_print ("\n   Name - %s\n", priv->name);
+       g_print ("   Description - %s\n", priv->description);
+       g_print ("   Service - %s\n", priv->service);
+       g_print ("   Path - %s\n", priv->path);
+       g_print ("   Accuracy level - %d\n", priv->expected_accuracy);
+       g_print ("   Provider is currently %srunning, status %d\n",
+                gc_master_provider_get_provider (master_provider) ? "" : "not ",
+                priv->master_status);
+       gc_master_provider_dump_required_resources (provider);
+       gc_master_provider_dump_provides (provider);
+
+
+       if (priv->interfaces & GC_IFACE_POSITION) {
+               g_print ("   Interface - Position\n");
+               gc_master_provider_dump_position (provider);
+       }
+       if (priv->interfaces & GC_IFACE_ADDRESS) {
+               g_print ("   Interface - Address\n");
+               gc_master_provider_dump_address (provider);
+       }
+}
+#endif
+
+static gboolean
+gc_master_provider_initialize_geoclue (GcMasterProvider *master_provider)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (master_provider);
+       GeoclueProvider *geoclue;
+       GError *error = NULL;
+
+       geoclue = gc_master_provider_get_provider (master_provider);
+
+       if (!geoclue_provider_set_options (geoclue,
+                                          geoclue_get_main_options (),
+                                          &error)) {
+               g_warning ("Error setting provider options: %s\n", error->message);
+               g_error_free (error);
+               return FALSE;
+       }
+
+       /* priv->name has been read from .provider-file earlier...
+        * could ask the provider anyway, just to be consistent */
+       if (!geoclue_provider_get_provider_info (geoclue, NULL,
+                                                &priv->description, &error)) {
+               g_warning ("Error getting provider info: %s\n", error->message);
+               g_error_free (error);
+               return FALSE;
+       }
+
+       g_signal_connect (G_OBJECT (geoclue), "status-changed",
+                         G_CALLBACK (provider_status_changed), master_provider);
+
+
+       if (!geoclue_provider_get_status (geoclue, &priv->status, &error)) {
+               g_warning ("Error getting provider status: %s\n", error->message);
+               g_error_free (error);
+               return FALSE;
+       }
+       return TRUE;
+}
+
+static gboolean
+gc_master_provider_initialize_interfaces (GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv;
+
+       priv = GET_PRIVATE (provider);
+
+       if (priv->interfaces <= GC_IFACE_GEOCLUE) {
+               g_warning ("No interfaces defined for %s", priv->name);
+               return FALSE;
+       }
+
+       if (priv->interfaces & GC_IFACE_POSITION) {
+               if (priv->position == NULL) {
+                       priv->position = geoclue_position_new (priv->service,
+                                                              priv->path);
+                       g_signal_connect (G_OBJECT (priv->position), "position-changed",
+                                         G_CALLBACK (position_changed), provider);
+               }
+       }
+       if (priv->interfaces & GC_IFACE_ADDRESS) {
+               if (priv->address == NULL) {
+                       priv->address = geoclue_address_new (priv->service,
+                                                            priv->path);
+                       g_signal_connect (G_OBJECT (priv->address), "address-changed",
+                                         G_CALLBACK (address_changed), provider);
+               }
+       }
+
+       if (!gc_master_provider_initialize_geoclue (provider)) {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+static gboolean
+gc_master_provider_initialize (GcMasterProvider *provider)
+{
+       if (!gc_master_provider_initialize_interfaces (provider)) {
+               return FALSE;
+       }
+
+       gc_master_provider_update_cache (provider);
+#if DEBUG_INFO
+       gc_master_provider_dump_provider_details (provider);
+#endif
+       return TRUE;
+}
+
+static void
+gc_master_provider_deinitialize (GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+
+       if (priv->position) {
+               g_object_unref (priv->position);
+               priv->position = NULL;
+       }
+       if (priv->address) {
+               g_object_unref (priv->address);
+               priv->address = NULL;
+       }
+       g_debug ("deinited %s", priv->name);
+}
+
+static void
+network_status_changed (gpointer *connectivity,
+                        GeoclueNetworkStatus status,
+                        GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv;
+
+       priv = GET_PRIVATE (provider);
+
+       priv->net_status = status;
+       /* update connection-cacheable providers */
+       if (status == GEOCLUE_CONNECTIVITY_ONLINE &&
+           priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION) {
+               /* intialize to fill cache (this will handle status change) */
+               if (gc_master_provider_initialize (provider)) {
+                       gc_master_provider_deinitialize (provider);
+               }
+       } else {
+               gc_master_provider_handle_status_change (provider);
+       }
+}
+
+/* for updating cache on providers that are not running */
+static gboolean
+update_cache_and_deinit (GcMasterProvider *provider)
+{
+       /* fill cache */
+       if (gc_master_provider_initialize (provider)) {
+               gc_master_provider_deinitialize (provider);
+       }
+       return FALSE;
+}
+
+
+/* public methods (for GcMaster and GcMasterClient) */
+
+/* Loads provider details from 'filename' */
+GcMasterProvider *
+gc_master_provider_new (const char *filename,
+                        GeoclueConnectivity *connectivity)
+{
+       GcMasterProvider *provider;
+       GcMasterProviderPrivate *priv;
+       GKeyFile *keyfile;
+       GError *error = NULL;
+       gboolean ret;
+       char *accuracy_str;
+       char **flags, **interfaces;
+
+       keyfile = g_key_file_new ();
+       ret = g_key_file_load_from_file (keyfile, filename,
+                                        G_KEY_FILE_NONE, &error);
+       if (ret == FALSE) {
+               g_warning ("Error loading %s: %s", filename, error->message);
+               g_error_free (error);
+               g_key_file_free (keyfile);
+               return NULL;
+       }
+
+       provider = g_object_new (GC_TYPE_MASTER_PROVIDER, NULL);
+       priv = GET_PRIVATE (provider);
+
+       priv->name = g_key_file_get_value (keyfile, "Geoclue Provider",
+                                          "Name", NULL);
+       priv->service = g_key_file_get_value (keyfile, "Geoclue Provider",
+                                             "Service", NULL);
+       priv->path = g_key_file_get_value (keyfile, "Geoclue Provider",
+                                          "Path", NULL);
+
+       accuracy_str = g_key_file_get_value (keyfile, "Geoclue Provider",
+                                            "Accuracy", NULL);
+       priv->expected_accuracy = parse_accuracy_string (accuracy_str);
+       if (accuracy_str){
+               g_free (accuracy_str);
+       }
+
+       /* set cached accuracies to a default value */
+       geoclue_accuracy_set_details (priv->position_cache.accuracy,
+                                     priv->expected_accuracy, 0.0, 0.0);
+       geoclue_accuracy_set_details (priv->address_cache.accuracy,
+                                     priv->expected_accuracy, 0.0, 0.0);
+
+
+       flags = g_key_file_get_string_list (keyfile, "Geoclue Provider",
+                                           "Requires", NULL, NULL);
+       if (flags != NULL) {
+               priv->required_resources = parse_resource_strings (flags);
+               g_strfreev (flags);
+       } else {
+               priv->required_resources = GEOCLUE_RESOURCE_NONE;
+       }
+
+       flags = g_key_file_get_string_list (keyfile, "Geoclue Provider",
+                                           "Provides", NULL, NULL);
+       if (flags != NULL) {
+               priv->provides = parse_provide_strings (flags);
+               g_strfreev (flags);
+       } else {
+               priv->provides = GEOCLUE_PROVIDE_NONE;
+       }
+
+    if (!connectivity &&
+         (priv->required_resources & GEOCLUE_RESOURCE_NETWORK)) {
+           priv->provides &= ~GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION;
+               priv->net_status = GEOCLUE_CONNECTIVITY_ONLINE;
+               priv->status = GEOCLUE_STATUS_AVAILABLE;
+        gc_master_provider_handle_status_change (provider);
+    }
+
+       if (connectivity &&
+           (priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION)) {
+
+               /* we have network status events: mark network provider
+                * with update flag, set the callback and set use_cache */
+               priv->provides |= GEOCLUE_PROVIDE_UPDATES;
+
+               g_signal_connect (connectivity,
+                                 "status-changed",
+                                 G_CALLBACK (network_status_changed),
+                                 provider);
+               priv->net_status = geoclue_connectivity_get_status (connectivity);
+       }
+
+       priv->interfaces = GC_IFACE_GEOCLUE;
+       interfaces = g_key_file_get_string_list (keyfile,
+                                                "Geoclue Provider",
+                                                "Interfaces",
+                                                NULL, NULL);
+       if (interfaces) {
+               priv->interfaces = parse_interface_strings (interfaces);
+               g_strfreev (interfaces);
+       }
+
+       if (priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION &&
+           priv->net_status == GEOCLUE_CONNECTIVITY_ONLINE) {
+               /* do this as idle so we can return without waiting for http queries */
+               g_idle_add ((GSourceFunc)update_cache_and_deinit, provider);
+       }
+       return provider;
+}
+
+/* client calls this when it wants to use the provider.
+   Returns true if provider was actually started, and
+   client should assume accuracy has changed.
+   Returns false if provider was not started (it was either already
+   running or starting the provider failed). */
+gboolean
+gc_master_provider_subscribe (GcMasterProvider *provider,
+                              gpointer          client,
+                              GcInterfaceFlags  interface)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+       gboolean started = FALSE;
+
+       /* decide wether to run initialize or not */
+       if (!gc_master_provider_is_running (provider)) {
+               if (!(priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION)) {
+                       started = gc_master_provider_initialize (provider);
+               }
+       }
+
+       /* add subscription */
+       if (interface & GC_IFACE_POSITION) {
+               if (!g_list_find (priv->position_clients, client)) {
+                       priv->position_clients = g_list_prepend (priv->position_clients, client);
+               }
+       }
+       if (interface & GC_IFACE_ADDRESS) {
+               if (!g_list_find (priv->address_clients, client)) {
+                       priv->address_clients = g_list_prepend (priv->address_clients, client);
+               }
+       }
+
+       return started;
+}
+
+/* client calls this when it does not intend to use the provider */
+void
+gc_master_provider_unsubscribe (GcMasterProvider *provider,
+                                gpointer          client,
+                                GcInterfaceFlags  interface)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+
+       if (interface & GC_IFACE_POSITION) {
+               priv->position_clients = g_list_remove (priv->position_clients, client);
+       }
+       if (interface & GC_IFACE_ADDRESS) {
+               priv->address_clients = g_list_remove (priv->address_clients, client);
+       }
+
+       if (!priv->position_clients &&
+           !priv->address_clients) {
+               /* no one is using this provider, shutdown... */
+               /* not clearing cached accuracies on purpose */
+               g_debug ("%s without clients", priv->name);
+
+               /* gc_master_provider_deinitialize (provider); */
+       }
+}
+
+
+GeocluePositionFields
+gc_master_provider_get_position (GcMasterProvider *provider,
+                                 int              *timestamp,
+                                 double           *latitude,
+                                 double           *longitude,
+                                 double           *altitude,
+                                 GeoclueAccuracy **accuracy,
+                                 GError          **error)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+
+       g_assert (priv->position ||
+                 priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION);
+
+       if (priv->provides & GEOCLUE_PROVIDE_UPDATES) {
+               if (timestamp != NULL) {
+                       *timestamp = priv->position_cache.timestamp;
+               }
+               if (latitude != NULL) {
+                       *latitude = priv->position_cache.latitude;
+               }
+               if (longitude != NULL) {
+                       *longitude = priv->position_cache.longitude;
+               }
+               if (altitude != NULL) {
+                       *altitude = priv->position_cache.altitude;
+               }
+               if (accuracy != NULL) {
+                       *accuracy = geoclue_accuracy_copy (priv->position_cache.accuracy);
+               }
+               if (error != NULL) {
+                       g_assert (!*error);
+                       copy_error (error, priv->position_cache.error);
+               }
+               return priv->position_cache.fields;
+       } else {
+               return geoclue_position_get_position (priv->position,
+                                                     timestamp,
+                                                     latitude,
+                                                     longitude,
+                                                     altitude,
+                                                     accuracy,
+                                                     error);
+       }
+}
+
+gboolean
+gc_master_provider_get_address (GcMasterProvider  *provider,
+                                int               *timestamp,
+                                GHashTable       **details,
+                                GeoclueAccuracy  **accuracy,
+                                GError           **error)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+       if (priv->provides & GEOCLUE_PROVIDE_UPDATES) {
+
+               if (timestamp != NULL) {
+                       *timestamp = priv->address_cache.timestamp;
+               }
+               if (details != NULL) {
+                       *details = geoclue_address_details_copy (priv->address_cache.details);
+               }
+               if (accuracy != NULL) {
+                       *accuracy = geoclue_accuracy_copy (priv->address_cache.accuracy);
+               }
+               if (error != NULL) {
+                       g_assert (!*error);
+                       copy_error (error, priv->address_cache.error);
+               }
+               return (!priv->address_cache.error);
+       } else {
+               g_assert (priv->address);
+               return geoclue_address_get_address (priv->address,
+                                                   timestamp,
+                                                   details,
+                                                   accuracy,
+                                                   error);
+       }
+}
+
+gboolean
+gc_master_provider_is_good (GcMasterProvider     *provider,
+                            GcInterfaceFlags      iface_type,
+                            GeoclueAccuracyLevel  min_accuracy,
+                            gboolean              need_update,
+                            GeoclueResourceFlags  allowed_resources)
+{
+       GcMasterProviderPrivate *priv;
+       GcInterfaceFlags supported_ifaces;
+       GeoclueProvideFlags required_flags = GEOCLUE_PROVIDE_NONE;
+
+       priv = GET_PRIVATE (provider);
+
+       if (need_update) {
+               required_flags |= GEOCLUE_PROVIDE_UPDATES;
+       }
+
+       supported_ifaces = priv->interfaces;
+
+       /* provider must provide all that is required and
+        * cannot require a resource that is not allowed */
+       /* TODO: really, we need to change some of those terms... */
+
+       return (((supported_ifaces & iface_type) == iface_type) &&
+               ((priv->provides & required_flags) == required_flags) &&
+               (priv->expected_accuracy >= min_accuracy) &&
+               ((priv->required_resources & (~allowed_resources)) == 0));
+}
+
+void
+gc_master_provider_update_options (GcMasterProvider *provider)
+{
+       GeoclueProvider *geoclue;
+       GError *error = NULL;
+
+       geoclue = gc_master_provider_get_provider (provider);
+
+       if (!geoclue_provider_set_options (geoclue,
+                                          geoclue_get_main_options (),
+                                          &error)) {
+               g_warning ("Error setting provider options: %s\n", error->message);
+               g_error_free (error);
+       }
+}
+
+GeoclueStatus
+gc_master_provider_get_status (GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+
+       return priv->master_status;
+}
+
+GeoclueAccuracyLevel
+gc_master_provider_get_accuracy (GcMasterProvider *provider, GcInterfaceFlags iface)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+       GeoclueAccuracyLevel acc_level;
+
+       switch (iface) {
+               case GC_IFACE_POSITION:
+                       geoclue_accuracy_get_details (priv->position_cache.accuracy,
+                                                     &acc_level, NULL, NULL);
+                       break;
+               case GC_IFACE_ADDRESS:
+                       geoclue_accuracy_get_details (priv->address_cache.accuracy,
+                                                     &acc_level, NULL, NULL);
+                       break;
+               default:
+                       g_assert_not_reached ();
+       }
+       return acc_level;
+}
+
+/*returns a reference, but is not meant for editing...*/
+char *
+gc_master_provider_get_name (GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+
+       return priv->name;
+}
+char *
+gc_master_provider_get_description (GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+
+       return priv->description;
+}
+char *
+gc_master_provider_get_service (GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+
+       return priv->service;
+}
+char *
+gc_master_provider_get_path (GcMasterProvider *provider)
+{
+       GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
+
+       return priv->path;
+}
+
+/* GCompareDataFunc for sorting providers by accuracy and required resources */
+int
+gc_master_provider_compare (GcMasterProvider *a,
+                            GcMasterProvider *b,
+                            GcInterfaceAccuracy *iface_min_accuracy)
+{
+       int diff;
+       GeoclueAccuracy *acc_a, *acc_b;
+       GeoclueAccuracyLevel level_a, level_b, min_level;
+
+
+       GcMasterProviderPrivate *priv_a = GET_PRIVATE (a);
+       GcMasterProviderPrivate *priv_b = GET_PRIVATE (b);
+
+       /* get the current accuracylevels */
+       switch (iface_min_accuracy->interface) {
+               case GC_IFACE_POSITION:
+                       acc_a = priv_a->position_cache.accuracy;
+                       acc_b = priv_b->position_cache.accuracy;
+                       break;
+               case GC_IFACE_ADDRESS:
+                       acc_a = priv_a->address_cache.accuracy;
+                       acc_b = priv_b->address_cache.accuracy;
+                       break;
+               default:
+                       g_warning("iface: %d", iface_min_accuracy->interface);
+                       g_assert_not_reached ();
+       }
+
+
+       geoclue_accuracy_get_details (acc_a, &level_a, NULL, NULL);
+       geoclue_accuracy_get_details (acc_b, &level_b, NULL, NULL);
+       min_level = iface_min_accuracy->accuracy_level;
+
+       /* sort by resource requirements and accuracy, but only if both
+        * providers meet the minimum accuracy requirement  */
+       if ((level_b >= min_level) &&
+           (level_a >= min_level)) {
+               diff = priv_a->required_resources - priv_b->required_resources;
+               if (diff != 0 ) {
+                       return diff;
+               }
+               return level_b - level_a;
+       }
+
+       /* one or both do not meet req's, sort by accuracy */
+       return level_b - level_a;
+}
diff --git a/src/master-provider.h b/src/master-provider.h
new file mode 100755 (executable)
index 0000000..309ba0d
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Geoclue
+ * master-provider.h
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007-2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef MASTER_PROVIDER_H
+#define MASTER_PROVIDER_H
+
+
+#include <geoclue/geoclue-provider.h>
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+#include "connectivity.h"
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_MASTER_PROVIDER (gc_master_provider_get_type ())
+#define GC_MASTER_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_MASTER_PROVIDER, GcMasterProvider))
+#define GC_IS_MASTER_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GC_TYPE_MASTER_PROVIDER))
+
+typedef enum {
+       GC_IFACE_NONE = 0,
+       GC_IFACE_GEOCLUE = 1 << 0,
+       GC_IFACE_POSITION = 1 << 1,
+       GC_IFACE_ADDRESS = 1 << 2,
+       GC_IFACE_VELOCITY = 1 << 3,
+       GC_IFACE_GEOCODE = 1 << 4,
+       GC_IFACE_REVERSE_GEOCODE = 1 << 5,
+
+       GC_IFACE_ALL = (1 << 6) - 1
+} GcInterfaceFlags;
+
+
+typedef struct _GcMasterProvider {
+       GObject parent;
+} GcMasterProvider;
+
+typedef struct _GcMasterProviderClass {
+       GObjectClass parent_class;
+
+       void (* status_changed) (GcMasterProvider *master_provider,
+                                GeoclueStatus     status);
+       void (* accuracy_changed) (GcMasterProvider     *master_provider,
+                                  GcInterfaceFlags      interface,
+                                  GeoclueAccuracyLevel  status);
+       void (* position_changed) (GcMasterProvider     *master_provider,
+                                  GeocluePositionFields fields,
+                                  int                   timestamp,
+                                  double                latitude,
+                                  double                longitude,
+                                  double                altitude,
+                                  GeoclueAccuracy      *accuracy);
+       void (* address_changed) (GcMasterProvider *master_provider,
+                                 int               timestamp,
+                                 GHashTable       *details,
+                                 GeoclueAccuracy  *accuracy);
+} GcMasterProviderClass;
+
+GType gc_master_provider_get_type (void);
+
+GcMasterProvider *gc_master_provider_new (const char *filename,
+                                          GeoclueConnectivity *connectivity);
+
+gboolean gc_master_provider_subscribe (GcMasterProvider *provider,
+                                       gpointer          client,
+                                       GcInterfaceFlags  interface);
+void gc_master_provider_unsubscribe (GcMasterProvider *provider,
+                                     gpointer          client,
+                                     GcInterfaceFlags  interface);
+
+/* for gc_master_provider_compare */
+typedef struct _GcInterfaceAccuracy {
+       GcInterfaceFlags interface;
+       GeoclueAccuracyLevel accuracy_level;
+} GcInterfaceAccuracy;
+
+gint gc_master_provider_compare (GcMasterProvider *a,
+                                 GcMasterProvider *b,
+                                 GcInterfaceAccuracy *iface_min_accuracy);
+
+gboolean gc_master_provider_is_good (GcMasterProvider     *provider,
+                                     GcInterfaceFlags      iface_types,
+                                     GeoclueAccuracyLevel  min_accuracy,
+                                     gboolean              need_update,
+                                     GeoclueResourceFlags  allowed_resources);
+
+void gc_master_provider_network_status_changed (GcMasterProvider *provider,
+                                                GeoclueNetworkStatus status);
+void gc_master_provider_update_options (GcMasterProvider *provider);
+
+char* gc_master_provider_get_name (GcMasterProvider *provider);
+char* gc_master_provider_get_description (GcMasterProvider *provider);
+char* gc_master_provider_get_service (GcMasterProvider *provider);
+char* gc_master_provider_get_path (GcMasterProvider *provider);
+
+GeoclueStatus gc_master_provider_get_status (GcMasterProvider *provider);
+GeoclueAccuracyLevel gc_master_provider_get_accuracy (GcMasterProvider *provider, GcInterfaceFlags iface);
+
+GeocluePositionFields gc_master_provider_get_position (GcMasterProvider *master_provider,
+                                                       int              *timestamp,
+                                                       double           *latitude,
+                                                       double           *longitude,
+                                                       double           *altitude,
+                                                       GeoclueAccuracy **accuracy,
+                                                       GError          **error);
+
+gboolean gc_master_provider_get_address (GcMasterProvider  *master_provider,
+                                         int               *timestamp,
+                                         GHashTable       **details,
+                                         GeoclueAccuracy  **accuracy,
+                                         GError           **error);
+
+
+G_END_DECLS
+
+#endif /* MASTER_PROVIDER_H */
diff --git a/src/master.c b/src/master.c
new file mode 100644 (file)
index 0000000..d4186ba
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Geoclue
+ * master.c - Master process
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ *          Jussi Kukkonen <jku@o-hand.com>
+ * Copyright 2007-2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include "main.h"
+#include "master.h"
+#include "client.h"
+#include "master-provider.h"
+
+#ifdef HAVE_NETWORK_MANAGER
+#include "connectivity-networkmanager.h"
+#else
+#ifdef HAVE_CONIC
+#include "connectivity-conic.h"
+#endif
+#endif
+
+enum {
+       OPTIONS_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+G_DEFINE_TYPE (GcMaster, gc_master, G_TYPE_OBJECT);
+
+static GList *providers = NULL;
+
+static gboolean gc_iface_master_create (GcMaster    *master,
+                                       const char **object_path,
+                                       GError     **error);
+
+#include "gc-iface-master-glue.h"
+
+#define GEOCLUE_MASTER_PATH "/org/freedesktop/Geoclue/Master/client"
+static gboolean
+gc_iface_master_create (GcMaster    *master,
+                       const char **object_path,
+                       GError     **error)
+{
+       static guint32 serial = 0;
+       GcMasterClient *client;
+       char *path;
+
+       path = g_strdup_printf ("%s%d", GEOCLUE_MASTER_PATH, serial++);
+       client = g_object_new (GC_TYPE_MASTER_CLIENT, NULL);
+       dbus_g_connection_register_g_object (master->connection, path,
+                                            G_OBJECT (client));
+
+       if (object_path) {
+               *object_path = path;
+       }
+       return TRUE;
+}
+
+static void
+gc_master_class_init (GcMasterClass *klass)
+{
+       dbus_g_object_type_install_info (gc_master_get_type (),
+                                        &dbus_glib_gc_iface_master_object_info);
+
+       signals[OPTIONS_CHANGED] = g_signal_new ("options-changed",
+                                                 G_TYPE_FROM_CLASS (klass),
+                                                 G_SIGNAL_RUN_FIRST |
+                                                 G_SIGNAL_NO_RECURSE,
+                                                 G_STRUCT_OFFSET (GcMasterClass, options_changed),
+                                                 NULL, NULL,
+                                                 g_cclosure_marshal_VOID__BOXED,
+                                                 G_TYPE_NONE, 1,
+                                                 G_TYPE_HASH_TABLE);
+}
+
+/* Load the provider details out of a keyfile */
+static void
+gc_master_add_new_provider (GcMaster   *master,
+                            const char *filename)
+{
+       GcMasterProvider *provider;
+
+       provider = gc_master_provider_new (filename,
+                                          master->connectivity);
+
+       if (!provider) {
+               g_warning ("Loading from %s failed", filename);
+               return;
+       }
+
+       providers = g_list_prepend (providers, provider);
+}
+
+/* Scan a directory for .provider files */
+#define PROVIDER_EXTENSION ".provider"
+
+static void
+gc_master_load_providers (GcMaster *master)
+{
+       GDir *dir;
+       GError *error = NULL;
+       const char *filename;
+
+       dir = g_dir_open (GEOCLUE_PROVIDERS_DIR, 0, &error);
+       if (dir == NULL) {
+               g_warning ("Error opening %s: %s\n", GEOCLUE_PROVIDERS_DIR,
+                          error->message);
+               g_error_free (error);
+               return;
+       }
+
+       filename = g_dir_read_name (dir);
+       if (!filename) {
+               g_print ("No providers found in %s\n", dir);
+       } else {
+               g_print ("Found providers:\n");
+       }
+       while (filename) {
+               char *fullname, *ext;
+
+               g_print ("  %s\n", filename);
+               ext = strrchr (filename, '.');
+               if (ext == NULL || strcmp (ext, PROVIDER_EXTENSION) != 0) {
+                       g_print ("   - Ignored\n");
+                       filename = g_dir_read_name (dir);
+                       continue;
+               }
+
+               fullname = g_build_filename (GEOCLUE_PROVIDERS_DIR,
+                                            filename, NULL);
+               gc_master_add_new_provider (master, fullname);
+               g_free (fullname);
+
+               filename = g_dir_read_name (dir);
+       }
+
+       g_dir_close (dir);
+}
+
+static void
+gc_master_init (GcMaster *master)
+{
+       GError *error = NULL;
+
+
+       master->connection = dbus_g_bus_get (GEOCLUE_DBUS_BUS, &error);
+       if (master->connection == NULL) {
+               g_warning ("Could not get %s: %s", GEOCLUE_DBUS_BUS,
+                          error->message);
+               g_error_free (error);
+       }
+
+       master->connectivity = NULL;
+#ifdef HAVE_NETWORK_MANAGER
+       master->connectivity = GEOCLUE_CONNECTIVITY (g_object_new (GEOCLUE_TYPE_NETWORKMANAGER, NULL));
+#else
+#ifdef HAVE_CONIC
+       master->connectivity = GEOCLUE_CONNECTIVITY (g_object_new (GEOCLUE_TYPE_CONIC, NULL));
+#endif
+#endif
+
+       gc_master_load_providers (master);
+}
+
+
+GList *
+gc_master_get_providers (GcInterfaceFlags      iface_type,
+                         GeoclueAccuracyLevel  min_accuracy,
+                         gboolean              can_update,
+                         GeoclueResourceFlags  allowed,
+                         GError              **error)
+{
+       GList *l, *p = NULL;
+
+       if (providers == NULL) {
+               return NULL;
+       }
+
+       for (l = providers; l; l = l->next) {
+               GcMasterProvider *provider = l->data;
+
+               if (gc_master_provider_is_good (provider,
+                                               iface_type,
+                                               min_accuracy,
+                                               can_update,
+                                               allowed)) {
+                       p = g_list_prepend (p, provider);
+               }
+       }
+
+       return p;
+}
diff --git a/src/master.h b/src/master.h
new file mode 100755 (executable)
index 0000000..549411b
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Geoclue
+ * master.h - Master process
+ *
+ * Authors: Iain Holmes <iain@openedhand.com>
+ * Copyright 2007-2008 by Garmin Ltd. or its subsidiaries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _MASTER_H_
+#define _MASTER_H_
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+#include <geoclue/geoclue-types.h>
+#include <geoclue/geoclue-accuracy.h>
+#include "connectivity.h"
+#include "master-provider.h"
+
+#define GC_TYPE_MASTER (gc_master_get_type ())
+#define GC_MASTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GC_TYPE_MASTER, GcMaster))
+
+typedef struct {
+       GObject parent;
+
+       GMainLoop *loop;
+       DBusGConnection *connection;
+       GeoclueConnectivity *connectivity;
+} GcMaster;
+
+typedef struct {
+       GObjectClass parent_class;
+
+       void (*options_changed) (GcMaster *master, GHashTable *options);
+} GcMasterClass;
+
+GType gc_master_get_type (void);
+GList *gc_master_get_providers (GcInterfaceFlags      iface_type,
+                               GeoclueAccuracyLevel  min_accuracy,
+                               gboolean              can_update,
+                               GeoclueResourceFlags  allowed,
+                               GError              **error);
+
+#endif
+
diff --git a/src/org.freedesktop.Geoclue.Master.service.in b/src/org.freedesktop.Geoclue.Master.service.in
new file mode 100755 (executable)
index 0000000..7ed0511
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Geoclue.Master
+Exec=@libexecdir@/geoclue-master
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644 (file)
index 0000000..9547151
--- /dev/null
@@ -0,0 +1,18 @@
+if HAVE_GTK
+
+bin_PROGRAMS = geoclue-test-gui
+
+geoclue_test_gui_LDADD = \
+       $(GTK_LIBS) \
+       $(GEOCLUE_LIBS) \
+       $(top_builddir)/geoclue/libgeoclue.la
+
+geoclue_test_gui_CFLAGS= \
+       -DGEOCLUE_PROVIDERS_DIR=\""$(datadir)/geoclue-providers"\" \
+       $(GTK_CFLAGS) \
+       $(GEOCLUE_CFLAGS)
+
+geoclue_test_gui_SOURCES = \
+       geoclue-test-gui.c
+
+endif
diff --git a/test/geoclue-test-gui.c b/test/geoclue-test-gui.c
new file mode 100644 (file)
index 0000000..929eebf
--- /dev/null
@@ -0,0 +1,911 @@
+/*
+ * Geoclue
+ * client-test-gui.c - Geoclue Test GUI
+ *
+ * Authors: Jussi Kukkonen <jku@linux.intel.com>
+ *
+ * Copyright 2008 OpenedHand Ltd
+ *           2008 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <time.h>
+#include <string.h>
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <geoclue/geoclue-master.h>
+#include <geoclue/geoclue-master-client.h>
+#include <geoclue/geoclue-address.h>
+#include <geoclue/geoclue-position.h>
+
+enum {
+       COL_ADDRESS_PROVIDER = 0,
+       COL_ADDRESS_PROVIDER_NAME,
+       COL_ADDRESS_IS_MASTER,
+       COL_ADDRESS_COUNTRY,
+       COL_ADDRESS_COUNTRYCODE,
+       COL_ADDRESS_REGION,
+       COL_ADDRESS_LOCALITY,
+       COL_ADDRESS_AREA,
+       COL_ADDRESS_POSTALCODE,
+       COL_ADDRESS_STREET,
+       NUM_ADDRESS_COLS
+};
+enum {
+       COL_POSITION_PROVIDER = 0,
+       COL_POSITION_PROVIDER_NAME,
+       COL_POSITION_IS_MASTER,
+       COL_POSITION_LAT,
+       COL_POSITION_LON,
+       COL_POSITION_ALT,
+       NUM_POSITION_COLS
+};
+
+
+#define GEOCLUE_TYPE_TEST_GUI geoclue_test_gui_get_type()
+#define GEOCLUE_TEST_GUI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_TEST_GUI, GeoclueTestGui))
+#define GEOCLUE_TEST_GUI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEOCLUE_TYPE_TEST_GUI, GeoclueTestGuiClass))
+#define GEOCLUE_TEST_GUI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEOCLUE_TYPE_TEST_GUI, GeoclueTestGuiClass))
+
+typedef struct {
+       GObject parent;
+
+       GtkWidget *window;
+       GtkTextBuffer *buffer;
+
+       GeoclueMasterClient *client;
+       char *master_client_path;
+       GeoclueAccuracyLevel master_accuracy;
+       GeoclueResourceFlags master_resources;
+
+       GtkListStore *position_store;
+       GList *position_providers; /* PositionProviders, first one is master */
+
+       GtkListStore *address_store;
+       GList *address_providers; /* AddressProviders, first one is master */
+} GeoclueTestGui;
+
+typedef struct {
+       GObjectClass parent_class;
+} GeoclueTestGuiClass;
+
+G_DEFINE_TYPE (GeoclueTestGui, geoclue_test_gui, G_TYPE_OBJECT)
+
+
+static void
+geoclue_test_gui_dispose (GObject *object)
+{
+
+       G_OBJECT_CLASS (geoclue_test_gui_parent_class)->dispose (object);
+}
+
+
+static void
+geoclue_test_gui_class_init (GeoclueTestGuiClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->dispose = geoclue_test_gui_dispose;
+}
+
+
+static void
+geoclue_test_gui_master_log_message (GeoclueTestGui *gui, char *message)
+{
+       GtkTextIter iter;
+       char *line;
+       time_t rawtime;
+       struct tm *timeinfo;
+       char time_buffer [20];
+
+       time (&rawtime);
+       timeinfo = localtime (&rawtime);
+
+       strftime (time_buffer, 19, "%X", timeinfo);
+       line = g_strdup_printf ("%s: %s\n", time_buffer, message);
+
+       gtk_text_buffer_get_end_iter (gui->buffer, &iter);
+       gtk_text_buffer_insert (gui->buffer, &iter, line, -1);
+
+       g_free (line);
+}
+
+static gboolean
+get_matching_tree_iter (GtkTreeModel *model, GeoclueProvider *provider, GtkTreeIter *iter)
+{
+       GeoclueProvider *p = NULL;
+       gboolean valid;
+
+       g_assert (model);
+       g_assert (provider);
+
+       valid = gtk_tree_model_get_iter_first (model, iter);
+       while (valid) {
+               gtk_tree_model_get (model, iter,
+                                   COL_ADDRESS_PROVIDER, &p,
+                                   -1);
+               if (p == provider) {
+                       return TRUE;
+               }
+
+               valid = gtk_tree_model_iter_next (model, iter);
+       }
+
+       return FALSE;
+}
+
+static void
+update_address (GeoclueTestGui *gui, GeoclueAddress *address, GHashTable *details)
+{
+       GtkTreeIter iter;
+
+       g_assert (details);
+
+       if (get_matching_tree_iter (GTK_TREE_MODEL (gui->address_store),
+                                   GEOCLUE_PROVIDER (address),
+                                   &iter)) {
+               gtk_list_store_set (gui->address_store, &iter,
+                                   COL_ADDRESS_COUNTRY, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_COUNTRY),
+                                   COL_ADDRESS_COUNTRYCODE, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_COUNTRYCODE),
+                                   COL_ADDRESS_REGION, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_REGION),
+                                   COL_ADDRESS_LOCALITY, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_LOCALITY),
+                                   COL_ADDRESS_AREA, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_AREA),
+                                   COL_ADDRESS_POSTALCODE, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_POSTALCODE),
+                                   COL_ADDRESS_STREET, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_STREET),
+                                   -1);
+       }
+}
+
+
+static void
+update_position (GeoclueTestGui *gui, GeocluePosition *position,
+                 double lat, double lon, double alt)
+{
+       GtkTreeIter iter;
+
+       if (get_matching_tree_iter (GTK_TREE_MODEL (gui->position_store),
+                                   GEOCLUE_PROVIDER (position),
+                                   &iter)) {
+               gtk_list_store_set (gui->position_store, &iter,
+                                   COL_POSITION_LAT, lat,
+                                   COL_POSITION_LON, lon,
+                                   COL_POSITION_ALT, alt,
+                                   -1);
+       }
+}
+
+
+static void
+address_changed (GeoclueAddress  *address,
+                 int              timestamp,
+                 GHashTable      *details,
+                 GeoclueAccuracy *accuracy,
+                 GeoclueTestGui  *gui)
+{
+       update_address (gui, address, details);
+}
+
+
+static void
+position_changed (GeocluePosition      *position,
+                  GeocluePositionFields fields,
+                  int                   timestamp,
+                  double                latitude,
+                  double                longitude,
+                  double                altitude,
+                  GeoclueAccuracy      *accuracy,
+                  GeoclueTestGui       *gui)
+{
+       update_position (gui, position, latitude, longitude, altitude);
+}
+
+static void
+address_callback (GeoclueAddress *address,
+                  int timestamp,
+                  GHashTable *details,
+                  GeoclueAccuracy *accuracy,
+                  GError *error,
+                  gpointer userdata)
+{
+       if (error) {
+               g_warning ("Error getting address: %s\n", error->message);
+               g_error_free (error);
+               details = geoclue_address_details_new ();
+       }
+
+       update_address (GEOCLUE_TEST_GUI (userdata), address, details);
+}
+
+static void
+info_callback (GeoclueProvider *provider,
+               char *name,
+               char *description,
+               GError *error,
+               gpointer userdata)
+{
+       GtkTreeIter iter;
+       GeoclueTestGui *gui = GEOCLUE_TEST_GUI (userdata);
+
+       if (error) {
+               g_warning ("Error getting provider info: %s\n", error->message);
+               g_error_free (error);
+               return;
+       }
+
+       if (get_matching_tree_iter (GTK_TREE_MODEL (gui->address_store),
+                                   provider,
+                                   &iter)) {
+               /* skip master, that's handled in master_*_provider_changed */
+               if (strcmp (name, "Geoclue Master") != 0) {
+                       gtk_list_store_set (gui->address_store, &iter,
+                                           COL_ADDRESS_PROVIDER_NAME, name,
+                                           -1);
+               }
+       }
+
+       if (get_matching_tree_iter (GTK_TREE_MODEL (gui->position_store),
+                                   provider,
+                                   &iter)) {
+               /* skip master, that's handled in master_*_provider_changed */
+               if (strcmp (name, "Geoclue Master") != 0) {
+                       gtk_list_store_set (gui->position_store, &iter,
+                                           COL_POSITION_PROVIDER_NAME, name,
+                                           -1);
+               }
+       }
+}
+
+static void
+add_to_address_store (GeoclueTestGui *gui, GeoclueAddress *address, gboolean is_master)
+{
+       GtkTreeIter iter;
+
+       g_assert (gui->address_store);
+       g_assert (address);
+
+       if (is_master) {
+               /* master is already on the first line */
+               gtk_tree_model_get_iter_first (GTK_TREE_MODEL (gui->address_store), &iter);
+       } else {
+               gtk_list_store_append (gui->address_store, &iter);
+       }
+       gtk_list_store_set (gui->address_store, &iter,
+                           COL_ADDRESS_PROVIDER, address,
+                           COL_ADDRESS_IS_MASTER, is_master,
+                           -1);
+
+       g_signal_connect (G_OBJECT (address), "address-changed",
+                               G_CALLBACK (address_changed), gui);
+
+       geoclue_provider_get_provider_info_async (GEOCLUE_PROVIDER (address),
+                                                 info_callback,
+                                                 gui);
+       geoclue_address_get_address_async (address, address_callback, gui);
+
+}
+
+static gboolean
+get_next_provider (GDir *dir, char **name, char **service, char **path, char **ifaces)
+{
+       const char *filename;
+       char *fullname;
+       GKeyFile *keyfile;
+       gboolean ret;
+       GError *error;
+
+       filename = g_dir_read_name (dir);
+       if (!filename) {
+               return FALSE;
+       }
+
+       fullname = g_build_filename (GEOCLUE_PROVIDERS_DIR,
+                                    filename, NULL);
+       keyfile = g_key_file_new ();
+       ret = g_key_file_load_from_file (keyfile, fullname,
+                                        G_KEY_FILE_NONE, &error);
+       g_free (fullname);
+
+       if (!ret) {
+               g_warning ("Error loading %s: %s", filename, error->message);
+               g_error_free (error);
+       } else {
+               *name = g_key_file_get_value (keyfile, "Geoclue Provider",
+                                             "Name", NULL);
+
+               *service = g_key_file_get_value (keyfile, "Geoclue Provider",
+                                                "Service", NULL);
+               *path = g_key_file_get_value (keyfile, "Geoclue Provider",
+                                             "Path", NULL);
+               *ifaces = g_key_file_get_value (keyfile, "Geoclue Provider",
+                                             "Interfaces", NULL);
+       }
+
+       g_key_file_free (keyfile);
+       return TRUE;
+}
+
+static void
+position_callback (GeocluePosition *position,
+                   GeocluePositionFields fields,
+                   int timestamp,
+                   double lat, double lon, double alt,
+                   GeoclueAccuracy *accuracy,
+                   GError *error,
+                   gpointer userdata)
+{
+       if (error) {
+               g_warning ("Error getting position: %s\n", error->message);
+               g_error_free (error);
+               lat = lon = alt = 0.0/0.0;
+       }
+       update_position (GEOCLUE_TEST_GUI (userdata), position, lat, lon, alt);
+}
+
+static void
+add_to_position_store (GeoclueTestGui *gui, GeocluePosition *position, gboolean is_master)
+{
+       GtkTreeIter iter;
+
+       g_assert (gui->position_store);
+       g_assert (position);
+
+       if (is_master) {
+               /* master is already on the first line */
+               gtk_tree_model_get_iter_first (GTK_TREE_MODEL (gui->position_store), &iter);
+       } else {
+               gtk_list_store_append (gui->position_store, &iter);
+       }
+       gtk_list_store_set (gui->position_store, &iter,
+                           COL_POSITION_PROVIDER, position,
+                           COL_POSITION_IS_MASTER, is_master,
+                           -1);
+
+       g_signal_connect (G_OBJECT (position), "position-changed",
+                               G_CALLBACK (position_changed), gui);
+
+       geoclue_provider_get_provider_info_async (GEOCLUE_PROVIDER (position),
+                                                 info_callback,
+                                                 gui);
+       geoclue_position_get_position_async (position, position_callback, gui);
+}
+
+
+static GtkWidget *
+get_address_tree_view (GeoclueTestGui *gui)
+{
+       GtkTreeView *view;
+       GtkCellRenderer *renderer;
+
+       view = GTK_TREE_VIEW (gtk_tree_view_new ());
+
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_insert_column_with_attributes (view, -1,
+                                                    "Provider",
+                                                    renderer,
+                                                    "text",
+                                                    COL_ADDRESS_PROVIDER_NAME,
+                                                    NULL);
+
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_insert_column_with_attributes (view, -1,
+                                                    GEOCLUE_ADDRESS_KEY_COUNTRY,
+                                                    renderer,
+                                                    "text",
+                                                    COL_ADDRESS_COUNTRY,
+                                                    NULL);
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_insert_column_with_attributes (view, -1,
+                                                    GEOCLUE_ADDRESS_KEY_COUNTRYCODE,
+                                                    renderer,
+                                                    "text",
+                                                    COL_ADDRESS_COUNTRYCODE,
+                                                    NULL);
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_insert_column_with_attributes (view, -1,
+                                                    GEOCLUE_ADDRESS_KEY_REGION,
+                                                    renderer,
+                                                    "text",
+                                                    COL_ADDRESS_REGION,
+                                                    NULL);
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_insert_column_with_attributes (view, -1,
+                                                    GEOCLUE_ADDRESS_KEY_LOCALITY,
+                                                    renderer,
+                                                    "text",
+                                                    COL_ADDRESS_LOCALITY,
+                                                    NULL);
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_insert_column_with_attributes (view, -1,
+                                                    GEOCLUE_ADDRESS_KEY_AREA,
+                                                    renderer,
+                                                    "text",
+                                                    COL_ADDRESS_AREA,
+                                                    NULL);
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_insert_column_with_attributes (view, -1,
+                                                    GEOCLUE_ADDRESS_KEY_POSTALCODE,
+                                                    renderer,
+                                                    "text",
+                                                    COL_ADDRESS_POSTALCODE,
+                                                    NULL);
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_insert_column_with_attributes (view, -1,
+                                                    GEOCLUE_ADDRESS_KEY_STREET,
+                                                    renderer,
+                                                    "text",
+                                                    COL_ADDRESS_STREET,
+                                                    NULL);
+
+       gui->address_store = gtk_list_store_new (NUM_ADDRESS_COLS,
+                                   G_TYPE_POINTER,
+                                   G_TYPE_STRING,
+                                   G_TYPE_BOOLEAN,
+                                   G_TYPE_STRING,
+                                   G_TYPE_STRING,
+                                   G_TYPE_STRING,
+                                   G_TYPE_STRING,
+                                   G_TYPE_STRING,
+                                   G_TYPE_STRING,
+                                   G_TYPE_STRING);
+
+       gtk_tree_view_set_model (view, GTK_TREE_MODEL(gui->address_store));
+
+       return GTK_WIDGET (view);
+}
+
+
+static GtkWidget *
+get_position_tree_view (GeoclueTestGui *gui)
+{
+       GtkTreeView *view;
+       GtkCellRenderer *renderer;
+
+       view = GTK_TREE_VIEW (gtk_tree_view_new ());
+
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_insert_column_with_attributes (view, -1,
+                                                    "Provider",
+                                                    renderer,
+                                                    "text",
+                                                    COL_POSITION_PROVIDER_NAME,
+                                                    NULL);
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_insert_column_with_attributes (view, -1,
+                                                    "latitude",
+                                                    renderer,
+                                                    "text",
+                                                    COL_POSITION_LAT,
+                                                    NULL);
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_insert_column_with_attributes (view, -1,
+                                                    "longitude",
+                                                    renderer,
+                                                    "text",
+                                                    COL_POSITION_LON,
+                                                    NULL);
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_insert_column_with_attributes (view, -1,
+                                                    "altitude",
+                                                    renderer,
+                                                    "text",
+                                                    COL_POSITION_ALT,
+                                                    NULL);
+
+       gui->position_store = gtk_list_store_new (NUM_POSITION_COLS,
+                                   G_TYPE_POINTER,
+                                   G_TYPE_STRING,
+                                   G_TYPE_BOOLEAN,
+                                   G_TYPE_DOUBLE,
+                                   G_TYPE_DOUBLE,
+                                   G_TYPE_DOUBLE);
+
+       gtk_tree_view_set_model (view, GTK_TREE_MODEL(gui->position_store));
+
+       return GTK_WIDGET (view);
+}
+
+static void
+master_position_provider_changed (GeoclueMasterClient *client,
+                                  char *name,
+                                  char *description,
+                                  char *service,
+                                  char *path,
+                                  GeoclueTestGui *gui)
+{
+       GtkTreeIter iter;
+       char *msg;
+
+       if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (gui->position_store),
+                                          &iter)) {
+               gtk_list_store_set (gui->position_store, &iter,
+                                   COL_POSITION_PROVIDER_NAME, g_strdup_printf ("Master (%s)", name),
+                                   -1);
+       }
+       msg = g_strdup_printf ("Master: position provider changed: %s", name);
+       geoclue_test_gui_master_log_message (gui, msg);
+       g_free (msg);
+}
+
+static void
+master_address_provider_changed (GeoclueMasterClient *client,
+                                 char *name,
+                                 char *description,
+                                 char *service,
+                                 char *path,
+                                 GeoclueTestGui *gui)
+{
+       GtkTreeIter iter;
+       char *msg;
+
+       if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (gui->address_store),
+                                          &iter)) {
+               gtk_list_store_set (gui->address_store, &iter,
+                                   COL_ADDRESS_PROVIDER_NAME, g_strdup_printf ("Master (%s)", name),
+                                   -1);
+       }
+       msg = g_strdup_printf ("Master: address provider changed: %s", name);
+       geoclue_test_gui_master_log_message (gui, msg);
+       g_free (msg);
+}
+
+static void
+set_requirements_callback (GeoclueMasterClient *client,
+                           GError *error,
+                           gpointer userdata)
+{
+       if (error) {
+               g_printerr ("Setting requirements failed : %s", error->message);
+               g_error_free (error);
+       }
+}
+
+static void
+update_master_requirements (GeoclueTestGui *gui)
+{
+       geoclue_master_client_set_requirements_async (gui->client,
+                                                     gui->master_accuracy,
+                                                     0,
+                                                     FALSE,
+                                                     gui->master_resources,
+                                                     set_requirements_callback,
+                                                     NULL);
+}
+
+static void
+create_address_callback (GeoclueMasterClient *client,
+                         GeoclueAddress      *address,
+                         GError              *error,
+                         gpointer             userdata)
+{
+       GeoclueTestGui *gui = GEOCLUE_TEST_GUI (userdata);
+
+       if (error) {
+               g_printerr ("Master Client: Failed to create address: %s", error->message);
+               g_error_free (error);
+               return;
+       }
+       add_to_address_store (gui, address, TRUE);
+}
+
+static void
+create_position_callback (GeoclueMasterClient *client,
+                          GeocluePosition     *position,
+                          GError              *error,
+                          gpointer             userdata)
+{
+       GeoclueTestGui *gui = GEOCLUE_TEST_GUI (userdata);
+
+       if (error) {
+               g_printerr ("Master Client: Failed to create position: %s", error->message);
+               g_error_free (error);
+               return;
+       }
+       add_to_position_store (gui, position, TRUE);
+}
+
+
+static void
+create_client_callback (GeoclueMaster       *master,
+                       GeoclueMasterClient *client,
+                       char                *object_path,
+                       GError              *error,
+                       gpointer             userdata)
+{
+       GDir *dir;
+       char *name, *path, *service, *ifaces;
+       GtkTreeIter iter;
+       GeoclueTestGui *gui = GEOCLUE_TEST_GUI (userdata);
+
+       if (error) {
+               g_printerr ("Failed to create master client: %s", error->message);
+               g_error_free (error);
+               return;
+       }
+
+       gui->client = client;
+
+       g_signal_connect (G_OBJECT (gui->client), "position-provider-changed",
+                         G_CALLBACK (master_position_provider_changed), gui);
+       g_signal_connect (G_OBJECT (gui->client), "address-provider-changed",
+                         G_CALLBACK (master_address_provider_changed), gui);
+       update_master_requirements (gui);
+
+       /* add master providers to the lists */
+       gtk_list_store_append (gui->position_store, &iter);
+       geoclue_master_client_create_position_async (gui->client,
+                                                    create_position_callback,
+                                                    gui);
+       gtk_list_store_append (gui->address_store, &iter);
+       geoclue_master_client_create_address_async (gui->client,
+                                                   create_address_callback,
+                                                   gui);
+
+       /* add individual providers based on files in GEOCLUE_PROVIDERS_DIR  */
+       dir = g_dir_open (GEOCLUE_PROVIDERS_DIR, 0, &error);
+       if (!dir) {
+               g_warning ("Error opening %s: %s\n",
+                          GEOCLUE_PROVIDERS_DIR, error->message);
+               g_error_free (error);
+               return;
+       }
+
+       name = service = path = ifaces = NULL;
+       while (get_next_provider (dir, &name, &service, &path, &ifaces)) {
+               if (ifaces && strstr (ifaces, "org.freedesktop.Geoclue.Position")) {
+                       add_to_position_store (gui, geoclue_position_new (service, path), FALSE);
+               }
+               if (ifaces && strstr (ifaces, "org.freedesktop.Geoclue.Address")) {
+                       add_to_address_store (gui, geoclue_address_new (service, path), FALSE);
+               }
+               g_free (name);
+               g_free (path);
+               g_free (service);
+               g_free (ifaces);
+       }
+
+       g_dir_close (dir);
+       g_object_unref (master);
+}
+
+static void
+geoclue_test_gui_load_providers (GeoclueTestGui *gui)
+{
+       GeoclueMaster *master;
+
+       master = geoclue_master_get_default ();
+       geoclue_master_create_client_async (master,
+                                           create_client_callback,
+                                           gui);
+}
+
+static void
+accuracy_combo_changed (GtkComboBox *combo, GeoclueTestGui *gui)
+{
+       GtkTreeIter iter;
+
+       if (gtk_combo_box_get_active_iter (combo, &iter)) {
+               GtkTreeModel *model;
+
+               model = gtk_combo_box_get_model (combo);
+               gtk_tree_model_get (model, &iter, 0, &gui->master_accuracy, -1);
+
+               update_master_requirements (gui);
+       }
+}
+
+static void
+gps_check_toggled (GtkCheckButton *btn, GeoclueTestGui *gui)
+{
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (btn))) {
+               gui->master_resources |= GEOCLUE_RESOURCE_GPS;
+       } else {
+               gui->master_resources &= ~GEOCLUE_RESOURCE_GPS;
+       }
+       update_master_requirements (gui);
+}
+
+static void
+network_check_toggled (GtkCheckButton *btn, GeoclueTestGui *gui)
+{
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (btn))) {
+               gui->master_resources |= GEOCLUE_RESOURCE_NETWORK;
+       } else {
+               gui->master_resources &= ~GEOCLUE_RESOURCE_NETWORK;
+       }
+       update_master_requirements (gui);
+}
+
+static void
+cell_check_toggled (GtkCheckButton *btn, GeoclueTestGui *gui)
+{
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (btn))) {
+               gui->master_resources |= GEOCLUE_RESOURCE_CELL;
+       } else {
+               gui->master_resources &= ~GEOCLUE_RESOURCE_CELL;
+       }
+       update_master_requirements (gui);
+}
+
+static GtkWidget*
+get_accuracy_combo (GeoclueTestGui *gui)
+{
+       GtkListStore *store;
+       GtkWidget *combo;
+       GtkTreeIter iter;
+       GtkCellRenderer *renderer;
+
+       store = gtk_list_store_new (2, G_TYPE_UINT, G_TYPE_STRING);
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           0, GEOCLUE_ACCURACY_LEVEL_COUNTRY,
+                           1, "Country",
+                           -1);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           0, GEOCLUE_ACCURACY_LEVEL_REGION,
+                           1, "Region",
+                           -1);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           0, GEOCLUE_ACCURACY_LEVEL_LOCALITY,
+                           1, "Locality",
+                           -1);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           0, GEOCLUE_ACCURACY_LEVEL_POSTALCODE,
+                           1, "Postalcode",
+                           -1);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           0, GEOCLUE_ACCURACY_LEVEL_STREET,
+                           1, "Street",
+                           -1);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           0, GEOCLUE_ACCURACY_LEVEL_DETAILED,
+                           1, "Detailed",
+                           -1);
+
+       combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
+       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
+                                       "text", 1, NULL);
+
+       gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+       gui->master_accuracy = GEOCLUE_ACCURACY_LEVEL_COUNTRY;
+
+       return combo;
+}
+
+
+static void
+geoclue_test_gui_init (GeoclueTestGui *gui)
+{
+       GtkWidget *address_view;
+       GtkWidget *position_view;
+       GtkWidget *notebook;
+       GtkWidget *box;
+       GtkWidget *frame;
+       GtkWidget *hbox, *vbox;
+       GtkWidget *label;
+       GtkWidget *combo, *check;
+       GtkWidget *scrolled_win;
+       GtkWidget *view;
+
+       gui->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+       g_signal_connect (G_OBJECT (gui->window), "destroy",
+                         G_CALLBACK (gtk_main_quit), NULL);
+
+       view = gtk_text_view_new ();
+       gtk_widget_set_size_request (GTK_WIDGET (view), 500, 200);
+       g_object_set (G_OBJECT (view), "editable", FALSE, NULL);
+       gui->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+
+       box = gtk_vbox_new (FALSE, 8);
+       gtk_container_add (GTK_CONTAINER (gui->window), box);
+
+       frame = gtk_frame_new ("Master settings");
+       gtk_box_pack_start (GTK_BOX (box), frame, FALSE, FALSE, 4);
+
+
+       hbox = gtk_hbox_new (FALSE, 24);
+       gtk_container_add (GTK_CONTAINER (frame), hbox);
+
+       vbox = gtk_vbox_new (FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 8);
+       label = gtk_label_new ("Required accuracy level:");
+       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+       combo = get_accuracy_combo (gui);
+       g_signal_connect (combo, "changed",
+                         G_CALLBACK (accuracy_combo_changed), gui);
+       gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
+
+       vbox = gtk_vbox_new (FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
+       label = gtk_label_new ("Allow resources:");
+       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+       check = gtk_check_button_new_with_label ("Network");
+       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
+       gui->master_resources |= GEOCLUE_RESOURCE_NETWORK;
+       g_signal_connect (check, "toggled",
+                         G_CALLBACK (network_check_toggled), gui);
+       gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
+
+       check = gtk_check_button_new_with_label ("GPS");
+       g_signal_connect (check, "toggled",
+                         G_CALLBACK (gps_check_toggled), gui);
+       gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
+
+       check = gtk_check_button_new_with_label ("Cell");
+       g_signal_connect (check, "toggled",
+                         G_CALLBACK (cell_check_toggled), gui);
+       gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
+
+       notebook = gtk_notebook_new ();
+       gtk_box_pack_start (GTK_BOX (box), notebook, FALSE, FALSE, 0);
+       gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), TRUE);
+       gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), TRUE);
+
+       address_view = get_address_tree_view (gui);
+       label = gtk_label_new ("Address");
+       gtk_notebook_append_page (GTK_NOTEBOOK (notebook), address_view, label);
+
+       position_view = get_position_tree_view (gui);
+       label = gtk_label_new ("Position");
+       gtk_notebook_append_page (GTK_NOTEBOOK (notebook), position_view, label);
+
+
+       hbox = gtk_hbox_new (FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (box), hbox, FALSE, FALSE, 0);
+       label = gtk_label_new ("Master log");
+       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+                                       GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+       gtk_container_add (GTK_CONTAINER (box), scrolled_win);
+       gtk_container_add (GTK_CONTAINER (scrolled_win), view);
+
+       geoclue_test_gui_load_providers (gui);
+
+       geoclue_test_gui_master_log_message (gui, "Started Geoclue test UI");
+
+       gtk_widget_show_all (gui->window);
+}
+
+
+int main (int argc, char **argv)
+{
+       GeoclueTestGui *gui;
+
+       gtk_init (&argc, &argv);
+
+       gui = g_object_new (GEOCLUE_TYPE_TEST_GUI, NULL);
+       gtk_main ();
+
+       g_object_unref (gui);
+
+       return 0;
+}