mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
Added infrastructure to register URI to element+property mappings
Original commit message from CVS: Added infrastructure to register URI to element+property mappings
This commit is contained in:
parent
6550acf9c8
commit
1ee670cff4
8 changed files with 322 additions and 4 deletions
|
@ -84,6 +84,7 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
|
||||||
gsttrashstack.c \
|
gsttrashstack.c \
|
||||||
gsttype.c \
|
gsttype.c \
|
||||||
$(GST_TYPEFIND_SRC) \
|
$(GST_TYPEFIND_SRC) \
|
||||||
|
gsturi.c \
|
||||||
gstutils.c \
|
gstutils.c \
|
||||||
gstregistry.c \
|
gstregistry.c \
|
||||||
$(GST_PARSE_SRC) \
|
$(GST_PARSE_SRC) \
|
||||||
|
@ -143,6 +144,7 @@ gst_headers = \
|
||||||
gsttrashstack.h \
|
gsttrashstack.h \
|
||||||
gsttype.h \
|
gsttype.h \
|
||||||
gsttypefind.h \
|
gsttypefind.h \
|
||||||
|
gsturi.h \
|
||||||
gstutils.h \
|
gstutils.h \
|
||||||
gstregistry.h \
|
gstregistry.h \
|
||||||
gstparse.h \
|
gstparse.h \
|
||||||
|
|
|
@ -251,6 +251,7 @@ gst_spider_identity_getcaps (GstPad *pad, GstCaps *caps)
|
||||||
|
|
||||||
if (otherpad != NULL)
|
if (otherpad != NULL)
|
||||||
return gst_pad_get_allowed_caps (otherpad);
|
return gst_pad_get_allowed_caps (otherpad);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -455,6 +455,7 @@ init_post (void)
|
||||||
gst_autoplug_factory_get_type ();
|
gst_autoplug_factory_get_type ();
|
||||||
#endif
|
#endif
|
||||||
gst_index_factory_get_type ();
|
gst_index_factory_get_type ();
|
||||||
|
gst_uri_handler_get_type ();
|
||||||
|
|
||||||
|
|
||||||
plugin_path = g_getenv ("GST_PLUGIN_PATH");
|
plugin_path = g_getenv ("GST_PLUGIN_PATH");
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include <gst/gstcaps.h>
|
#include <gst/gstcaps.h>
|
||||||
#include <gst/gstprops.h>
|
#include <gst/gstprops.h>
|
||||||
#include <gst/gstplugin.h>
|
#include <gst/gstplugin.h>
|
||||||
|
#include <gst/gsturi.h>
|
||||||
#include <gst/gstutils.h>
|
#include <gst/gstutils.h>
|
||||||
#include <gst/gsttrace.h>
|
#include <gst/gsttrace.h>
|
||||||
#include <gst/gstxml.h>
|
#include <gst/gstxml.h>
|
||||||
|
|
|
@ -1863,13 +1863,17 @@ gst_pad_get_peer (GstPad *pad)
|
||||||
GstCaps*
|
GstCaps*
|
||||||
gst_pad_get_allowed_caps (GstPad *pad)
|
gst_pad_get_allowed_caps (GstPad *pad)
|
||||||
{
|
{
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
g_return_val_if_fail (pad != NULL, NULL);
|
g_return_val_if_fail (pad != NULL, NULL);
|
||||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||||
|
|
||||||
GST_DEBUG (GST_CAT_PROPERTIES, "get allowed caps of %s:%s",
|
GST_DEBUG (GST_CAT_PROPERTIES, "get allowed caps of %s:%s",
|
||||||
GST_DEBUG_PAD_NAME (pad));
|
GST_DEBUG_PAD_NAME (pad));
|
||||||
|
|
||||||
return gst_caps_copy (GST_RPAD_FILTER (pad));
|
caps = gst_caps_copy (GST_RPAD_FILTER (pad));
|
||||||
|
|
||||||
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
197
gst/gsturi.c
Normal file
197
gst/gsturi.c
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
* 2000 Wim Taymans <wtay@chello.be>
|
||||||
|
*
|
||||||
|
* gsttype.c: Media-type management functions
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
* probably should set up a hash table for the type id's, since currently
|
||||||
|
* it's a rather pathetic linear search. Eventually there may be dozens
|
||||||
|
* of id's, but in reality there are only so many instances of lookup, so
|
||||||
|
* I'm not overly worried yet...
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gst_private.h"
|
||||||
|
|
||||||
|
#include "gsturi.h"
|
||||||
|
#include "gstregistry.h"
|
||||||
|
#include "gstlog.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void gst_uri_handler_class_init (GstURIHandlerClass *klass);
|
||||||
|
static void gst_uri_handler_init (GstURIHandler *factory);
|
||||||
|
|
||||||
|
static GstPluginFeatureClass *parent_class = NULL;
|
||||||
|
/* static guint gst_uri_handler_signals[LAST_SIGNAL] = { 0 }; */
|
||||||
|
|
||||||
|
GType
|
||||||
|
gst_uri_handler_get_type (void)
|
||||||
|
{
|
||||||
|
static GType typefactory_type = 0;
|
||||||
|
|
||||||
|
if (!typefactory_type) {
|
||||||
|
static const GTypeInfo typefactory_info = {
|
||||||
|
sizeof (GstURIHandlerClass),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
(GClassInitFunc) gst_uri_handler_class_init,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
sizeof(GstURIHandler),
|
||||||
|
0,
|
||||||
|
(GInstanceInitFunc) gst_uri_handler_init,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
typefactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE,
|
||||||
|
"GstURIHandler", &typefactory_info, 0);
|
||||||
|
}
|
||||||
|
return typefactory_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_uri_handler_class_init (GstURIHandlerClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
GstObjectClass *gstobject_class;
|
||||||
|
GstPluginFeatureClass *gstpluginfeature_class;
|
||||||
|
|
||||||
|
gobject_class = (GObjectClass*)klass;
|
||||||
|
gstobject_class = (GstObjectClass*)klass;
|
||||||
|
gstpluginfeature_class = (GstPluginFeatureClass*) klass;
|
||||||
|
|
||||||
|
parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_uri_handler_init (GstURIHandler *factory)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_uri_handler_new:
|
||||||
|
* @definition: the definition to use
|
||||||
|
*
|
||||||
|
* Creata a new typefactory from the given definition.
|
||||||
|
*
|
||||||
|
* Returns: the new typefactory
|
||||||
|
*/
|
||||||
|
GstURIHandler*
|
||||||
|
gst_uri_handler_new (const gchar *name,
|
||||||
|
const gchar *uri, const gchar *longdesc,
|
||||||
|
const gchar *element, gchar *property)
|
||||||
|
{
|
||||||
|
GstURIHandler *factory;
|
||||||
|
|
||||||
|
g_return_val_if_fail (name != NULL, NULL);
|
||||||
|
g_return_val_if_fail (uri != NULL, NULL);
|
||||||
|
g_return_val_if_fail (element != NULL, NULL);
|
||||||
|
g_return_val_if_fail (property != NULL, NULL);
|
||||||
|
|
||||||
|
factory = gst_uri_handler_find (name);
|
||||||
|
|
||||||
|
if (!factory) {
|
||||||
|
factory = GST_URI_HANDLER (g_object_new (GST_TYPE_URI_HANDLER, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_PLUGIN_FEATURE_NAME (factory) = g_strdup (name);
|
||||||
|
factory->uri = g_strdup (uri);
|
||||||
|
factory->longdesc = g_strdup (longdesc);
|
||||||
|
factory->element = g_strdup (element);
|
||||||
|
factory->property = g_strdup (property);
|
||||||
|
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_uri_handler_find:
|
||||||
|
* @name: the name of the typefactory to find
|
||||||
|
*
|
||||||
|
* Return the URIHandler with the given name.
|
||||||
|
*
|
||||||
|
* Returns: a GstURIHandler with the given name;
|
||||||
|
*/
|
||||||
|
GstURIHandler*
|
||||||
|
gst_uri_handler_find (const gchar *name)
|
||||||
|
{
|
||||||
|
GstPluginFeature *feature;
|
||||||
|
|
||||||
|
g_return_val_if_fail (name != NULL, NULL);
|
||||||
|
|
||||||
|
feature = gst_registry_pool_find_feature (name, GST_TYPE_URI_HANDLER);
|
||||||
|
if (feature)
|
||||||
|
return GST_URI_HANDLER (feature);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstURIHandler*
|
||||||
|
gst_uri_handler_find_by_uri (const gchar *uri)
|
||||||
|
{
|
||||||
|
GList *walk, *orig;
|
||||||
|
GstURIHandler *handler = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (uri != NULL, NULL);
|
||||||
|
|
||||||
|
orig = walk = gst_registry_pool_feature_list (GST_TYPE_URI_HANDLER);
|
||||||
|
|
||||||
|
while (walk) {
|
||||||
|
handler = GST_URI_HANDLER (walk->data);
|
||||||
|
|
||||||
|
if (g_str_has_prefix (uri, handler->uri))
|
||||||
|
break;
|
||||||
|
|
||||||
|
walk = g_list_next (walk);
|
||||||
|
}
|
||||||
|
g_list_free (orig);
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstElement*
|
||||||
|
gst_uri_handler_create (GstURIHandler *factory, const gchar *name)
|
||||||
|
{
|
||||||
|
GstElement *element = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (factory != NULL, NULL);
|
||||||
|
|
||||||
|
element = gst_element_factory_make (factory->element, name);
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstElement*
|
||||||
|
gst_uri_handler_make_by_uri (const gchar *uri, const gchar *name)
|
||||||
|
{
|
||||||
|
GstElement *element = NULL;
|
||||||
|
GstURIHandler *handler;
|
||||||
|
|
||||||
|
g_return_val_if_fail (uri != NULL, NULL);
|
||||||
|
|
||||||
|
handler = gst_uri_handler_find_by_uri (uri);
|
||||||
|
if (handler) {
|
||||||
|
element = gst_uri_handler_create (handler, name);
|
||||||
|
if (element) {
|
||||||
|
g_object_set (G_OBJECT (element), handler->property, uri, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
71
gst/gsturi.h
Normal file
71
gst/gsturi.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
* 2000 Wim Taymans <wtay@chello.be>
|
||||||
|
*
|
||||||
|
* gstscheduler.h: Header for default scheduler code
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GST_URI_H__
|
||||||
|
#define __GST_URI_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <gst/gstelement.h>
|
||||||
|
#include <gst/gstpluginfeature.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_URI_HANDLER (gst_uri_handler_get_type ())
|
||||||
|
#define GST_URI_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_URI_HANDLER, GstURIHandler))
|
||||||
|
#define GST_IS_URI_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_URI_HANDLER))
|
||||||
|
#define GST_URI_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_URI_HANDLER, GstURIHandlerClass))
|
||||||
|
#define GST_IS_URI_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_URI_HANDLER))
|
||||||
|
#define GST_URI_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_URI_HANDLER, GstURIHandlerClass))
|
||||||
|
|
||||||
|
typedef struct _GstURIHandler GstURIHandler;
|
||||||
|
typedef struct _GstURIHandlerClass GstURIHandlerClass;
|
||||||
|
|
||||||
|
struct _GstURIHandler {
|
||||||
|
GstPluginFeature feature;
|
||||||
|
|
||||||
|
gchar *uri; /* The uri that is described */
|
||||||
|
gchar *longdesc; /* description of the uri */
|
||||||
|
gchar *element; /* The element that can handle this uri */
|
||||||
|
gchar *property; /* The property on the element to set the uri */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstURIHandlerClass {
|
||||||
|
GstPluginFeatureClass parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_uri_handler_get_type (void);
|
||||||
|
|
||||||
|
GstURIHandler* gst_uri_handler_new (const gchar *name,
|
||||||
|
const gchar *uri, const gchar *longdesc,
|
||||||
|
const gchar *element, gchar *property);
|
||||||
|
void gst_uri_handler_destroy (GstURIHandler *factory);
|
||||||
|
|
||||||
|
GstURIHandler* gst_uri_handler_find (const gchar *name);
|
||||||
|
GstURIHandler* gst_uri_handler_find_by_uri (const gchar *uri);
|
||||||
|
|
||||||
|
GstElement* gst_uri_handler_create (GstURIHandler *factory, const gchar *name);
|
||||||
|
GstElement* gst_uri_handler_make_by_uri (const gchar *uri, const gchar *name);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_SCHEDULER_H__ */
|
|
@ -34,6 +34,7 @@
|
||||||
#include <gst/gsttype.h>
|
#include <gst/gsttype.h>
|
||||||
#include <gst/gstscheduler.h>
|
#include <gst/gstscheduler.h>
|
||||||
#include <gst/gstautoplug.h>
|
#include <gst/gstautoplug.h>
|
||||||
|
#include <gst/gsturi.h>
|
||||||
|
|
||||||
#include "gstxmlregistry.h"
|
#include "gstxmlregistry.h"
|
||||||
|
|
||||||
|
@ -769,6 +770,30 @@ gst_xml_registry_parse_index_factory (GMarkupParseContext *context, const gchar
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_xml_registry_parse_uri_handler (GMarkupParseContext *context, const gchar *tag, const gchar *text,
|
||||||
|
gsize text_len, GstXMLRegistry *registry, GError **error)
|
||||||
|
{
|
||||||
|
GstURIHandler *handler = GST_URI_HANDLER (registry->current_feature);
|
||||||
|
|
||||||
|
if (!strcmp (tag, "name")) {
|
||||||
|
registry->current_feature->name = g_strndup (text, text_len);
|
||||||
|
}
|
||||||
|
else if (!strcmp (tag, "uri")) {
|
||||||
|
handler->uri = g_strndup (text, text_len);
|
||||||
|
}
|
||||||
|
else if (!strcmp (tag, "longdesc")) {
|
||||||
|
handler->longdesc = g_strndup (text, text_len);
|
||||||
|
}
|
||||||
|
else if (!strcmp (tag, "element")) {
|
||||||
|
handler->element = g_strndup (text, text_len);
|
||||||
|
}
|
||||||
|
else if (!strcmp (tag, "property")) {
|
||||||
|
handler->property = g_strndup (text, text_len);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_xml_registry_parse_padtemplate (GMarkupParseContext *context, const gchar *tag, const gchar *text,
|
gst_xml_registry_parse_padtemplate (GMarkupParseContext *context, const gchar *tag, const gchar *text,
|
||||||
gsize text_len, GstXMLRegistry *registry, GError **error)
|
gsize text_len, GstXMLRegistry *registry, GError **error)
|
||||||
|
@ -865,6 +890,7 @@ gst_xml_registry_start_element (GMarkupParseContext *context,
|
||||||
}
|
}
|
||||||
if (feature) {
|
if (feature) {
|
||||||
xmlregistry->current_feature = feature;
|
xmlregistry->current_feature = feature;
|
||||||
|
|
||||||
if (GST_IS_ELEMENT_FACTORY (feature)) {
|
if (GST_IS_ELEMENT_FACTORY (feature)) {
|
||||||
GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
|
GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
|
||||||
|
|
||||||
|
@ -873,17 +899,24 @@ gst_xml_registry_start_element (GMarkupParseContext *context,
|
||||||
factory->padtemplates = NULL;
|
factory->padtemplates = NULL;
|
||||||
factory->rank = 0;
|
factory->rank = 0;
|
||||||
xmlregistry->parser = gst_xml_registry_parse_element_factory;
|
xmlregistry->parser = gst_xml_registry_parse_element_factory;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (GST_IS_TYPE_FACTORY (feature))
|
else if (GST_IS_TYPE_FACTORY (feature)) {
|
||||||
xmlregistry->parser = gst_xml_registry_parse_type_factory;
|
xmlregistry->parser = gst_xml_registry_parse_type_factory;
|
||||||
|
}
|
||||||
else if (GST_IS_SCHEDULER_FACTORY (feature)) {
|
else if (GST_IS_SCHEDULER_FACTORY (feature)) {
|
||||||
xmlregistry->parser = gst_xml_registry_parse_scheduler_factory;
|
xmlregistry->parser = gst_xml_registry_parse_scheduler_factory;
|
||||||
GST_SCHEDULER_FACTORY (feature)->type = 0;
|
GST_SCHEDULER_FACTORY (feature)->type = 0;
|
||||||
}
|
}
|
||||||
else if (GST_IS_AUTOPLUG_FACTORY (feature))
|
else if (GST_IS_AUTOPLUG_FACTORY (feature)) {
|
||||||
xmlregistry->parser = gst_xml_registry_parse_autoplug_factory;
|
xmlregistry->parser = gst_xml_registry_parse_autoplug_factory;
|
||||||
else if (GST_IS_INDEX_FACTORY (feature))
|
}
|
||||||
|
else if (GST_IS_INDEX_FACTORY (feature)) {
|
||||||
xmlregistry->parser = gst_xml_registry_parse_index_factory;
|
xmlregistry->parser = gst_xml_registry_parse_index_factory;
|
||||||
|
}
|
||||||
|
else if (GST_IS_URI_HANDLER (feature)) {
|
||||||
|
xmlregistry->parser = gst_xml_registry_parse_uri_handler;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
g_warning ("unkown feature type");
|
g_warning ("unkown feature type");
|
||||||
}
|
}
|
||||||
|
@ -1411,6 +1444,14 @@ gst_xml_registry_save_feature (GstXMLRegistry *xmlregistry, GstPluginFeature *fe
|
||||||
else if (GST_IS_INDEX_FACTORY (feature)) {
|
else if (GST_IS_INDEX_FACTORY (feature)) {
|
||||||
PUT_ESCAPED ("longdesc", GST_INDEX_FACTORY (feature)->longdesc);
|
PUT_ESCAPED ("longdesc", GST_INDEX_FACTORY (feature)->longdesc);
|
||||||
}
|
}
|
||||||
|
else if (GST_IS_URI_HANDLER (feature)) {
|
||||||
|
GstURIHandler *handler = GST_URI_HANDLER (feature);
|
||||||
|
|
||||||
|
PUT_ESCAPED ("uri", handler->uri);
|
||||||
|
PUT_ESCAPED ("longdesc", handler->longdesc);
|
||||||
|
PUT_ESCAPED ("element", handler->element);
|
||||||
|
PUT_ESCAPED ("property", handler->property);
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue