<commit_before>/*
 * Copyright (C) 2006, <NAME> <<EMAIL>>
 * Copyright (C) 2007, <NAME> <<EMAIL>>
 * Copyright (C) 2008, Nokia <<EMAIL>>
 *
 * 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"

/* Ensure we have a valid backend enabled */
#if !defined(GSTREAMER_BACKEND_TAGREADBIN) && \
    !defined(GSTREAMER_BACKEND_DECODEBIN2) && \
    !defined(GSTREAMER_BACKEND_DISCOVERER) && \
    !defined(GSTREAMER_BACKEND_GUPNP_DLNA)
#error Not a valid GStreamer backend defined
#endif

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <glib.h>
#include <glib/gstdio.h>

#if defined(GSTREAMER_BACKEND_DISCOVERER) || \
    defined(GSTREAMER_BACKEND_GUPNP_DLNA)
#define GST_USE_UNSTABLE_API
#include <gst/pbutils/pbutils.h>
#endif

#if defined(GSTREAMER_BACKEND_GUPNP_DLNA)
#include <libgupnp-dlna/gupnp-dlna-discoverer.h>
#endif

#include <gst/gst.h>
#include <gst/tag/tag.h>

#include <libtracker-common/tracker-common.h>
#include <libtracker-extract/tracker-extract.h>

#include "tracker-albumart.h"
#include "tracker-cue-sheet.h"

/* We wait this long (seconds) for NULL state before freeing */
#define TRACKER_EXTRACT_GUARD_TIMEOUT 3

/* An additional tag in gstreamer for the content source. Remove when in upstream */
#ifndef GST_TAG_CLASSIFICATION
#define GST_TAG_CLASSIFICATION "classification"
#endif

/* Some additional tagreadbin tags (FIXME until they are defined upstream)*/
#ifndef GST_TAG_CHANNEL
#define GST_TAG_CHANNEL "channels"
#endif

#ifndef GST_TAG_RATE
#define GST_TAG_RATE "rate"
#endif

#ifndef GST_TAG_WIDTH
#define GST_TAG_WIDTH "width"
#endif

#ifndef GST_TAG_HEIGHT
#define GST_TAG_HEIGHT "height"
#endif

#ifndef GST_TAG_PIXEL_RATIO
#define GST_TAG_PIXEL_RATIO "pixel-aspect-ratio"
#endif

#ifndef GST_TAG_FRAMERATE
#define GST_TAG_FRAMERATE "framerate"
#endif

typedef enum {
	EXTRACT_MIME_AUDIO,
	EXTRACT_MIME_VIDEO,
	EXTRACT_MIME_IMAGE,
	EXTRACT_MIME_GUESS,
	EXTRACT_MIME_SVG,
} ExtractMime;

typedef struct {
	ExtractMime     mime;
	GstTagList     *tagcache;
	TrackerToc     *toc;
	gboolean        is_content_encrypted;

	GSList         *artist_list;

	unsigned char  *album_art_data;
	guint           album_art_size;
	const gchar    *album_art_mime;

#if defined(GSTREAMER_BACKEND_TAGREADBIN) || \
    defined(GSTREAMER_BACKEND_DECODEBIN2)
	GstElement     *pipeline;
	GstBus         *bus;
#endif

#if defined(GSTREAMER_BACKEND_DECODEBIN2)
	GstElement     *bin;
	GList          *fsinks;
#endif

#if defined(GSTREAMER_BACKEND_DISCOVERER) || \
    defined(GSTREAMER_BACKEND_GUPNP_DLNA)
	gboolean        has_image;
	gboolean        has_audio;
	gboolean        has_video;
	GList          *streams;
#endif

#if defined(GSTREAMER_BACKEND_DISCOVERER)
	GstDiscoverer  *discoverer;
#endif

#if defined(GSTREAMER_BACKEND_GUPNP_DLNA)
	GUPnPDLNADiscoverer  *discoverer;
	GUPnPDLNAInformation *dlna_info;
	const gchar          *dlna_profile;
	const gchar          *dlna_mime;
#endif

#if defined(GSTREAMER_BACKEND_DISCOVERER) || \
    defined(GSTREAMER_BACKEND_DECODEBIN2) || \
    defined(GSTREAMER_BACKEND_GUPNP_DLNA)
	gint64          duration;
	gint            audio_channels;
	gint            audio_samplerate;
	gint            height;
	gint            width;
	gfloat          aspect_ratio;
	gfloat          video_fps;
#endif
} MetadataExtractor;

