19 #ifndef GSTREAMER_META_DATA_EXTRACTOR_H_ 20 #define GSTREAMER_META_DATA_EXTRACTOR_H_ 22 #include "../engine.h" 41 static const std::map<std::string, std::string> lut
43 {GST_TAG_ALBUM, std::string{xesam::Album::name}},
44 {GST_TAG_ALBUM_ARTIST, std::string{xesam::AlbumArtist::name}},
45 {GST_TAG_ARTIST, std::string{xesam::Artist::name}},
46 {GST_TAG_LYRICS, std::string{xesam::AsText::name}},
47 {GST_TAG_COMMENT, std::string{xesam::Comment::name}},
48 {GST_TAG_COMPOSER, std::string{xesam::Composer::name}},
49 {GST_TAG_DATE, std::string{xesam::ContentCreated::name}},
50 {GST_TAG_ALBUM_VOLUME_NUMBER, std::string{xesam::DiscNumber::name}},
51 {GST_TAG_GENRE, std::string{xesam::Genre::name}},
52 {GST_TAG_TITLE, std::string{xesam::Title::name}},
53 {GST_TAG_TRACK_NUMBER, std::string{xesam::TrackNumber::name}},
54 {GST_TAG_USER_RATING, std::string{xesam::UserRating::name}},
57 {GST_TAG_IMAGE, std::string{tags::Image::name}},
58 {GST_TAG_PREVIEW_IMAGE, std::string{tags::PreviewImage::name}}
72 [](
const GstTagList *list,
78 auto md = static_cast<media::Track::MetaData*>(user_data);
81 switch (gst_tag_get_type(tag))
86 if (gst_tag_list_get_boolean(list, tag, &value))
93 if (gst_tag_list_get_int(list, tag, &value))
100 if (gst_tag_list_get_uint(list, tag, &value))
107 if (gst_tag_list_get_int64(list, tag, &value))
114 if (gst_tag_list_get_uint64(list, tag, &value))
121 if (gst_tag_list_get_float(list, tag, &value))
128 if (gst_tag_list_get_double(list, tag, &value))
135 if (gst_tag_list_get_string(list, tag, &value))
147 const std::string tag_name{(has_tag_from_lut) ?
152 if (tag_name == tags::PreviewImage::name)
154 if (tag_name == tags::Image::name)
157 (*md).set((has_tag_from_lut ?
164 : pipe(gst_pipeline_new(
"meta_data_extractor_pipeline")),
165 decoder(gst_element_factory_make (
"uridecodebin", NULL)),
166 bus(gst_element_get_bus(pipe))
168 gst_bin_add(GST_BIN(pipe), decoder);
170 auto sink = gst_element_factory_make (
"fakesink", NULL);
171 gst_bin_add (GST_BIN (pipe), sink);
173 g_signal_connect (decoder,
"pad-added", G_CALLBACK (on_new_pad), sink);
179 gst_object_unref(pipe);
184 static const std::chrono::nanoseconds state_change_timeout
189 std::chrono::milliseconds{5000}
192 auto ret = gst_element_set_state(pipe, new_state);
194 bool result =
false; GstState current, pending;
197 case GST_STATE_CHANGE_FAILURE:
198 result =
false;
break;
199 case GST_STATE_CHANGE_NO_PREROLL:
200 case GST_STATE_CHANGE_SUCCESS:
201 result =
true;
break;
202 case GST_STATE_CHANGE_ASYNC:
203 result = GST_STATE_CHANGE_SUCCESS == gst_element_get_state(
207 state_change_timeout.count());
216 if (!gst_uri_is_valid(uri.c_str()))
217 throw std::runtime_error(
"Invalid uri");
220 std::promise<core::ubuntu::media::Track::MetaData> promise;
221 std::future<core::ubuntu::media::Track::MetaData> future{promise.get_future()};
223 core::ScopedConnection on_new_message_connection
229 if (msg.
type == GST_MESSAGE_TAG)
231 MetaDataExtractor::on_tag_available(msg.detail.tag, meta_data);
232 }
else if (msg.
type == GST_MESSAGE_ASYNC_DONE)
234 promise.set_value(meta_data);
239 g_object_set(decoder,
"uri", uri.c_str(), NULL);
240 gst_element_set_state(pipe, GST_STATE_PAUSED);
242 if (std::future_status::ready != future.wait_for(std::chrono::seconds(4)))
245 throw std::runtime_error(
"Problem extracting meta data for track");
255 static void on_new_pad(GstElement*, GstPad* pad, GstElement* fakesink)
259 sinkpad = gst_element_get_static_pad (fakesink,
"sink");
261 if (!gst_pad_is_linked (sinkpad)) {
262 if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)
263 g_error (
"Failed to link pads!");
266 gst_object_unref (sinkpad);
275 #endif // GSTREAMER_META_DATA_EXTRACTOR_H_
core::Signal< Message > on_new_message