mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-13 22:21:11 +02:00
Simplify recent GStreamer changes with deleters.
This commit is contained in:
@@ -103,40 +103,25 @@ struct g_mutex_locker
|
|||||||
GMutex &mutex;
|
GMutex &mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GstString
|
template<typename T, void(*Fn)(T*)> struct Deleter {
|
||||||
{
|
inline void operator() (void *p) const
|
||||||
explicit GstString(gchar *string_ = nullptr)
|
|
||||||
: string(string_)
|
|
||||||
{}
|
|
||||||
~GstString()
|
|
||||||
{
|
{
|
||||||
reset();
|
if (p)
|
||||||
|
Fn(static_cast<T*>(p));
|
||||||
}
|
}
|
||||||
void reset(gchar *string_ = nullptr)
|
|
||||||
{
|
|
||||||
if (string && string != string_)
|
|
||||||
g_free(string);
|
|
||||||
string = string_;
|
|
||||||
}
|
|
||||||
gchar *get() const { return string; }
|
|
||||||
explicit operator bool() const { return nullptr != get(); }
|
|
||||||
|
|
||||||
gchar *string;
|
|
||||||
};
|
};
|
||||||
|
using GstString = std::unique_ptr < gchar, Deleter<void, g_free> > ;
|
||||||
|
using GErrorHandle = std::unique_ptr < GError, Deleter<GError, g_error_free> > ;
|
||||||
|
|
||||||
struct GErrorHandle
|
using ParseFn = void (*)(GstMessage *message, GError **gerror, gchar **debug);
|
||||||
|
inline void GstMessageParse(ParseFn fn, GstMessage *msg, GErrorHandle &err, GstString &debug)
|
||||||
{
|
{
|
||||||
explicit GErrorHandle(GError *error_ = nullptr)
|
|
||||||
: error(error_)
|
|
||||||
{}
|
|
||||||
~GErrorHandle()
|
|
||||||
{
|
|
||||||
g_error_free(error);
|
|
||||||
}
|
|
||||||
GError *get() const { return error; }
|
|
||||||
explicit operator bool() const { return nullptr != get(); }
|
|
||||||
GError *error;
|
GError *error;
|
||||||
};
|
gchar *string;
|
||||||
|
fn(msg, &error, &string);
|
||||||
|
err.reset(error);
|
||||||
|
debug.reset(string);
|
||||||
|
}
|
||||||
|
|
||||||
// Context used for private stream data
|
// Context used for private stream data
|
||||||
struct GStreamContext
|
struct GStreamContext
|
||||||
@@ -171,56 +156,7 @@ struct GStreamContext
|
|||||||
};
|
};
|
||||||
|
|
||||||
// For RAII on gst objects
|
// For RAII on gst objects
|
||||||
template<typename T>
|
template<typename T> using GstObjHandle = std::unique_ptr < T, Deleter<void, gst_object_unref > > ;
|
||||||
struct GstObjHandle
|
|
||||||
{
|
|
||||||
explicit GstObjHandle(T* obj_ = nullptr)
|
|
||||||
: obj(obj_)
|
|
||||||
{}
|
|
||||||
~GstObjHandle()
|
|
||||||
{
|
|
||||||
unref();
|
|
||||||
}
|
|
||||||
|
|
||||||
void unref()
|
|
||||||
{
|
|
||||||
if (obj) {
|
|
||||||
gst_object_unref(obj);
|
|
||||||
obj = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GstObjHandle(const GstObjHandle&) PROHIBITED;
|
|
||||||
GstObjHandle &operator= (const GstObjHandle&) PROHIBITED;
|
|
||||||
|
|
||||||
GstObjHandle(GstObjHandle&& that)
|
|
||||||
: obj(that.obj)
|
|
||||||
{
|
|
||||||
that.obj = nullptr;
|
|
||||||
}
|
|
||||||
GstObjHandle &operator= (GstObjHandle&& that)
|
|
||||||
{
|
|
||||||
if (this != &that) {
|
|
||||||
unref();
|
|
||||||
obj = that.obj;
|
|
||||||
that.obj = nullptr;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* get() const { return obj; }
|
|
||||||
explicit operator bool() const
|
|
||||||
{ return nullptr != get(); }
|
|
||||||
void reset(T* obj_ = nullptr)
|
|
||||||
{
|
|
||||||
if (obj != obj_) {
|
|
||||||
unref();
|
|
||||||
obj = obj_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
T *obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
///! Does actual import, returned by GStreamerImportPlugin::Open
|
///! Does actual import, returned by GStreamerImportPlugin::Open
|
||||||
class GStreamerImportFileHandle final : public ImportFileHandle
|
class GStreamerImportFileHandle final : public ImportFileHandle
|
||||||
@@ -338,13 +274,15 @@ GetGStreamerImportPlugin(ImportPluginList *importPluginList,
|
|||||||
GErrorHandle error;
|
GErrorHandle error;
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
char **argv = NULL;
|
char **argv = NULL;
|
||||||
if (!gst_init_check(&argc, &argv, &error.error))
|
GError *ee;
|
||||||
|
if (!gst_init_check(&argc, &argv, &ee))
|
||||||
{
|
{
|
||||||
wxLogMessage(wxT("Failed to initialize GStreamer. Error %d: %s"),
|
wxLogMessage(wxT("Failed to initialize GStreamer. Error %d: %s"),
|
||||||
error.get()->code,
|
error.get()->code,
|
||||||
wxString::FromUTF8(error.get()->message).c_str());
|
wxString::FromUTF8(error.get()->message).c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
error.reset(ee);
|
||||||
|
|
||||||
guint major, minor, micro, nano;
|
guint major, minor, micro, nano;
|
||||||
gst_version(&major, &minor, µ, &nano);
|
gst_version(&major, &minor, µ, &nano);
|
||||||
@@ -413,10 +351,10 @@ GStreamerImportPlugin::GetSupportedExtensions()
|
|||||||
|
|
||||||
// Gather extensions from all factories that support audio
|
// Gather extensions from all factories that support audio
|
||||||
{
|
{
|
||||||
GList *factories = gst_type_find_factory_get_list();
|
std::unique_ptr < GList, Deleter<GList, gst_plugin_feature_list_free> >
|
||||||
auto cleanup = finally([&]{ gst_plugin_feature_list_free(factories); });
|
factories{ gst_type_find_factory_get_list() };
|
||||||
|
|
||||||
for (GList *list = factories; list != NULL; list = g_list_next(list))
|
for (GList *list = factories.get(); list != NULL; list = g_list_next(list))
|
||||||
{
|
{
|
||||||
GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY(list->data);
|
GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY(list->data);
|
||||||
|
|
||||||
@@ -548,6 +486,8 @@ GStreamerPadRemovedCallback(GstElement * WXUNUSED(element),
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Handle the "NEW-sample" signal from uridecodebin
|
// Handle the "NEW-sample" signal from uridecodebin
|
||||||
|
inline void GstSampleUnref(GstSample *p) { gst_sample_unref(p); } // I can't use the static function name directly...
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
GStreamerNewSample(GstAppSink *appsink, gpointer data)
|
GStreamerNewSample(GstAppSink *appsink, gpointer data)
|
||||||
{
|
{
|
||||||
@@ -555,17 +495,14 @@ GStreamerNewSample(GstAppSink *appsink, gpointer data)
|
|||||||
static GMutex mutex;
|
static GMutex mutex;
|
||||||
|
|
||||||
// Get the sample
|
// Get the sample
|
||||||
GstSample *sample = gst_app_sink_pull_sample(appsink);
|
std::unique_ptr < GstSample, Deleter< GstSample, GstSampleUnref> >
|
||||||
auto cleanup = finally([&]{
|
sample{ gst_app_sink_pull_sample(appsink) };
|
||||||
// Release the sample
|
|
||||||
if(sample) gst_sample_unref(sample);
|
|
||||||
});
|
|
||||||
|
|
||||||
// We must single thread here to prevent concurrent use of the
|
// We must single thread here to prevent concurrent use of the
|
||||||
// Audacity track functions.
|
// Audacity track functions.
|
||||||
g_mutex_locker locker{ mutex };
|
g_mutex_locker locker{ mutex };
|
||||||
|
|
||||||
handle->OnNewSample(GETCTX(appsink), sample);
|
handle->OnNewSample(GETCTX(appsink), sample.get());
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
@@ -586,19 +523,8 @@ static GstAppSinkCallbacks AppSinkBitBucket =
|
|||||||
NULL // new_sample
|
NULL // new_sample
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GstCapsHandle
|
inline void GstCapsUnref(GstCaps *p) { gst_caps_unref(p); } // I can't use the static function name directly...
|
||||||
{
|
using GstCapsHandle = std::unique_ptr < GstCaps, Deleter<GstCaps, GstCapsUnref> >;
|
||||||
explicit GstCapsHandle(GstCaps *caps_)
|
|
||||||
: caps(caps_)
|
|
||||||
{}
|
|
||||||
~GstCapsHandle()
|
|
||||||
{
|
|
||||||
if (caps)
|
|
||||||
gst_caps_unref(caps);
|
|
||||||
}
|
|
||||||
|
|
||||||
GstCaps *caps;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Handle the "pad-added" message
|
// Handle the "pad-added" message
|
||||||
@@ -1246,6 +1172,8 @@ GStreamerImportFileHandle::Import(TrackFactory *trackFactory,
|
|||||||
// Message handlers
|
// Message handlers
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline void GstMessageUnref(GstMessage *p) { gst_message_unref(p); }
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Retrieve and process a bus message
|
// Retrieve and process a bus message
|
||||||
bool
|
bool
|
||||||
@@ -1257,11 +1185,8 @@ GStreamerImportFileHandle::ProcessBusMessage(bool & success)
|
|||||||
success = true;
|
success = true;
|
||||||
|
|
||||||
// Get the next message
|
// Get the next message
|
||||||
GstMessage *msg = gst_bus_timed_pop(mBus.get(), 100 * GST_MSECOND);
|
std::unique_ptr < GstMessage, Deleter < GstMessage, GstMessageUnref > >
|
||||||
auto cleanp = finally([&]{
|
msg{ gst_bus_timed_pop(mBus.get(), 100 * GST_MSECOND) };
|
||||||
// Release the message
|
|
||||||
if (msg) gst_message_unref(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!msg)
|
if (!msg)
|
||||||
{
|
{
|
||||||
@@ -1278,14 +1203,14 @@ GStreamerImportFileHandle::ProcessBusMessage(bool & success)
|
|||||||
}
|
}
|
||||||
|
|
||||||
wxLogMessage(wxT("GStreamer: Got %s%s%s"),
|
wxLogMessage(wxT("GStreamer: Got %s%s%s"),
|
||||||
wxString::FromUTF8(GST_MESSAGE_TYPE_NAME(msg)).c_str(),
|
wxString::FromUTF8(GST_MESSAGE_TYPE_NAME(msg.get())).c_str(),
|
||||||
objname ? wxT(" from ") : wxT(""),
|
objname ? wxT(" from ") : wxT(""),
|
||||||
objname ? wxString::FromUTF8(objname.get()).c_str() : wxT(""));
|
objname ? wxString::FromUTF8(objname.get()).c_str() : wxT(""));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Handle based on message type
|
// Handle based on message type
|
||||||
switch (GST_MESSAGE_TYPE(msg))
|
switch (GST_MESSAGE_TYPE(msg.get()))
|
||||||
{
|
{
|
||||||
// Handle error message from gstreamer
|
// Handle error message from gstreamer
|
||||||
case GST_MESSAGE_ERROR:
|
case GST_MESSAGE_ERROR:
|
||||||
@@ -1293,7 +1218,7 @@ GStreamerImportFileHandle::ProcessBusMessage(bool & success)
|
|||||||
GErrorHandle err;
|
GErrorHandle err;
|
||||||
GstString debug;
|
GstString debug;
|
||||||
|
|
||||||
gst_message_parse_error(msg, &err.error, &debug.string);
|
GstMessageParse(gst_message_parse_error, msg.get(), err, debug);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
wxString m;
|
wxString m;
|
||||||
@@ -1319,8 +1244,7 @@ GStreamerImportFileHandle::ProcessBusMessage(bool & success)
|
|||||||
{
|
{
|
||||||
GErrorHandle err;
|
GErrorHandle err;
|
||||||
GstString debug;
|
GstString debug;
|
||||||
|
GstMessageParse(gst_message_parse_warning, msg.get(), err, debug);
|
||||||
gst_message_parse_warning(msg, &err.error, &debug.string);
|
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@@ -1338,7 +1262,7 @@ GStreamerImportFileHandle::ProcessBusMessage(bool & success)
|
|||||||
GErrorHandle err;
|
GErrorHandle err;
|
||||||
GstString debug;
|
GstString debug;
|
||||||
|
|
||||||
gst_message_parse_info(msg, &err.error, &debug.string);
|
GstMessageParse(gst_message_parse_info, msg.get(), err, debug);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
wxLogMessage(wxT("GStreamer Info: %s%s%s"),
|
wxLogMessage(wxT("GStreamer Info: %s%s%s"),
|
||||||
@@ -1359,11 +1283,11 @@ GStreamerImportFileHandle::ProcessBusMessage(bool & success)
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Retrieve tag list from message...just ignore failure
|
// Retrieve tag list from message...just ignore failure
|
||||||
gst_message_parse_tag(msg, &tags);
|
gst_message_parse_tag(msg.get(), &tags);
|
||||||
if (tags)
|
if (tags)
|
||||||
{
|
{
|
||||||
// Go process the list
|
// Go process the list
|
||||||
OnTag(GST_APP_SINK(GST_MESSAGE_SRC(msg)), tags);
|
OnTag(GST_APP_SINK(GST_MESSAGE_SRC(msg.get())), tags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user