#if defined(GSTREAMER_BACKEND_TAGREADBIN)
static void tagreadbin_extract_stream_metadata (MetadataExtractor    *extractor,
                                                const gchar          *uri,
                                                TrackerSparqlBuilder *metadata);
#else  /* DECODEBIN2/DISCOVERER/GUPnP-DLNA */
static void common_extract_stream_metadata (MetadataExtractor    *extractor,
                                            const gchar          *uri,
                                            TrackerSparqlBuilder *metadata);
#endif /* DECODEBIN2/DISCOVERER/GUPnP-DLNA */

static void
add_artist (MetadataExtractor     *extractor,
            TrackerSparqlBuilder  *preupdate,
            const gchar           *graph,
            const gchar           *artist_name,
            gchar                **p_artist_uri)
{
	g_return_if_fail (artist_name != NULL);

	*p_artist_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", artist_name);

	/* Check if already added to the preupdate, to avoid sending 9 identical INSERTs */
	if (g_slist_find_custom (extractor->artist_list, artist_name, (GCompareFunc) g_ascii_strcasecmp))
		return;

	tracker_sparql_builder_insert_open (preupdate, NULL);
	if (graph) {
		tracker_sparql_builder_graph_open (preupdate, graph);
	}

	tracker_sparql_builder_subject_iri (preupdate, *p_artist_uri);
	tracker_sparql_builder_predicate (preupdate, "a");
	tracker_sparql_builder_object (preupdate, "nmm:Artist");
	tracker_sparql_builder_predicate (preupdate, "nmm:artistName");
	tracker_sparql_builder_object_unvalidated (preupdate, artist_name);

	if (graph) {
		tracker_sparql_builder_graph_close (preupdate);
	}
	tracker_sparql_builder_insert_close (preupdate);

	extractor->artist_list = g_slist_prepend (extractor->artist_list, g_strdup (artist_name));
}

