summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartyn Russell <curlybeast@gmail.com>2013-09-27 09:05:50 -0700
committerMartyn Russell <curlybeast@gmail.com>2013-09-27 09:05:50 -0700
commit1e7487261b22361b8785271b8e6e19947f211a76 (patch)
tree98b89f7dddb0800aa7c2296702c546022ea41846
parent3940d3560105ba17d81d45470ca711173af4ab74 (diff)
parent64e06dbeac3284b287a2b630bbe18c2494a11b37 (diff)
downloadlibmediaart-1e7487261b22361b8785271b8e6e19947f211a76.tar.gz
Merge pull request #4 from kyoushuu/tracker-storage
Add TrackerStorage and fix license file
-rw-r--r--COPYING (renamed from LICENSE)8
-rw-r--r--COPYING.LESSER502
-rw-r--r--Makefile.am3
-rw-r--r--configure.ac8
-rw-r--r--libmediaart/Makefile.am31
-rw-r--r--libmediaart/extract.c33
-rw-r--r--libmediaart/marshal.list2
-rw-r--r--libmediaart/tracker-storage.c1104
-rw-r--r--libmediaart/tracker-storage.h114
-rw-r--r--tests/Makefile.am2
10 files changed, 1776 insertions, 31 deletions
diff --git a/LICENSE b/COPYING
index 28b818a..d159169 100644
--- a/LICENSE
+++ b/COPYING
@@ -1,4 +1,4 @@
-GNU GENERAL PUBLIC LICENSE
+ GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
@@ -290,8 +290,8 @@ to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
- Library tasked with managing, extracting and handling media art caches
- Copyright (C) 2013 Martyn Russell
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
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
@@ -329,7 +329,7 @@ necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
- {signature of Ty Coon}, 1 April 1989
+ <signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
diff --git a/COPYING.LESSER b/COPYING.LESSER
new file mode 100644
index 0000000..4362b49
--- /dev/null
+++ b/COPYING.LESSER
@@ -0,0 +1,502 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ 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 Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+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 other code 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.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ 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, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser 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.
+
+ 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.
+
+ 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.
+
+ 6. As an exception to the Sections above, you may also combine 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) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) 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.
+
+ d) 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.
+
+ e) 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 materials to be 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.
+
+ 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 with
+this License.
+
+ 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 Lesser 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.
+
+ 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
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/Makefile.am b/Makefile.am
index 7692dd1..7a214c4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,5 +21,6 @@ CLEANFILES = \
DISTCHECK_CONFIGURE_FLAGS = \
--enable-unit-tests \
- --enable-introspection
+ --enable-introspection \
+ --enable-gtk-doc
diff --git a/configure.ac b/configure.ac
index 9015d84..8c9ce90 100644
--- a/configure.ac
+++ b/configure.ac
@@ -143,9 +143,15 @@ QT_REQUIRED=4.7.1
TRACKER_REQUIRED=0.16.0
# Check requirements for libmediaart
-LIBMEDIAART_REQUIRED="glib-2.0 >= $GLIB_REQUIRED tracker-sparql-0.16 >= $TRACKER_REQUIRED"
+LIBMEDIAART_REQUIRED="glib-2.0 >= $GLIB_REQUIRED
+ gio-2.0 >= $GLIB_REQUIRED
+ gio-unix-2.0 >= $GLIB_REQUIRED
+ tracker-sparql-0.16 >= $TRACKER_REQUIRED"
PKG_CHECK_MODULES(LIBMEDIAART, [$LIBMEDIAART_REQUIRED])
+GLIB_GENMARSHAL=`$PKG_CONFIG glib-2.0 --variable=glib_genmarshal`
+AC_SUBST(GLIB_GENMARSHAL)
+
LIBMEDIAART_LIBS="$LIBMEDIAART_LIBS -lz -lm"
####################################################################
diff --git a/libmediaart/Makefile.am b/libmediaart/Makefile.am
index 00c8d0e..42c155f 100644
--- a/libmediaart/Makefile.am
+++ b/libmediaart/Makefile.am
@@ -25,7 +25,12 @@ libmediaartinclude_HEADERS = \
extract.h \
extractgeneric.h
-libmediaart_@LIBMEDIAART_API_VERSION@_la_SOURCES = $(libmediaart_sources)
+libmediaart_@LIBMEDIAART_API_VERSION@_la_SOURCES = \
+ $(libmediaart_sources) \
+ marshal.c \
+ marshal.h \
+ tracker-storage.c \
+ tracker-storage.h
if HAVE_GDKPIXBUF
libmediaart_@LIBMEDIAART_API_VERSION@_la_SOURCES += extractpixbuf.c
@@ -46,6 +51,24 @@ libmediaart_@LIBMEDIAART_API_VERSION@_la_LIBADD = \
$(LIBMEDIAART_LIBS)
+marshal.h: marshal.list
+ $(AM_V_GEN)$(GLIB_GENMARSHAL) $< --prefix=media_art_marshal --header > $@
+
+marshal.c: marshal.list
+ $(AM_V_GEN)(echo "#include \"marshal.h\""; \
+ $(GLIB_GENMARSHAL) $< --prefix=media_art_marshal --body) > $@
+
+
+BUILT_SOURCES = \
+ marshal.c \
+ marshal.h
+
+CLEANFILES = $(BUILT_SOURCES)
+
+EXTRA_DIST = \
+ marshal.list
+
+
-include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS =
INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) --symbol-prefix=media_art
@@ -54,7 +77,7 @@ INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
if HAVE_INTROSPECTION
introspection_sources = $(libmediaart_sources) extractdummy.c
-MediaArt-@LIBMEDIAART_API_VERSION_U@.gir: libmediaart-@LIBMEDIAART_API_VERSION@.la
+MediaArt-@LIBMEDIAART_API_VERSION@.gir: libmediaart-@LIBMEDIAART_API_VERSION@.la
MediaArt_@LIBMEDIAART_API_VERSION_U@_gir_INCLUDES = GObject-2.0
MediaArt_@LIBMEDIAART_API_VERSION_U@_gir_CFLAGS = $(INCLUDES) -DLIBMEDIAART_COMPILATION
MediaArt_@LIBMEDIAART_API_VERSION_U@_gir_LIBS = libmediaart-@LIBMEDIAART_API_VERSION@.la
@@ -68,7 +91,7 @@ gir_DATA = $(INTROSPECTION_GIRS)
typelibdir = $(libdir)/girepository-1.0
typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
-CLEANFILES = $(gir_DATA) $(typelib_DATA)
+BUILT_SOURCES += $(gir_DATA) $(typelib_DATA)
endif
if ENABLE_VAPIGEN
@@ -83,4 +106,6 @@ libmediaart_@LIBMEDIAART_API_VERSION_U@_vapi_FILES = MediaArt-@LIBMEDIAART_API_V
vapidir = $(datadir)/vala/vapi
vapi_DATA = $(VAPIGEN_VAPIS)
+
+BUILT_SOURCES += $(vapi_DATA)
endif
diff --git a/libmediaart/extract.c b/libmediaart/extract.c
index 8afc3f7..358c8d9 100644
--- a/libmediaart/extract.c
+++ b/libmediaart/extract.c
@@ -25,6 +25,8 @@
#include <gio/gio.h>
+#include "tracker-storage.h"
+
#include "extract.h"
#include "cache.h"
@@ -69,6 +71,7 @@ static gboolean disable_requests;
static GHashTable *media_art_cache;
static GDBusConnection *connection;
+static TrackerStorage *storage;
static void media_art_queue_cb (GObject *source_object,
GAsyncResult *res,
@@ -825,12 +828,9 @@ media_art_request_download (MediaArtType type,
}
}
-#if 0
-
static void
-media_art_copy_to_local (TrackerStorage *storage,
- const gchar *filename,
- const gchar *local_uri)
+media_art_copy_to_local (const gchar *filename,
+ const gchar *local_uri)
{
GSList *roots, *l;
gboolean on_removable_device = FALSE;
@@ -897,18 +897,6 @@ media_art_copy_to_local (TrackerStorage *storage,
}
}
-#else
-#warning "FIXME: WE don't have TrackerStorage, media_art_copy_to_local() does nothing."
-
-static void
-media_art_copy_to_local (const gchar *filename,
- const gchar *local_uri)
-{
- g_warning ("FIXME: WE don't have TrackerStorage, media_art_copy_to_local() does nothing.");
-}
-
-#endif
-
static void
media_art_queue_cb (GObject *source_object,
GAsyncResult *res,
@@ -935,10 +923,7 @@ media_art_queue_cb (GObject *source_object,
g_variant_unref (v);
}
- /* FIXME: was TrackerStorage ...*/
-#warning "FIXME: check for non-existant TrackerStorage"
-
- if (NULL &&
+ if (storage &&
fi->art_path &&
g_file_test (fi->art_path, G_FILE_TEST_EXISTS)) {
media_art_copy_to_local (fi->art_path,
@@ -973,6 +958,8 @@ media_art_init (void)
return FALSE;
}
+ storage = tracker_storage_new ();
+
initialized = TRUE;
return TRUE;
@@ -983,6 +970,10 @@ media_art_shutdown (void)
{
g_return_if_fail (initialized == TRUE);
+ if (storage) {
+ g_object_unref (storage);
+ }
+
if (connection) {
g_object_unref (connection);
}
diff --git a/libmediaart/marshal.list b/libmediaart/marshal.list
new file mode 100644
index 0000000..f7cef75
--- /dev/null
+++ b/libmediaart/marshal.list
@@ -0,0 +1,2 @@
+VOID:STRING,STRING
+VOID:STRING,STRING,STRING,BOOLEAN,BOOLEAN
diff --git a/libmediaart/tracker-storage.c b/libmediaart/tracker-storage.c
new file mode 100644
index 0000000..e13be7d
--- /dev/null
+++ b/libmediaart/tracker-storage.c
@@ -0,0 +1,1104 @@
+/*
+ * Copyright (C) 2008, Nokia <ivan.frade@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gio/gio.h>
+#include <gio/gunixmounts.h>
+
+#include "tracker-storage.h"
+#include "marshal.h"
+
+/**
+ * SECTION:tracker-storage
+ * @short_description: Removable storage and mount point convenience API
+ * @include: libtracker-miner/tracker-miner.h
+ *
+ * This API is a convenience to to be able to keep track of volumes
+ * which are mounted and also the type of removable media available.
+ * The API is built upon the top of GIO's #GMount, #GDrive and #GVolume API.
+ **/
+
+#define TRACKER_STORAGE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_STORAGE, TrackerStoragePrivate))
+
+typedef struct {
+ GVolumeMonitor *volume_monitor;
+
+ GNode *mounts;
+ GHashTable *mounts_by_uuid;
+ GHashTable *unmount_watchdogs;
+} TrackerStoragePrivate;
+
+typedef struct {
+ gchar *mount_point;
+ gchar *uuid;
+ guint unmount_timer_id;
+ guint removable : 1;
+ guint optical : 1;
+} MountInfo;
+
+typedef struct {
+ const gchar *path;
+ GNode *node;
+} TraverseData;
+
+typedef struct {
+ GSList *roots;
+ TrackerStorageType type;
+ gboolean exact_match;
+} GetRoots;
+
+typedef struct {
+ TrackerStorage *storage;
+ GMount *mount;
+} UnmountCheckData;
+
+static void tracker_storage_finalize (GObject *object);
+static gboolean mount_info_free (GNode *node,
+ gpointer user_data);
+static void mount_node_free (GNode *node);
+static gboolean mounts_setup (TrackerStorage *storage);
+static void mount_added_cb (GVolumeMonitor *monitor,
+ GMount *mount,
+ gpointer user_data);
+static void mount_removed_cb (GVolumeMonitor *monitor,
+ GMount *mount,
+ gpointer user_data);
+static void mount_pre_removed_cb (GVolumeMonitor *monitor,
+ GMount *mount,
+ gpointer user_data);
+
+enum {
+ MOUNT_POINT_ADDED,
+ MOUNT_POINT_REMOVED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+G_DEFINE_TYPE (TrackerStorage, tracker_storage, G_TYPE_OBJECT);
+
+static void
+tracker_storage_class_init (TrackerStorageClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = tracker_storage_finalize;
+
+ signals[MOUNT_POINT_ADDED] =
+ g_signal_new ("mount-point-added",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ media_art_marshal_VOID__STRING_STRING_STRING_BOOLEAN_BOOLEAN,
+ G_TYPE_NONE,
+ 5,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN);
+
+ signals[MOUNT_POINT_REMOVED] =
+ g_signal_new ("mount-point-removed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ media_art_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+
+ g_type_class_add_private (object_class, sizeof (TrackerStoragePrivate));
+}
+
+static void
+tracker_storage_init (TrackerStorage *storage)
+{
+ TrackerStoragePrivate *priv;
+
+ g_message ("Initializing Storage...");
+
+ priv = TRACKER_STORAGE_GET_PRIVATE (storage);
+
+ priv->mounts = g_node_new (NULL);
+
+ priv->mounts_by_uuid = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify) g_free,
+ NULL);
+ priv->unmount_watchdogs = g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify) g_source_remove);
+
+ priv->volume_monitor = g_volume_monitor_get ();
+
+ /* Volume and property notification callbacks */
+ g_signal_connect_object (priv->volume_monitor, "mount-removed",
+ G_CALLBACK (mount_removed_cb), storage, 0);
+ g_signal_connect_object (priv->volume_monitor, "mount-pre-unmount",
+ G_CALLBACK (mount_pre_removed_cb), storage, 0);
+ g_signal_connect_object (priv->volume_monitor, "mount-added",
+ G_CALLBACK (mount_added_cb), storage, 0);
+
+ g_message ("Mount monitors set up for to watch for added, removed and pre-unmounts...");
+
+ /* Get all mounts and set them up */
+ if (!mounts_setup (storage)) {
+ return;
+ }
+}
+
+static void
+tracker_storage_finalize (GObject *object)
+{
+ TrackerStoragePrivate *priv;
+
+ priv = TRACKER_STORAGE_GET_PRIVATE (object);
+
+ g_hash_table_destroy (priv->unmount_watchdogs);
+
+ if (priv->mounts_by_uuid) {
+ g_hash_table_unref (priv->mounts_by_uuid);
+ }
+
+ if (priv->mounts) {
+ mount_node_free (priv->mounts);
+ }
+
+ if (priv->volume_monitor) {
+ g_object_unref (priv->volume_monitor);
+ }
+
+ (G_OBJECT_CLASS (tracker_storage_parent_class)->finalize) (object);
+}
+
+static void
+mount_node_free (GNode *node)
+{
+ g_node_traverse (node,
+ G_POST_ORDER,
+ G_TRAVERSE_ALL,
+ -1,
+ mount_info_free,
+ NULL);
+
+ g_node_destroy (node);
+}
+
+static gboolean
+mount_node_traverse_func (GNode *node,
+ gpointer user_data)
+{
+ TraverseData *data;
+ MountInfo *info;
+
+ if (!node->data) {
+ /* Root node */
+ return FALSE;
+ }
+
+ data = user_data;
+ info = node->data;
+
+ if (g_str_has_prefix (data->path, info->mount_point)) {
+ data->node = node;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static GNode *
+mount_node_find (GNode *root,
+ const gchar *path)
+{
+ TraverseData data = { path, NULL };
+
+ g_node_traverse (root,
+ G_POST_ORDER,
+ G_TRAVERSE_ALL,
+ -1,
+ mount_node_traverse_func,
+ &data);
+
+ return data.node;
+}
+
+static gboolean
+mount_info_free (GNode *node,
+ gpointer user_data)
+{
+ MountInfo *info;
+
+ info = node->data;
+
+ if (info) {
+ g_free (info->mount_point);
+ g_free (info->uuid);
+
+ g_slice_free (MountInfo, info);
+ }
+
+ return FALSE;
+}
+
+static MountInfo *
+mount_info_find (GNode *root,
+ const gchar *path)
+{
+ GNode *node;
+
+ node = mount_node_find (root, path);
+ return (node) ? node->data : NULL;
+}
+
+static TrackerStorageType
+mount_info_get_type (MountInfo *info)
+{
+ TrackerStorageType mount_type = 0;
+
+ if (info->removable) {
+ mount_type |= TRACKER_STORAGE_REMOVABLE;
+ }
+
+ if (info->optical) {
+ mount_type |= TRACKER_STORAGE_OPTICAL;
+ }
+
+ return mount_type;
+}
+
+static gchar *
+mount_point_normalize (const gchar *mount_point)
+{
+ gchar *mp;
+
+ /* Normalize all mount points to have a / at the end */
+ if (g_str_has_suffix (mount_point, G_DIR_SEPARATOR_S)) {
+ mp = g_strdup (mount_point);
+ } else {
+ mp = g_strconcat (mount_point, G_DIR_SEPARATOR_S, NULL);
+ }
+
+ return mp;
+}
+
+static GNode *
+mount_add_hierarchy (GNode *root,
+ const gchar *uuid,
+ const gchar *mount_point,
+ gboolean removable,
+ gboolean optical)
+{
+ MountInfo *info;
+ GNode *node;
+ gchar *mp;
+
+ mp = mount_point_normalize (mount_point);
+ node = mount_node_find (root, mp);
+
+ if (!node) {
+ node = root;
+ }
+
+ info = g_slice_new (MountInfo);
+ info->mount_point = mp;
+ info->uuid = g_strdup (uuid);
+ info->removable = removable;
+ info->optical = optical;
+
+ return g_node_append_data (node, info);
+}
+
+static void
+mount_add_new (TrackerStorage *storage,
+ const gchar *uuid,
+ const gchar *mount_point,
+ const gchar *mount_name,
+ gboolean removable_device,
+ gboolean optical_disc)
+{
+ TrackerStoragePrivate *priv;
+ GNode *node;
+
+ priv = TRACKER_STORAGE_GET_PRIVATE (storage);
+
+ node = mount_add_hierarchy (priv->mounts, uuid, mount_point, removable_device, optical_disc);
+ g_hash_table_insert (priv->mounts_by_uuid, g_strdup (uuid), node);
+
+ g_signal_emit (storage,
+ signals[MOUNT_POINT_ADDED],
+ 0,
+ uuid,
+ mount_point,
+ mount_name,
+ removable_device,
+ optical_disc,
+ NULL);
+}
+
+static gchar *
+mount_guess_content_type (GMount *mount,
+ gboolean *is_optical,
+ gboolean *is_multimedia,
+ gboolean *is_blank)
+{
+ gchar *content_type = NULL;
+ gchar **guess_type;
+
+ *is_optical = FALSE;
+ *is_multimedia = FALSE;
+ *is_blank = FALSE;
+
+ /* This function has 2 purposes:
+ *
+ * 1. Detect if we are using optical media
+ * 2. Detect if we are video or music, we can't index those types
+ *
+ * We try to determine the content type because we don't want
+ * to store Volume information in Tracker about DVDs and media
+ * which has no real data for us to mine.
+ *
+ * Generally, if is_multimedia is TRUE then we end up ignoring
+ * the media.
+ */
+ guess_type = g_mount_guess_content_type_sync (mount, TRUE, NULL, NULL);
+
+ if (guess_type) {
+ gint i = 0;
+
+ while (!content_type && guess_type[i]) {
+ if (!g_strcmp0 (guess_type[i], "x-content/image-picturecd")) {
+ /* Images */
+ content_type = g_strdup (guess_type[i]);
+ } else if (!g_strcmp0 (guess_type[i], "x-content/video-bluray") ||
+ !g_strcmp0 (guess_type[i], "x-content/video-dvd") ||
+ !g_strcmp0 (guess_type[i], "x-content/video-hddvd") ||
+ !g_strcmp0 (guess_type[i], "x-content/video-svcd") ||
+ !g_strcmp0 (guess_type[i], "x-content/video-vcd")) {
+ /* Videos */
+ *is_multimedia = TRUE;
+ content_type = g_strdup (guess_type[i]);
+ } else if (!g_strcmp0 (guess_type[i], "x-content/audio-cdda") ||
+ !g_strcmp0 (guess_type[i], "x-content/audio-dvd") ||
+ !g_strcmp0 (guess_type[i], "x-content/audio-player")) {
+ /* Audios */
+ *is_multimedia = TRUE;
+ content_type = g_strdup (guess_type[i]);
+ } else if (!g_strcmp0 (guess_type[i], "x-content/blank-bd") ||
+ !g_strcmp0 (guess_type[i], "x-content/blank-cd") ||
+ !g_strcmp0 (guess_type[i], "x-content/blank-dvd") ||
+ !g_strcmp0 (guess_type[i], "x-content/blank-hddvd")) {
+ /* Blank */
+ *is_blank = TRUE;
+ content_type = g_strdup (guess_type[i]);
+ } else if (!g_strcmp0 (guess_type[i], "x-content/software") ||
+ !g_strcmp0 (guess_type[i], "x-content/unix-software") ||
+ !g_strcmp0 (guess_type[i], "x-content/win32-software")) {
+ /* NOTE: This one is a guess, can we
+ * have this content type on
+ * none-optical mount points?
+ */
+ content_type = g_strdup (guess_type[i]);
+ } else {
+ /* else, keep on with the next guess, if any */
+ i++;
+ }
+ }
+
+ /* If we didn't have an exact match on possible guessed content types,
+ * then use the first one returned (best guess always first) if any */
+ if (!content_type && guess_type[0]) {
+ content_type = g_strdup (guess_type[0]);
+ }
+
+ g_strfreev (guess_type);
+ }
+
+ if (content_type) {
+ if (strstr (content_type, "vcd") ||
+ strstr (content_type, "cdda") ||
+ strstr (content_type, "dvd") ||
+ strstr (content_type, "bluray")) {
+ *is_optical = TRUE;
+ }
+ } else {
+ GUnixMountEntry *entry;
+ gchar *mount_path;
+ GFile *mount_root;
+
+ /* No content type was guessed, try to find out
+ * at least whether it's an optical media or not
+ */
+ mount_root = g_mount_get_root (mount);
+ mount_path = g_file_get_path (mount_root);
+
+ /* FIXME: Try to assume we have a unix mount :(
+ * EEK, once in a while, I have to write crack, oh well
+ */
+ if (mount_path &&
+ (entry = g_unix_mount_at (mount_path, NULL)) != NULL) {
+ const gchar *filesystem_type;
+ gchar *device_path = NULL;
+ GVolume *volume;
+
+ volume = g_mount_get_volume (mount);
+ filesystem_type = g_unix_mount_get_fs_type (entry);
+ g_debug (" Using filesystem type:'%s'",
+ filesystem_type);
+
+ /* Volume may be NULL */
+ if (volume) {
+ device_path = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
+ g_debug (" Using device path:'%s'",
+ device_path);
+ g_object_unref (volume);
+ }
+
+ /* NOTE: This code was taken from guess_mount_type()
+ * in GIO's gunixmounts.c and adapted purely for
+ * guessing optical media. We don't use the guessing
+ * code for other types such as MEMSTICKS, ZIPs,
+ * IPODs, etc.
+ *
+ * This code may need updating over time since it is
+ * very situational depending on how distributions
+ * mount their devices and how devices are named in
+ * /dev.
+ */
+ if (strcmp (filesystem_type, "udf") == 0 ||
+ strcmp (filesystem_type, "iso9660") == 0 ||
+ strcmp (filesystem_type, "cd9660") == 0 ||
+ (device_path &&
+ (g_str_has_prefix (device_path, "/dev/cdrom") ||
+ g_str_has_prefix (device_path, "/dev/acd") ||
+ g_str_has_prefix (device_path, "/dev/cd")))) {
+ *is_optical = TRUE;
+ } else if (device_path &&
+ g_str_has_prefix (device_path, "/vol/")) {
+ const gchar *name;
+
+ name = mount_path + strlen ("/");
+
+ if (g_str_has_prefix (name, "cdrom")) {
+ *is_optical = TRUE;
+ }
+ } else {
+ gchar *basename = g_path_get_basename (mount_path);
+
+ if (g_str_has_prefix (basename, "cdr") ||
+ g_str_has_prefix (basename, "cdwriter") ||
+ g_str_has_prefix (basename, "burn") ||
+ g_str_has_prefix (basename, "dvdr")) {
+ *is_optical = TRUE;
+ }
+
+ g_free (basename);
+ }
+
+ g_free (device_path);
+ g_free (mount_path);
+ g_unix_mount_free (entry);
+ } else {
+ g_debug (" No GUnixMountEntry found, needed for detecting if optical media... :(");
+ g_free (mount_path);
+ }
+
+ g_object_unref (mount_root);
+ }
+
+ return content_type;
+}
+
+static void
+mount_add (TrackerStorage *storage,
+ GMount *mount)
+{
+ TrackerStoragePrivate *priv;
+ GFile *root;
+ GVolume *volume;
+ gchar *mount_name, *mount_path, *uuid;
+ gboolean is_optical = FALSE;
+ gboolean is_removable = FALSE;
+
+ /* Get mount name */
+ mount_name = g_mount_get_name (mount);
+
+ /* Get root path of the mount */
+ root = g_mount_get_root (mount);
+ mount_path = g_file_get_path (root);
+
+ g_debug ("Found '%s' mounted on path '%s'",
+ mount_name,
+ mount_path);
+
+ /* Do not process shadowed mounts! */
+ if (g_mount_is_shadowed (mount)) {
+ g_debug (" Skipping shadowed mount '%s'", mount_name);
+ g_object_unref (root);
+ g_free (mount_path);
+ g_free (mount_name);
+ return;
+ }
+
+ priv = TRACKER_STORAGE_GET_PRIVATE (storage);
+
+ /* fstab partitions may not have corresponding
+ * GVolumes, so volume may be NULL */
+ volume = g_mount_get_volume (mount);
+ if (volume) {
+ /* GMount with GVolume */
+
+ /* Try to get UUID from the Volume.
+ * Note that g_volume_get_uuid() is NOT equivalent */
+ uuid = g_volume_get_identifier (volume,
+ G_VOLUME_IDENTIFIER_KIND_UUID);
+ if (!uuid) {
+ gchar *content_type;
+ gboolean is_multimedia;
+ gboolean is_blank;
+
+ /* Optical discs usually won't have UUID in the GVolume */
+ content_type = mount_guess_content_type (mount, &is_optical, &is_multimedia, &is_blank);
+ is_removable = TRUE;
+
+ /* We don't index content which is video, music or blank */
+ if (!is_multimedia && !is_blank) {
+ uuid = g_compute_checksum_for_string (G_CHECKSUM_MD5,
+ mount_name,
+ -1);
+ g_debug (" No UUID, generated:'%s' (based on mount name)", uuid);
+ g_debug (" Assuming GVolume has removable media, if wrong report a bug! "
+ "content type is '%s'",
+ content_type);
+ } else {
+ g_debug (" Being ignored because mount with volume is music/video/blank "
+ "(content type:%s, optical:%s, multimedia:%s, blank:%s)",
+ content_type,
+ is_optical ? "yes" : "no",
+ is_multimedia ? "yes" : "no",
+ is_blank ? "yes" : "no");
+ }
+
+ g_free (content_type);
+ } else {
+ /* Any other removable media will have UUID in the
+ * GVolume. Note that this also may include some
+ * partitions in the machine which have GVolumes
+ * associated to the GMounts. We also check a drive
+ * exists to be sure the device is local. */
+ GDrive *drive;
+
+ drive = g_volume_get_drive (volume);
+
+ if (drive) {
+ /* We can't mount/unmount system volumes, so tag
+ * them as non removable. */
+ is_removable = g_volume_can_mount (volume);
+ g_debug (" Found mount with volume and drive which %s be mounted: "
+ "Assuming it's %s removable, if wrong report a bug!",
+ is_removable ? "can" : "cannot",
+ is_removable ? "" : "not");
+ g_object_unref (drive);
+ } else {
+ /* Note: not sure when this can happen... */
+ g_debug (" Mount with volume but no drive, "
+ "assuming not a removable device, "
+ "if wrong report a bug!");
+ is_removable = FALSE;
+ }
+ }
+
+ g_object_unref (volume);
+ } else {
+ /* GMount without GVolume.
+ * Note: Never found a case where this g_mount_get_uuid() returns
+ * non-NULL... :-) */
+ uuid = g_mount_get_uuid (mount);
+ if (!uuid) {
+ if (mount_path) {
+ gchar *content_type;
+ gboolean is_multimedia;
+ gboolean is_blank;
+
+ content_type = mount_guess_content_type (mount, &is_optical, &is_multimedia, &is_blank);
+
+ /* Note: for GMounts without GVolume, is_blank should NOT be considered,
+ * as it may give unwanted results... */
+ if (!is_multimedia) {
+ uuid = g_compute_checksum_for_string (G_CHECKSUM_MD5,
+ mount_path,
+ -1);
+ g_debug (" No UUID, generated:'%s' (based on mount path)", uuid);
+ } else {
+ g_debug (" Being ignored because mount is music/video "
+ "(content type:%s, optical:%s, multimedia:%s)",
+ content_type,
+ is_optical ? "yes" : "no",
+ is_multimedia ? "yes" : "no");
+ }
+
+ g_free (content_type);
+ } else {
+ g_debug (" Being ignored because mount has no GVolume (i.e. not user mountable) "
+ "and has no mount root path available");
+ }
+ }
+ }
+
+ /* If we got something to be used as UUID, then add the mount
+ * to the TrackerStorage */
+ if (uuid && mount_path && !g_hash_table_lookup (priv->mounts_by_uuid, uuid)) {
+ g_debug (" Adding mount point with UUID: '%s', removable: %s, optical: %s, path: '%s'",
+ uuid,
+ is_removable ? "yes" : "no",
+ is_optical ? "yes" : "no",
+ mount_path);
+ mount_add_new (storage, uuid, mount_path, mount_name, is_removable, is_optical);
+ } else {
+ g_debug (" Skipping mount point with UUID: '%s', path: '%s', already managed: '%s'",
+ uuid ? uuid : "none",
+ mount_path ? mount_path : "none",
+ (uuid && g_hash_table_lookup (priv->mounts_by_uuid, uuid)) ? "yes" : "no");
+ }
+
+ g_free (mount_name);
+ g_free (mount_path);
+ g_free (uuid);
+ g_object_unref (root);
+}
+
+static gboolean
+mounts_setup (TrackerStorage *storage)
+{
+ TrackerStoragePrivate *priv;
+ GList *mounts, *lm;
+
+ priv = TRACKER_STORAGE_GET_PRIVATE (storage);
+
+ mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
+
+ if (!mounts) {
+ g_message ("No mounts found to iterate");
+ return TRUE;
+ }
+
+ /* Iterate over all available mounts and add them.
+ * Note that GVolumeMonitor shows only those mounts which are
+ * actually mounted. */
+ for (lm = mounts; lm; lm = g_list_next (lm)) {
+ mount_add (storage, lm->data);
+ g_object_unref (lm->data);
+ }
+
+ g_list_free (mounts);
+
+ return TRUE;
+}
+
+static void
+mount_added_cb (GVolumeMonitor *monitor,
+ GMount *mount,
+ gpointer user_data)
+{
+ mount_add (user_data, mount);
+}
+
+static void
+mount_remove (TrackerStorage *storage,
+ GMount *mount)
+{
+ TrackerStoragePrivate *priv;
+ MountInfo *info;
+ GNode *node;
+ GFile *file;
+ gchar *name;
+ gchar *mount_point;
+ gchar *mp;
+
+ priv = TRACKER_STORAGE_GET_PRIVATE (storage);
+
+ file = g_mount_get_root (mount);
+ mount_point = g_file_get_path (file);
+ name = g_mount_get_name (mount);
+
+ mp = mount_point_normalize (mount_point);
+ node = mount_node_find (priv->mounts, mp);
+ g_free (mp);
+
+ if (node) {
+ info = node->data;
+
+ g_message ("Mount:'%s' with UUID:'%s' now unmounted from:'%s'",
+ name,
+ info->uuid,
+ mount_point);
+
+ g_signal_emit (storage, signals[MOUNT_POINT_REMOVED], 0, info->uuid, mount_point, NULL);
+
+ g_hash_table_remove (priv->mounts_by_uuid, info->uuid);
+ mount_node_free (node);
+ } else {
+ g_message ("Mount:'%s' now unmounted from:'%s' (was not tracked)",
+ name,
+ mount_point);
+ }
+
+ g_free (name);
+ g_free (mount_point);
+ g_object_unref (file);
+}
+
+static void
+mount_removed_cb (GVolumeMonitor *monitor,
+ GMount *mount,
+ gpointer user_data)
+{
+ TrackerStorage *storage;
+ TrackerStoragePrivate *priv;
+
+ storage = user_data;
+ priv = TRACKER_STORAGE_GET_PRIVATE (storage);
+
+ mount_remove (storage, mount);
+
+ /* Unmount suceeded, remove the pending check */
+ g_hash_table_remove (priv->unmount_watchdogs, mount);
+}
+
+static gboolean
+unmount_failed_cb (gpointer user_data)
+{
+ UnmountCheckData *data = user_data;
+ TrackerStoragePrivate *priv;
+
+ /* If this timeout gets to be executed, this is due
+ * to a pre-unmount signal with no corresponding
+ * unmount in a timely fashion, we assume this is
+ * due to an error, and add back the still mounted
+ * path.
+ */
+ priv = TRACKER_STORAGE_GET_PRIVATE (data->storage);
+
+ g_warning ("Unmount operation failed, adding back mount point...");
+
+ mount_add (data->storage, data->mount);
+
+ g_hash_table_remove (priv->unmount_watchdogs, data->mount);
+ return FALSE;
+}
+
+static void
+mount_pre_removed_cb (GVolumeMonitor *monitor,
+ GMount *mount,
+ gpointer user_data)
+{
+ TrackerStorage *storage;
+ TrackerStoragePrivate *priv;
+ UnmountCheckData *data;
+ guint id;
+
+ storage = user_data;
+ priv = TRACKER_STORAGE_GET_PRIVATE (storage);
+
+ mount_remove (storage, mount);
+
+ /* Add check for failed unmounts */
+ data = g_new (UnmountCheckData, 1);
+ data->storage = storage;
+ data->mount = mount;
+
+ id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE + 10, 3,
+ unmount_failed_cb,
+ data, (GDestroyNotify) g_free);
+ g_hash_table_insert (priv->unmount_watchdogs, data->mount,
+ GUINT_TO_POINTER (id));
+}
+
+/**
+ * tracker_storage_new:
+ *
+ * Creates a new instance of #TrackerStorage.
+ *
+ * Returns: The newly created #TrackerStorage.
+ *
+ * Since: 0.8
+ **/
+TrackerStorage *
+tracker_storage_new (void)
+{
+ return g_object_new (TRACKER_TYPE_STORAGE, NULL);
+}
+
+static void
+get_mount_point_by_uuid_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GetRoots *gr;
+ GNode *node;
+ MountInfo *info;
+ TrackerStorageType mount_type;
+
+ gr = user_data;
+ node = value;
+ info = node->data;
+ mount_type = mount_info_get_type (info);
+
+ /* is mount of the type we're looking for? */
+ if ((gr->exact_match && mount_type == gr->type) ||
+ (!gr->exact_match && (mount_type & gr->type))) {
+ gchar *normalized_mount_point;
+ gint len;
+
+ normalized_mount_point = g_strdup (info->mount_point);
+ len = strlen (normalized_mount_point);
+
+ /* Don't include trailing slashes */
+ if (len > 2 && normalized_mount_point[len - 1] == G_DIR_SEPARATOR) {
+ normalized_mount_point[len - 1] = '\0';
+ }
+
+ gr->roots = g_slist_prepend (gr->roots, normalized_mount_point);
+ }
+}
+
+/**
+ * tracker_storage_get_device_roots:
+ * @storage: A #TrackerStorage
+ * @type: A #TrackerStorageType
+ * @exact_match: if all devices should exactly match the types
+ *
+ * Returns: (transfer full) (element-type utf8): a #GSList of strings
+ * containing the root directories for devices with @type based on
+ * @exact_match. Each element must be freed using g_free() and the
+ * list itself through g_slist_free().
+ *
+ * Since: 0.8
+ **/
+GSList *
+tracker_storage_get_device_roots (TrackerStorage *storage,
+ TrackerStorageType type,
+ gboolean exact_match)
+{
+ TrackerStoragePrivate *priv;
+ GetRoots gr;
+
+ g_return_val_if_fail (TRACKER_IS_STORAGE (storage), NULL);
+
+ priv = TRACKER_STORAGE_GET_PRIVATE (storage);
+
+ gr.roots = NULL;
+ gr.type = type;
+ gr.exact_match = exact_match;
+
+ g_hash_table_foreach (priv->mounts_by_uuid,
+ get_mount_point_by_uuid_foreach,
+ &gr);
+
+ return gr.roots;
+}
+
+/**
+ * tracker_storage_get_device_uuids:
+ * @storage: A #TrackerStorage
+ * @type: A #TrackerStorageType
+ * @exact_match: if all devices should exactly match the types
+ *
+ * Returns: (transfer full) (element-type utf8): a #GSList of
+ * strings containing the UUID for devices with @type based
+ * on @exact_match. Each element must be freed using g_free()
+ * and the list itself through g_slist_free().
+ *
+ * Since: 0.8
+ **/
+GSList *
+tracker_storage_get_device_uuids (TrackerStorage *storage,
+ TrackerStorageType type,
+ gboolean exact_match)
+{
+ TrackerStoragePrivate *priv;
+ GHashTableIter iter;
+ gpointer key, value;
+ GSList *uuids;
+
+ g_return_val_if_fail (TRACKER_IS_STORAGE (storage), NULL);
+
+ priv = TRACKER_STORAGE_GET_PRIVATE (storage);
+
+ uuids = NULL;
+
+ g_hash_table_iter_init (&iter, priv->mounts_by_uuid);
+
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ const gchar *uuid;
+ GNode *node;
+ MountInfo *info;
+ TrackerStorageType mount_type;
+
+ uuid = key;
+ node = value;
+ info = node->data;
+
+ mount_type = mount_info_get_type (info);
+
+ /* is mount of the type we're looking for? */
+ if ((exact_match && mount_type == type) ||
+ (!exact_match && (mount_type & type))) {
+ uuids = g_slist_prepend (uuids, g_strdup (uuid));
+ }
+ }
+
+ return uuids;
+}
+
+/**
+ * tracker_storage_get_mount_point_for_uuid:
+ * @storage: A #TrackerStorage
+ * @uuid: A string pointer to the UUID for the %GVolume.
+ *
+ * Returns: The mount point for @uuid, this should not be freed.
+ *
+ * Since: 0.8
+ **/
+const gchar *
+tracker_storage_get_mount_point_for_uuid (TrackerStorage *storage,
+ const gchar *uuid)
+{
+ TrackerStoragePrivate *priv;
+ GNode *node;
+ MountInfo *info;
+
+ g_return_val_if_fail (TRACKER_IS_STORAGE (storage), NULL);
+ g_return_val_if_fail (uuid != NULL, NULL);
+
+ priv = TRACKER_STORAGE_GET_PRIVATE (storage);
+
+ node = g_hash_table_lookup (priv->mounts_by_uuid, uuid);
+
+ if (!node) {
+ return NULL;
+ }
+
+ info = node->data;
+
+ return info->mount_point;
+}
+
+/**
+ * tracker_storage_get_type_for_uuid:
+ * @storage: A #TrackerStorage
+ * @uuid: A string pointer to the UUID for the %GVolume.
+ *
+ * Returns: The type flags for @uuid.
+ *
+ * Since: 0.10
+ **/
+TrackerStorageType
+tracker_storage_get_type_for_uuid (TrackerStorage *storage,
+ const gchar *uuid)
+{
+ TrackerStoragePrivate *priv;
+ GNode *node;
+ TrackerStorageType type = 0;
+
+ g_return_val_if_fail (TRACKER_IS_STORAGE (storage), 0);
+ g_return_val_if_fail (uuid != NULL, 0);
+
+ priv = TRACKER_STORAGE_GET_PRIVATE (storage);
+
+ node = g_hash_table_lookup (priv->mounts_by_uuid, uuid);
+
+ if (node) {
+ MountInfo *info;
+
+ info = node->data;
+
+ if (info->removable) {
+ type |= TRACKER_STORAGE_REMOVABLE;
+ }
+ if (info->optical) {
+ type |= TRACKER_STORAGE_OPTICAL;
+ }
+ }
+
+ return type;
+}
+
+/**
+ * tracker_storage_get_uuid_for_file:
+ * @storage: A #TrackerStorage
+ * @file: a file
+ *
+ * Returns the UUID of the removable device for @file
+ *
+ * Returns: Returns the UUID of the removable device for @file, this
+ * should not be freed.
+ *
+ * Since: 0.8
+ **/
+const gchar *
+tracker_storage_get_uuid_for_file (TrackerStorage *storage,
+ GFile *file)
+{
+ TrackerStoragePrivate *priv;
+ gchar *path;
+ MountInfo *info;
+
+ g_return_val_if_fail (TRACKER_IS_STORAGE (storage), FALSE);
+
+ path = g_file_get_path (file);
+
+ if (!path) {
+ return NULL;
+ }
+
+ /* Normalize all paths to have a / at the end */
+ if (!g_str_has_suffix (path, G_DIR_SEPARATOR_S)) {
+ gchar *norm_path;
+
+ norm_path = g_strconcat (path, G_DIR_SEPARATOR_S, NULL);
+ g_free (path);
+ path = norm_path;
+ }
+
+ priv = TRACKER_STORAGE_GET_PRIVATE (storage);
+
+ info = mount_info_find (priv->mounts, path);
+
+ if (!info) {
+ g_free (path);
+ return NULL;
+ }
+
+ /* g_debug ("Mount for path '%s' is '%s' (UUID:'%s')", */
+ /* path, info->mount_point, info->uuid); */
+
+ g_free (path);
+
+ return info->uuid;
+}
+
diff --git a/libmediaart/tracker-storage.h b/libmediaart/tracker-storage.h
new file mode 100644
index 0000000..2c28a5b
--- /dev/null
+++ b/libmediaart/tracker-storage.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2008, Nokia <ivan.frade@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __LIBTRACKER_MINER_STORAGE_H__
+#define __LIBTRACKER_MINER_STORAGE_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+/**
+ * TrackerStorageType:
+ * @TRACKER_STORAGE_REMOVABLE: Storage is a removable media
+ * @TRACKER_STORAGE_OPTICAL: Storage is an optical disc
+ *
+ * Flags specifying properties of the type of storage.
+ *
+ * Since: 0.8
+ */
+typedef enum {
+ TRACKER_STORAGE_REMOVABLE = 1 << 0,
+ TRACKER_STORAGE_OPTICAL = 1 << 1
+} TrackerStorageType;
+
+/**
+ * TRACKER_STORAGE_TYPE_IS_REMOVABLE:
+ * @type: Mask of TrackerStorageType flags
+ *
+ * Check if the given storage type is marked as being removable media.
+ *
+ * Returns: %TRUE if the storage is marked as removable media, %FALSE otherwise
+ *
+ * Since: 0.10
+ */
+#define TRACKER_STORAGE_TYPE_IS_REMOVABLE(type) ((type & TRACKER_STORAGE_REMOVABLE) ? TRUE : FALSE)
+
+/**
+ * TRACKER_STORAGE_TYPE_IS_OPTICAL:
+ * @type: Mask of TrackerStorageType flags
+ *
+ * Check if the given storage type is marked as being optical disc
+ *
+ * Returns: %TRUE if the storage is marked as optical disc, %FALSE otherwise
+ *
+ * Since: 0.10
+ */
+#define TRACKER_STORAGE_TYPE_IS_OPTICAL(type) ((type & TRACKER_STORAGE_OPTICAL) ? TRUE : FALSE)
+
+
+#define TRACKER_TYPE_STORAGE (tracker_storage_get_type ())
+#define TRACKER_STORAGE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_STORAGE, TrackerStorage))
+#define TRACKER_STORAGE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TRACKER_TYPE_STORAGE, TrackerStorageClass))
+#define TRACKER_IS_STORAGE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_STORAGE))
+#define TRACKER_IS_STORAGE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TRACKER_TYPE_STORAGE))
+#define TRACKER_STORAGE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_STORAGE, TrackerStorageClass))
+
+typedef struct _TrackerStorage TrackerStorage;
+typedef struct _TrackerStorageClass TrackerStorageClass;
+
+/**
+ * TrackerStorage:
+ * @parent: parent object
+ *
+ * A storage API for using mount points and devices
+ **/
+struct _TrackerStorage {
+ GObject parent;
+};
+
+/**
+ * TrackerStorageClass:
+ * @parent_class: parent object class
+ *
+ * A storage class for #TrackerStorage.
+ **/
+struct _TrackerStorageClass {
+ GObjectClass parent_class;
+};
+
+GType tracker_storage_get_type (void) G_GNUC_CONST;
+TrackerStorage * tracker_storage_new (void);
+GSList * tracker_storage_get_device_roots (TrackerStorage *storage,
+ TrackerStorageType type,
+ gboolean exact_match);
+GSList * tracker_storage_get_device_uuids (TrackerStorage *storage,
+ TrackerStorageType type,
+ gboolean exact_match);
+const gchar * tracker_storage_get_mount_point_for_uuid (TrackerStorage *storage,
+ const gchar *uuid);
+TrackerStorageType tracker_storage_get_type_for_uuid (TrackerStorage *storage,
+ const gchar *uuid);
+const gchar * tracker_storage_get_uuid_for_file (TrackerStorage *storage,
+ GFile *file);
+
+G_END_DECLS
+
+#endif /* __LIBTRACKER_MINER_STORAGE_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6d907fb..cb487dc 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -8,7 +8,7 @@ AM_CPPFLAGS = \
-DTOP_SRCDIR=\"$(abs_top_srcdir)\" \
-DTOP_BUILDDIR=\"$(abs_top_builddir)\" \
$(BUILD_CFLAGS) \
- -I$(top_srcdir)/libmediaart \
+ -I$(top_srcdir) \
$(LIBMEDIAART_CFLAGS)
LDADD = \