2
* Copyright (C) 2013-2014 Canonical, Ltd.
5
* Jussi Pakkanen <jussi.pakkanen@canonical.com>
6
* James Henstridge <james.henstridge@canonical.com>
8
* This library is free software; you can redistribute it and/or modify it under
9
* the terms of version 3 of the GNU General Public License as published
10
* by the Free Software Foundation.
12
* This library is distributed in the hope that it will be useful, but WITHOUT
13
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17
* You should have received a copy of the GNU General Public License
18
* along with this program. If not, see <http://www.gnu.org/licenses/>.
21
#include "GStreamerExtractor.hh"
22
#include "DetectedFile.hh"
23
#include "../mediascanner/MediaFile.hh"
24
#include "../mediascanner/MediaFileBuilder.hh"
25
#include "../mediascanner/internal/utils.hh"
27
#include <glib-object.h>
30
#include <gst/pbutils/pbutils.h>
37
using mediascanner::MediaFileBuilder;
41
void extract_tag_info (const GstTagList *list, const gchar *tag, void *user_data) {
42
MediaFileBuilder *mfb = (MediaFileBuilder *) user_data;
46
if(tagname == GST_TAG_IMAGE || tagname == GST_TAG_PREVIEW_IMAGE) {
47
mfb->setHasThumbnail(true);
50
num = gst_tag_list_get_tag_size (list, tag);
51
for (i = 0; i < num; ++i) {
54
val = gst_tag_list_get_value_index (list, tag, i);
55
if (G_VALUE_HOLDS_STRING(val)) {
56
const char *value = g_value_get_string(val);
60
if (tagname == GST_TAG_ARTIST)
61
mfb->setAuthor(value);
62
else if (tagname == GST_TAG_TITLE)
64
else if (tagname == GST_TAG_ALBUM)
66
else if (tagname == GST_TAG_ALBUM_ARTIST)
67
mfb->setAlbumArtist(value);
68
else if (tagname == GST_TAG_GENRE)
70
} else if (G_VALUE_HOLDS(val, GST_TYPE_DATE_TIME)) {
71
if (tagname == GST_TAG_DATE_TIME) {
72
GstDateTime *dt = static_cast<GstDateTime*>(g_value_get_boxed(val));
76
char *dt_string = gst_date_time_to_iso8601_string(dt);
77
mfb->setDate(dt_string);
80
} else if (G_VALUE_HOLDS(val, G_TYPE_DATE)) {
81
if (tagname == GST_TAG_DATE) {
82
GDate *dt = static_cast<GDate*>(g_value_get_boxed(val));
87
if (g_date_strftime(buf, sizeof(buf), "%Y-%m-%d", dt) != 0) {
91
} else if (G_VALUE_HOLDS_UINT(val)) {
92
if (tagname == GST_TAG_TRACK_NUMBER) {
93
mfb->setTrackNumber(g_value_get_uint(val));
94
} else if (tagname == GST_TAG_ALBUM_VOLUME_NUMBER) {
95
mfb->setDiscNumber(g_value_get_uint(val));
104
namespace mediascanner {
106
GStreamerExtractor::GStreamerExtractor(int seconds)
107
: discoverer(nullptr, g_object_unref) {
108
GError *error = nullptr;
110
discoverer.reset(gst_discoverer_new(GST_SECOND * seconds, &error));
111
if (not discoverer) {
112
string errortxt(error->message);
115
string msg = "Failed to create discoverer: ";
117
throw runtime_error(msg);
120
// Sometimes this is filled in even though no error happens.
125
GStreamerExtractor::~GStreamerExtractor() = default;
127
void GStreamerExtractor::extract(const DetectedFile &d, MediaFileBuilder &mfb) {
128
string uri = getUri(d.filename);
130
GError *error = nullptr;
131
unique_ptr<GstDiscovererInfo, void(*)(void *)> info(
132
gst_discoverer_discover_uri(discoverer.get(), uri.c_str(), &error),
134
if (info.get() == nullptr) {
135
string errortxt(error->message);
138
string msg = "Discovery of file ";
142
throw runtime_error(msg);
145
// Sometimes this gets filled in even if no error actually occurs.
150
if (gst_discoverer_info_get_result(info.get()) != GST_DISCOVERER_OK) {
151
throw runtime_error("Unable to discover file " + d.filename);
154
const GstTagList *tags = gst_discoverer_info_get_tags(info.get());
155
if (tags != nullptr) {
156
gst_tag_list_foreach(tags, extract_tag_info, &mfb);
158
mfb.setDuration(static_cast<int>(
159
gst_discoverer_info_get_duration(info.get())/GST_SECOND));
161
/* Check for video specific information */
162
unique_ptr<GList, void(*)(GList*)> streams(
163
gst_discoverer_info_get_stream_list(info.get()),
164
gst_discoverer_stream_info_list_free);
165
for (const GList *l = streams.get(); l != nullptr; l = l->next) {
166
auto stream_info = static_cast<GstDiscovererStreamInfo*>(l->data);
168
if (GST_IS_DISCOVERER_VIDEO_INFO(stream_info)) {
169
mfb.setWidth(gst_discoverer_video_info_get_width(
170
GST_DISCOVERER_VIDEO_INFO(stream_info)));
171
mfb.setHeight(gst_discoverer_video_info_get_height(
172
GST_DISCOVERER_VIDEO_INFO(stream_info)));