22 #ifndef GSTREAMER_META_DATA_EXTRACTOR_H
23 #define GSTREAMER_META_DATA_EXTRACTOR_H
25 #include "../engine.h"
42 static const std::map<std::string, std::string> lut
44 {GST_TAG_ALBUM, std::string{xesam::Album::name}},
45 {GST_TAG_ALBUM_ARTIST, std::string{xesam::AlbumArtist::name}},
46 {GST_TAG_ARTIST, std::string{xesam::Artist::name}},
47 {GST_TAG_LYRICS, std::string{xesam::AsText::name}},
48 {GST_TAG_COMMENT, std::string{xesam::Comment::name}},
49 {GST_TAG_COMPOSER, std::string{xesam::Composer::name}},
50 {GST_TAG_DATE, std::string{xesam::ContentCreated::name}},
51 {GST_TAG_ALBUM_VOLUME_NUMBER, std::string{xesam::DiscNumber::name}},
52 {GST_TAG_GENRE, std::string{xesam::Genre::name}},
53 {GST_TAG_TITLE, std::string{xesam::Title::name}},
54 {GST_TAG_TRACK_NUMBER, std::string{xesam::TrackNumber::name}},
55 {GST_TAG_USER_RATING, std::string{xesam::UserRating::name}},
58 {GST_TAG_IMAGE, std::string{tags::Image::name}},
59 {GST_TAG_PREVIEW_IMAGE, std::string{tags::PreviewImage::name}}
73 [](
const GstTagList *list,
79 auto md = static_cast<QVariantMap*>(user_data);
82 switch (gst_tag_get_type(tag))
87 if (gst_tag_list_get_boolean(list, tag, &value))
94 if (gst_tag_list_get_int(list, tag, &value))
101 if (gst_tag_list_get_uint(list, tag, &value))
108 if (gst_tag_list_get_int64(list, tag, &value))
109 v = QVariant(qint64(value));
115 if (gst_tag_list_get_uint64(list, tag, &value))
116 v = QVariant(quint64(value));
122 if (gst_tag_list_get_float(list, tag, &value))
129 if (gst_tag_list_get_double(list, tag, &value))
136 if (gst_tag_list_get_string(list, tag, &value))
138 v = QString::fromUtf8(value);
148 const std::string tag_name{(has_tag_from_lut) ?
153 if (tag_name == tags::PreviewImage::name)
155 if (tag_name == tags::Image::name)
159 md->insert(QString::fromStdString(tag_name), v);
166 : pipe(gst_pipeline_new(
"meta_data_extractor_pipeline")),
167 decoder(gst_element_factory_make (
"uridecodebin", NULL)),
168 bus(gst_element_get_bus(pipe)),
169 m_newMessageSubscriptionId(-1)
171 gst_bin_add(GST_BIN(pipe), decoder);
173 auto sink = gst_element_factory_make (
"fakesink", NULL);
174 gst_bin_add (GST_BIN (pipe), sink);
176 g_signal_connect (decoder,
"pad-added", G_CALLBACK (on_new_pad), sink);
181 if (m_newMessageSubscriptionId >= 0) {
182 bus.unsubscribeFromNewMessage(m_newMessageSubscriptionId);
184 set_state_and_wait(GST_STATE_NULL);
185 gst_object_unref(pipe);
190 static const std::chrono::nanoseconds state_change_timeout
195 std::chrono::milliseconds{5000}
198 auto ret = gst_element_set_state(pipe, new_state);
200 bool result =
false; GstState current, pending;
203 case GST_STATE_CHANGE_FAILURE:
204 result =
false;
break;
205 case GST_STATE_CHANGE_NO_PREROLL:
206 case GST_STATE_CHANGE_SUCCESS:
207 result =
true;
break;
208 case GST_STATE_CHANGE_ASYNC:
209 result = GST_STATE_CHANGE_SUCCESS == gst_element_get_state(
213 state_change_timeout.count());
223 if (!gst_uri_is_valid(qUtf8Printable(uri.toString())))
224 throw std::runtime_error(
"Invalid uri");
227 auto messageHandler = [
this, cb](
230 if (msg.type == GST_MESSAGE_TAG)
233 }
else if (msg.type == GST_MESSAGE_ASYNC_DONE)
235 set_state_and_wait(GST_STATE_NULL);
236 bus.unsubscribeFromNewMessage(m_newMessageSubscriptionId);
237 m_newMessageSubscriptionId = -1;
241 m_newMessageSubscriptionId = bus.onNewMessage(messageHandler);
243 g_object_set(decoder,
"uri", qUtf8Printable(uri.toString()), NULL);
244 gst_element_set_state(pipe, GST_STATE_PAUSED);
248 static void on_new_pad(GstElement*, GstPad* pad, GstElement* fakesink)
252 sinkpad = gst_element_get_static_pad (fakesink,
"sink");
254 if (!gst_pad_is_linked (sinkpad)) {
255 if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)
256 g_error (
"Failed to link pads!");
259 gst_object_unref (sinkpad);
265 QVariantMap m_metadata;
266 int m_newMessageSubscriptionId;
270 #endif // GSTREAMER_META_DATA_EXTRACTOR_H