static void
add_string_gst_tag (TrackerSparqlBuilder *metadata,
                    const gchar          *key,
                    GstTagList           *tag_list,<commit_msg>tracker-extract-gstreamer: Use strcmp() not g_ascii_strcasecmp() for artists<commit_after>/*
 * Copyright (C) 2006, <NAME> <<EMAIL>>
 * Copyright (C) 2007, <NAME> <<EMAIL>>
 * Copyright (C) 2008, Nokia <<EMAIL>.<EMAIL>>
 *
 * 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"

/* Ensure we have a valid backend enabled */
#if !defined(GSTREAMER_BACKEND_TAGREADBIN) && \
    !defined(GSTREAMER_BACKEND_DECODEBIN2) && \
    !defined(GSTREAMER_BACKEND_DISCOVERER) && \
    !defined(GSTREAMER_BACKEND_GUPNP_DLNA)
#error Not a valid GStreamer backend defined
#endif

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <glib.h>
#include <glib/gstdio.h>

#if defined(GSTREAMER_BACKEND_DISCOVERER) || \
    defined(GSTREAMER_BACKEND_GUPNP_DLNA)
#define GST_USE_UNSTABLE_API
#include <gst/pbutils/pbutils.h>
#endif

#if defined(GSTREAMER_BACKEND_GUPNP_DLNA)
#include <libgupnp-dlna/gupnp-dlna-discoverer.h>
#endif

#include <gst/gst.h>
#include <gst/tag/tag.h>

#include <libtracker-common/tracker-common.h>
#include <libtracker-extract/tracker-extract.h>

#include "tracker-albumart.h"
#include "tracker-cue-sheet.h"

/* We wait this long (seconds) for NULL state before freeing */
#define TRACKER_EXTRACT_GUARD_TIMEOUT 3

/* An additional tag in gstreamer for the content source. Remove when in upstream */
#ifndef GST_TAG_CLASSIFICATION
#define GST_TAG_CLASSIFICATION "classification"
#endif

/* Some additional tagreadbin tags (FIXME until they are defined upstream)*/
#ifndef GST_TAG_CHANNEL
#define GST_TAG_CHANNEL "channels"
#endif

#ifndef GST_TAG_RATE
#define GST_TAG_RATE "rate"
#endif

#ifndef GST_TAG_WIDTH
#define GST_TAG_WIDTH "width"
#endif

#ifndef GST_TAG_HEIGHT
#define GST_TAG_HEIGHT "height"
#endif

#ifndef GST_TAG_PIXEL_RATIO
#define GST_TAG_PIXEL_RATIO "pixel-aspect-ratio"
#endif

#ifndef GST_TAG_FRAMERATE
#define GST_TAG_FRAMERATE "framerate"
#endif

typedef enum {
	EXTRACT_MIME_AUDIO,
	EXTRACT_MIME_VIDEO,
	EXTRACT_MIME_IMAGE,
	EXTRACT_MIME_GUESS,
	EXTRACT_MIME_SVG,
} ExtractMime;

typedef struct {
	ExtractMime     mime;
	GstTagList     *tagcache;
	TrackerToc     *toc;
	gboolean        is_content_encrypted;

	GSList         *artist_list;

	unsigned char  *album_art_data;
	guint           album_art_size;
	const gchar    *album_art_mime;

#if defined(GSTREAMER_BACKEND_TAGREADBIN) || \
    defined(GSTREAMER_BACKEND_DECODEBIN2)
	GstElement     *pipeline;
	GstBus         *bus;
#endif

#if defined(GSTREAMER_BACKEND_DECODEBIN2)
	GstElement     *bin;
	GList          *fsinks;
#endif

#if defined(GSTREAMER_BACKEND_DISCOVERER) || \
    defined(GSTREAMER_BACKEND_GUPNP_DLNA)
	gboolean        has_image;
	gboolean        has_audio;
	gboolean        has_video;
	GList          *streams;
#endif

#if defined(GSTREAMER_BACKEND_DISCOVERER)
	GstDiscoverer  *discoverer;
#endif

#if defined(GSTREAMER_BACKEND_GUPNP_DLNA)
	GUPnPDLNADiscoverer  *discoverer;
	GUPnPDLNAInformation *dlna_info;
	const gchar          *dlna_profile;
	const gchar          *dlna_mime;
#endif

#if defined(GSTREAMER_BACKEND_DISCOVERER) || \
    defined(GSTREAMER_BACKEND_DECODEBIN2) || \
    defined(GSTREAMER_BACKEND_GUPNP_DLNA)
	gint64          duration;
	gint            audio_channels;
	gint            audio_samplerate;
	gint            height;
	gint            width;
	gfloat          aspect_ratio;
	gfloat          video_fps;
#endif
} MetadataExtractor;

#if defined(GSTREAMER_BACKEND_TAGREADBIN)
static void tagreadbin_extract_stream_metadata (MetadataExtractor    *extractor,
                                                const gchar          *uri,
                                                TrackerSparqlBuilder *metadata);
#else  /* DECODEBIN2/DISCOVERER/GUPnP-DLNA */
static void common_extract_stream_metadata (MetadataExtractor    *extractor,
                                            const gchar          *uri,
                                            TrackerSparqlBuilder *metadata);
#endif /* DECODEBIN2/DISCOVERER/GUPnP-DLNA */

static void
add_artist (MetadataExtractor     *extractor,
            TrackerSparqlBuilder  *preupdate,
            const gchar           *graph,
            const gchar           *artist_name,
            gchar                **p_artist_uri)
{
	g_return_if_fail (artist_name != NULL);

	*p_artist_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", artist_name);

	/* Check if already added to the preupdate, to avoid sending 9 identical INSERTs */
	if (g_slist_find_custom (extractor->artist_list, artist_name, (GCompareFunc) strcmp))
		return;

	tracker_sparql_builder_insert_open (preupdate, NULL);
	if (graph) {
		tracker_sparql_builder_graph_open (preupdate, graph);
	}

	tracker_sparql_builder_subject_iri (preupdate, *p_artist_uri);
	tracker_sparql_builder_predicate (preupdate, "a");
	tracker_sparql_builder_object (preupdate, "nmm:Artist");
	tracker_sparql_builder_predicate (preupdate, "nmm:artistName");
	tracker_sparql_builder_object_unvalidated (preupdate, artist_name);

	if (graph) {
		tracker_sparql_builder_graph_close (preupdate);
	}
	tracker_sparql_builder_insert_close (preupdate);

	extractor->artist_list = g_slist_prepend (extractor->artist_list, g_strdup (artist_name));
}

static void
add_string_gst_tag (TrackerSparqlBuilder *metadata,
                    const gchar          *key,
                    GstTagList           *tag_list,
{'fraction_non_alphanumeric': 0.08317455057576009, 'fraction_numerical': 0.0057990224505012015, 'mean_word_length': 3.628834355828221, 'pattern_counts': {'":': 0, '<': 44, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6030773', 'n_tokens_mistral': 4263, 'n_tokens_neox': 4126, 'n_words': 953}