2012-09-23 00:13:38 +00:00
|
|
|
/* GStreamer Editing Services
|
|
|
|
*
|
|
|
|
* Copyright (C) <2012> Thibault Saunier <thibault.saunier@collabora.com>
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "test-utils.h"
|
|
|
|
#include <ges/ges.h>
|
|
|
|
#include <gst/check/gstcheck.h>
|
2013-03-30 17:54:50 +00:00
|
|
|
#include <gst/controller/gstdirectcontrolbinding.h>
|
|
|
|
#include <gst/controller/gstinterpolationcontrolsource.h>
|
2012-09-23 00:13:38 +00:00
|
|
|
|
2014-01-27 14:30:40 +00:00
|
|
|
GMainLoop *mainloop;
|
|
|
|
|
2012-12-29 22:36:07 +00:00
|
|
|
static void
|
|
|
|
project_loaded_cb (GESProject * project, GESTimeline * timeline,
|
|
|
|
GMainLoop * mainloop)
|
|
|
|
{
|
|
|
|
g_main_loop_quit (mainloop);
|
|
|
|
}
|
|
|
|
|
2012-09-23 00:13:38 +00:00
|
|
|
GST_START_TEST (test_project_simple)
|
|
|
|
{
|
|
|
|
gchar *id;
|
|
|
|
GESProject *project;
|
|
|
|
GESTimeline *timeline;
|
|
|
|
|
|
|
|
ges_init ();
|
|
|
|
|
2012-12-29 22:36:07 +00:00
|
|
|
mainloop = g_main_loop_new (NULL, FALSE);
|
2012-09-23 00:13:38 +00:00
|
|
|
project = GES_PROJECT (ges_asset_request (GES_TYPE_TIMELINE, NULL, NULL));
|
|
|
|
fail_unless (GES_IS_PROJECT (project));
|
|
|
|
assert_equals_string (ges_asset_get_id (GES_ASSET (project)), "project-0");
|
2012-12-29 22:36:07 +00:00
|
|
|
g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
|
2012-09-23 00:13:38 +00:00
|
|
|
|
|
|
|
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
|
2012-12-29 22:36:07 +00:00
|
|
|
g_main_loop_run (mainloop);
|
|
|
|
|
2012-09-23 00:13:38 +00:00
|
|
|
fail_unless (GES_IS_TIMELINE (timeline));
|
|
|
|
id = ges_extractable_get_id (GES_EXTRACTABLE (timeline));
|
|
|
|
assert_equals_string (id, "project-0");
|
2012-12-29 22:36:07 +00:00
|
|
|
ASSERT_OBJECT_REFCOUNT (timeline, "We own the only ref", 1);
|
2012-09-23 00:13:38 +00:00
|
|
|
|
|
|
|
g_free (id);
|
2012-12-29 22:36:07 +00:00
|
|
|
gst_object_unref (project);
|
|
|
|
gst_object_unref (timeline);
|
|
|
|
g_main_loop_unref (mainloop);
|
|
|
|
g_signal_handlers_disconnect_by_func (project, (GCallback) project_loaded_cb,
|
|
|
|
mainloop);
|
2019-01-28 02:24:29 +00:00
|
|
|
|
|
|
|
ges_deinit ();
|
2012-09-23 00:13:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GST_END_TEST;
|
|
|
|
|
|
|
|
static void
|
|
|
|
asset_removed_add_cb (GESProject * project, GESAsset * asset, gboolean * called)
|
|
|
|
{
|
|
|
|
*called = TRUE;
|
|
|
|
}
|
|
|
|
|
2014-01-27 14:30:40 +00:00
|
|
|
static void
|
|
|
|
asset_created_cb (GObject * source, GAsyncResult * res, GESAsset ** asset)
|
|
|
|
{
|
|
|
|
GError *error = NULL;
|
|
|
|
*asset = ges_asset_request_finish (res, &error);
|
|
|
|
|
|
|
|
fail_unless (error == NULL);
|
|
|
|
g_main_loop_quit (mainloop);
|
|
|
|
}
|
|
|
|
|
2012-09-23 00:13:38 +00:00
|
|
|
GST_START_TEST (test_project_add_assets)
|
|
|
|
{
|
|
|
|
GESProject *project;
|
|
|
|
GESAsset *asset;
|
|
|
|
gboolean added_cb_called = FALSE;
|
|
|
|
gboolean removed_cb_called = FALSE;
|
|
|
|
|
|
|
|
ges_init ();
|
|
|
|
|
2014-01-27 14:30:40 +00:00
|
|
|
mainloop = g_main_loop_new (NULL, FALSE);
|
2012-09-23 00:13:38 +00:00
|
|
|
project = GES_PROJECT (ges_asset_request (GES_TYPE_TIMELINE, NULL, NULL));
|
|
|
|
fail_unless (GES_IS_PROJECT (project));
|
|
|
|
|
|
|
|
g_signal_connect (project, "asset-added",
|
|
|
|
(GCallback) asset_removed_add_cb, &added_cb_called);
|
|
|
|
g_signal_connect (project, "asset-removed",
|
|
|
|
(GCallback) asset_removed_add_cb, &removed_cb_called);
|
|
|
|
|
2014-01-27 14:30:40 +00:00
|
|
|
ges_asset_request_async (GES_TYPE_TEST_CLIP, NULL, NULL,
|
|
|
|
(GAsyncReadyCallback) asset_created_cb, &asset);
|
|
|
|
g_main_loop_run (mainloop);
|
|
|
|
g_main_loop_unref (mainloop);
|
|
|
|
|
2012-09-23 00:13:38 +00:00
|
|
|
fail_unless (GES_IS_ASSET (asset));
|
|
|
|
|
|
|
|
fail_unless (ges_project_add_asset (project, asset));
|
|
|
|
fail_unless (added_cb_called);
|
|
|
|
ASSERT_OBJECT_REFCOUNT (project, "The project", 2);
|
|
|
|
ASSERT_OBJECT_REFCOUNT (asset, "The asset (1 for project and one for "
|
|
|
|
"us + 1 cache)", 3);
|
|
|
|
|
|
|
|
fail_unless (ges_project_remove_asset (project, asset));
|
|
|
|
fail_unless (removed_cb_called);
|
|
|
|
|
2012-12-29 22:36:07 +00:00
|
|
|
g_signal_handlers_disconnect_by_func (project,
|
|
|
|
(GCallback) asset_removed_add_cb, &added_cb_called);
|
|
|
|
g_signal_handlers_disconnect_by_func (project,
|
|
|
|
(GCallback) asset_removed_add_cb, &removed_cb_called);
|
|
|
|
|
2014-01-27 14:30:40 +00:00
|
|
|
gst_object_unref (asset);
|
|
|
|
gst_object_unref (project);
|
2012-09-23 00:13:38 +00:00
|
|
|
ASSERT_OBJECT_REFCOUNT (asset, "The asset (1 ref in cache)", 1);
|
|
|
|
ASSERT_OBJECT_REFCOUNT (project, "The project (1 ref in cache)", 1);
|
2019-01-28 02:24:29 +00:00
|
|
|
|
|
|
|
ges_deinit ();
|
2012-09-23 00:13:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GST_END_TEST;
|
|
|
|
|
|
|
|
static void
|
|
|
|
error_loading_asset_cb (GESProject * project, GError * error, gchar * id,
|
|
|
|
GType extractable_type, GMainLoop * mainloop)
|
|
|
|
{
|
|
|
|
fail_unless (g_error_matches (error, GST_PARSE_ERROR,
|
|
|
|
GST_PARSE_ERROR_NO_SUCH_ELEMENT));
|
|
|
|
g_main_loop_quit (mainloop);
|
|
|
|
}
|
|
|
|
|
|
|
|
GST_START_TEST (test_project_unexistant_effect)
|
|
|
|
{
|
|
|
|
GESProject *project;
|
|
|
|
gboolean added_cb_called = FALSE;
|
|
|
|
gboolean removed_cb_called = FALSE;
|
|
|
|
|
|
|
|
ges_init ();
|
|
|
|
|
|
|
|
project = GES_PROJECT (ges_asset_request (GES_TYPE_TIMELINE, NULL, NULL));
|
|
|
|
fail_unless (GES_IS_PROJECT (project));
|
|
|
|
|
|
|
|
mainloop = g_main_loop_new (NULL, FALSE);
|
|
|
|
g_signal_connect (project, "asset-added",
|
|
|
|
(GCallback) asset_removed_add_cb, &added_cb_called);
|
|
|
|
g_signal_connect (project, "asset-removed",
|
|
|
|
(GCallback) asset_removed_add_cb, &removed_cb_called);
|
|
|
|
g_signal_connect (project, "error-loading-asset",
|
|
|
|
(GCallback) error_loading_asset_cb, mainloop);
|
|
|
|
|
|
|
|
fail_unless (ges_project_create_asset (project, "nowaythiselementexists",
|
2013-01-26 15:40:51 +00:00
|
|
|
GES_TYPE_EFFECT));
|
2012-09-23 00:13:38 +00:00
|
|
|
g_main_loop_run (mainloop);
|
|
|
|
|
|
|
|
/* And.... try again! */
|
2013-01-11 22:07:22 +00:00
|
|
|
fail_if (ges_project_create_asset (project, "nowaythiselementexists",
|
2013-01-26 15:40:51 +00:00
|
|
|
GES_TYPE_EFFECT));
|
2012-09-23 00:13:38 +00:00
|
|
|
|
|
|
|
fail_if (added_cb_called);
|
|
|
|
fail_if (removed_cb_called);
|
|
|
|
|
|
|
|
ASSERT_OBJECT_REFCOUNT (project, "The project", 2);
|
|
|
|
gst_object_unref (project);
|
|
|
|
g_main_loop_unref (mainloop);
|
|
|
|
|
|
|
|
ASSERT_OBJECT_REFCOUNT (project, "The project (1 ref in cache)", 1);
|
|
|
|
|
2019-01-28 02:24:29 +00:00
|
|
|
ges_deinit ();
|
2012-09-23 00:13:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GST_END_TEST;
|
|
|
|
|
|
|
|
static void
|
|
|
|
asset_added_cb (GESProject * project, GESAsset * asset)
|
|
|
|
{
|
|
|
|
gchar *uri = ges_test_file_uri ("audio_video.ogg");
|
|
|
|
GstDiscovererInfo *info;
|
|
|
|
|
2013-01-26 15:40:51 +00:00
|
|
|
if (ges_asset_get_extractable_type (asset) == GES_TYPE_EFFECT) {
|
2016-01-25 14:57:22 +00:00
|
|
|
assert_equals_string (ges_asset_get_id (asset), "video agingtv");
|
2012-09-23 00:13:38 +00:00
|
|
|
} else {
|
2013-01-20 15:44:57 +00:00
|
|
|
info = ges_uri_clip_asset_get_info (GES_URI_CLIP_ASSET (asset));
|
2012-09-23 00:13:38 +00:00
|
|
|
fail_unless (GST_IS_DISCOVERER_INFO (info));
|
|
|
|
assert_equals_string (ges_asset_get_id (asset), uri);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (uri);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gchar *
|
|
|
|
_set_new_uri (GESProject * project, GError * error, GESAsset * wrong_asset)
|
|
|
|
{
|
|
|
|
fail_unless (!g_strcmp0 (ges_asset_get_id (wrong_asset),
|
|
|
|
"file:///test/not/exisiting"));
|
|
|
|
|
|
|
|
return ges_test_file_uri ("audio_video.ogg");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_test_project (GESProject * project, GESTimeline * timeline)
|
|
|
|
{
|
|
|
|
guint a_meta;
|
|
|
|
gchar *media_uri;
|
|
|
|
GESTrack *track;
|
|
|
|
const GList *profiles;
|
|
|
|
GstEncodingContainerProfile *profile;
|
2013-01-26 15:31:33 +00:00
|
|
|
GList *tracks, *tmp, *tmptrackelement, *clips;
|
2012-09-23 00:13:38 +00:00
|
|
|
|
|
|
|
fail_unless (GES_IS_TIMELINE (timeline));
|
|
|
|
assert_equals_int (g_list_length (timeline->layers), 2);
|
|
|
|
|
|
|
|
assert_equals_string (ges_meta_container_get_string (GES_META_CONTAINER
|
|
|
|
(project), "name"), "Example project");
|
2013-04-23 23:04:04 +00:00
|
|
|
clips = ges_layer_get_clips (GES_LAYER (timeline->layers->data));
|
|
|
|
fail_unless (ges_meta_container_get_uint (GES_META_CONTAINER
|
|
|
|
(timeline->layers->data), "a", &a_meta));
|
2012-09-23 00:13:38 +00:00
|
|
|
assert_equals_int (a_meta, 3);
|
2013-01-20 15:42:29 +00:00
|
|
|
assert_equals_int (g_list_length (clips), 1);
|
2012-09-23 00:13:38 +00:00
|
|
|
media_uri = ges_test_file_uri ("audio_video.ogg");
|
|
|
|
assert_equals_string (ges_asset_get_id (ges_extractable_get_asset
|
2013-01-20 15:42:29 +00:00
|
|
|
(GES_EXTRACTABLE (clips->data))), media_uri);
|
2012-09-23 00:13:38 +00:00
|
|
|
g_free (media_uri);
|
2013-01-20 15:42:29 +00:00
|
|
|
g_list_free_full (clips, gst_object_unref);
|
2012-09-23 00:13:38 +00:00
|
|
|
|
|
|
|
/* Check tracks and the objects they contain */
|
|
|
|
tracks = ges_timeline_get_tracks (timeline);
|
|
|
|
assert_equals_int (g_list_length (tracks), 2);
|
|
|
|
for (tmp = tracks; tmp; tmp = tmp->next) {
|
2013-01-26 15:31:33 +00:00
|
|
|
GList *trackelements;
|
2012-09-23 00:13:38 +00:00
|
|
|
track = GES_TRACK (tmp->data);
|
|
|
|
|
2013-02-08 20:23:18 +00:00
|
|
|
trackelements = ges_track_get_elements (track);
|
2012-12-29 22:36:07 +00:00
|
|
|
GST_DEBUG_OBJECT (track, "Testing track");
|
2012-09-23 00:13:38 +00:00
|
|
|
switch (track->type) {
|
|
|
|
case GES_TRACK_TYPE_VIDEO:
|
2013-01-26 15:31:33 +00:00
|
|
|
assert_equals_int (g_list_length (trackelements), 2);
|
|
|
|
for (tmptrackelement = trackelements; tmptrackelement;
|
|
|
|
tmptrackelement = tmptrackelement->next) {
|
|
|
|
GESTrackElement *trackelement =
|
|
|
|
GES_TRACK_ELEMENT (tmptrackelement->data);
|
2012-09-23 00:13:38 +00:00
|
|
|
|
2013-01-26 15:35:19 +00:00
|
|
|
if (GES_IS_BASE_EFFECT (trackelement)) {
|
2012-09-23 00:13:38 +00:00
|
|
|
guint nb_scratch_lines;
|
|
|
|
|
2015-02-19 15:30:18 +00:00
|
|
|
ges_timeline_element_get_child_properties (tmptrackelement->data,
|
2013-01-26 15:31:33 +00:00
|
|
|
"scratch-lines", &nb_scratch_lines, NULL);
|
2012-09-23 00:13:38 +00:00
|
|
|
assert_equals_int (nb_scratch_lines, 12);
|
|
|
|
|
2014-08-15 13:48:14 +00:00
|
|
|
nle_object_check (ges_track_element_get_nleobject (trackelement),
|
2016-08-11 13:14:42 +00:00
|
|
|
0, 1000000000, 0, 1000000000, MIN_NLE_PRIO + TRANSITIONS_HEIGHT,
|
|
|
|
TRUE);
|
2012-09-23 00:13:38 +00:00
|
|
|
} else {
|
2014-08-15 13:48:14 +00:00
|
|
|
nle_object_check (ges_track_element_get_nleobject (trackelement),
|
2016-08-11 13:14:42 +00:00
|
|
|
0, 1000000000, 0, 1000000000,
|
|
|
|
MIN_NLE_PRIO + TRANSITIONS_HEIGHT + 1, TRUE);
|
2012-09-23 00:13:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GES_TRACK_TYPE_AUDIO:
|
2013-01-26 15:31:33 +00:00
|
|
|
assert_equals_int (g_list_length (trackelements), 2);
|
2012-09-23 00:13:38 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert (1);
|
|
|
|
}
|
|
|
|
|
2013-01-26 15:31:33 +00:00
|
|
|
g_list_free_full (trackelements, gst_object_unref);
|
2012-09-23 00:13:38 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
g_list_free_full (tracks, gst_object_unref);
|
|
|
|
|
|
|
|
/* Now test the encoding profile */
|
|
|
|
profiles = ges_project_list_encoding_profiles (project);
|
|
|
|
assert_equals_int (g_list_length ((GList *) profiles), 1);
|
|
|
|
profile = profiles->data;
|
|
|
|
fail_unless (GST_IS_ENCODING_CONTAINER_PROFILE (profile));
|
|
|
|
profiles = gst_encoding_container_profile_get_profiles (profile);
|
|
|
|
assert_equals_int (g_list_length ((GList *) profiles), 2);
|
|
|
|
}
|
|
|
|
|
2013-03-30 17:54:50 +00:00
|
|
|
static void
|
2013-09-23 16:40:34 +00:00
|
|
|
_add_properties (GESTimeline * timeline)
|
2013-03-30 17:54:50 +00:00
|
|
|
{
|
|
|
|
GList *tracks;
|
|
|
|
GList *tmp;
|
|
|
|
|
|
|
|
tracks = ges_timeline_get_tracks (timeline);
|
|
|
|
for (tmp = tracks; tmp; tmp = tmp->next) {
|
|
|
|
GESTrack *track;
|
|
|
|
GList *track_elements;
|
|
|
|
GList *tmp_tck;
|
|
|
|
|
|
|
|
track = GES_TRACK (tmp->data);
|
|
|
|
switch (track->type) {
|
|
|
|
case GES_TRACK_TYPE_VIDEO:
|
|
|
|
track_elements = ges_track_get_elements (track);
|
|
|
|
|
|
|
|
for (tmp_tck = track_elements; tmp_tck; tmp_tck = tmp_tck->next) {
|
|
|
|
GESTrackElement *element = GES_TRACK_ELEMENT (tmp_tck->data);
|
|
|
|
|
2013-09-23 16:40:34 +00:00
|
|
|
/* Adding keyframes */
|
2013-03-30 17:54:50 +00:00
|
|
|
if (GES_IS_EFFECT (element)) {
|
|
|
|
GstControlSource *source;
|
|
|
|
GstControlBinding *tmp_binding, *binding;
|
|
|
|
|
|
|
|
source = gst_interpolation_control_source_new ();
|
|
|
|
|
|
|
|
/* Check binding creation and replacement */
|
|
|
|
binding =
|
|
|
|
ges_track_element_get_control_binding (element,
|
|
|
|
"scratch-lines");
|
|
|
|
fail_unless (binding == NULL);
|
2013-03-31 14:07:14 +00:00
|
|
|
ges_track_element_set_control_source (element,
|
2013-03-30 17:54:50 +00:00
|
|
|
source, "scratch-lines", "direct");
|
|
|
|
tmp_binding =
|
|
|
|
ges_track_element_get_control_binding (element,
|
|
|
|
"scratch-lines");
|
|
|
|
fail_unless (tmp_binding != NULL);
|
2013-03-31 14:07:14 +00:00
|
|
|
ges_track_element_set_control_source (element,
|
2013-03-30 17:54:50 +00:00
|
|
|
source, "scratch-lines", "direct");
|
|
|
|
binding =
|
|
|
|
ges_track_element_get_control_binding (element,
|
|
|
|
"scratch-lines");
|
|
|
|
fail_unless (binding != tmp_binding);
|
|
|
|
|
|
|
|
|
|
|
|
g_object_set (source, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
|
|
|
|
gst_timed_value_control_source_set (GST_TIMED_VALUE_CONTROL_SOURCE
|
|
|
|
(source), 0 * GST_SECOND, 0.);
|
|
|
|
gst_timed_value_control_source_set (GST_TIMED_VALUE_CONTROL_SOURCE
|
|
|
|
(source), 5 * GST_SECOND, 0.);
|
|
|
|
gst_timed_value_control_source_set (GST_TIMED_VALUE_CONTROL_SOURCE
|
|
|
|
(source), 10 * GST_SECOND, 1.);
|
2020-05-20 20:20:10 +00:00
|
|
|
|
|
|
|
gst_object_unref (source);
|
2019-04-09 12:58:24 +00:00
|
|
|
} else if (GES_IS_VIDEO_SOURCE (element)) {
|
|
|
|
/* Adding children properties */
|
2021-05-01 20:50:11 +00:00
|
|
|
gint posx = 42;
|
2015-02-19 15:30:18 +00:00
|
|
|
ges_timeline_element_set_child_properties (GES_TIMELINE_ELEMENT
|
|
|
|
(element), "posx", posx, NULL);
|
|
|
|
ges_timeline_element_get_child_properties (GES_TIMELINE_ELEMENT
|
|
|
|
(element), "posx", &posx, NULL);
|
2021-05-01 20:50:11 +00:00
|
|
|
fail_unless_equals_int (posx, 42);
|
2013-09-23 16:40:34 +00:00
|
|
|
}
|
2019-04-12 22:31:07 +00:00
|
|
|
|
2013-03-30 17:54:50 +00:00
|
|
|
}
|
2019-04-12 22:31:07 +00:00
|
|
|
g_list_free_full (track_elements, g_object_unref);
|
2013-03-30 17:54:50 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-04-09 12:58:24 +00:00
|
|
|
|
|
|
|
g_list_free_full (tracks, g_object_unref);
|
2013-03-30 17:54:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2013-09-23 16:40:34 +00:00
|
|
|
_check_properties (GESTimeline * timeline)
|
2013-03-30 17:54:50 +00:00
|
|
|
{
|
|
|
|
GList *tracks;
|
|
|
|
GList *tmp;
|
|
|
|
|
|
|
|
tracks = ges_timeline_get_tracks (timeline);
|
|
|
|
for (tmp = tracks; tmp; tmp = tmp->next) {
|
|
|
|
GESTrack *track;
|
|
|
|
GList *track_elements;
|
|
|
|
GList *tmp_tck;
|
|
|
|
|
|
|
|
track = GES_TRACK (tmp->data);
|
|
|
|
switch (track->type) {
|
|
|
|
case GES_TRACK_TYPE_VIDEO:
|
|
|
|
track_elements = ges_track_get_elements (track);
|
|
|
|
|
|
|
|
for (tmp_tck = track_elements; tmp_tck; tmp_tck = tmp_tck->next) {
|
|
|
|
GESTrackElement *element = GES_TRACK_ELEMENT (tmp_tck->data);
|
2013-09-23 16:40:34 +00:00
|
|
|
/* Checking keyframes */
|
2013-03-30 17:54:50 +00:00
|
|
|
if (GES_IS_EFFECT (element)) {
|
|
|
|
GstControlBinding *binding;
|
|
|
|
GstControlSource *source;
|
2019-07-12 20:15:35 +00:00
|
|
|
GList *timed_values, *tmpvalue;
|
2013-03-30 17:54:50 +00:00
|
|
|
GstTimedValue *value;
|
|
|
|
|
|
|
|
binding =
|
|
|
|
ges_track_element_get_control_binding (element,
|
|
|
|
"scratch-lines");
|
|
|
|
fail_unless (binding != NULL);
|
|
|
|
g_object_get (binding, "control-source", &source, NULL);
|
|
|
|
fail_unless (source != NULL);
|
|
|
|
|
|
|
|
/* Now check keyframe position */
|
2019-07-12 20:15:35 +00:00
|
|
|
tmpvalue = timed_values =
|
2013-03-30 17:54:50 +00:00
|
|
|
gst_timed_value_control_source_get_all
|
|
|
|
(GST_TIMED_VALUE_CONTROL_SOURCE (source));
|
2019-07-12 20:15:35 +00:00
|
|
|
value = tmpvalue->data;
|
2013-03-30 17:54:50 +00:00
|
|
|
fail_unless (value->value == 0.);
|
|
|
|
fail_unless (value->timestamp == 0 * GST_SECOND);
|
2019-07-12 20:15:35 +00:00
|
|
|
tmpvalue = tmpvalue->next;
|
|
|
|
value = tmpvalue->data;
|
2013-03-30 17:54:50 +00:00
|
|
|
fail_unless (value->value == 0.);
|
|
|
|
fail_unless (value->timestamp == 5 * GST_SECOND);
|
2019-07-12 20:15:35 +00:00
|
|
|
tmpvalue = tmpvalue->next;
|
|
|
|
value = tmpvalue->data;
|
2013-03-30 17:54:50 +00:00
|
|
|
fail_unless (value->value == 1.);
|
|
|
|
fail_unless (value->timestamp == 10 * GST_SECOND);
|
2019-07-12 20:15:35 +00:00
|
|
|
g_list_free (timed_values);
|
2020-05-20 20:20:10 +00:00
|
|
|
gst_object_unref (source);
|
2013-03-30 17:54:50 +00:00
|
|
|
}
|
2013-09-23 16:40:34 +00:00
|
|
|
/* Checking children properties */
|
|
|
|
else if (GES_IS_VIDEO_SOURCE (element)) {
|
|
|
|
/* Init 'posx' with a wrong value */
|
2021-05-01 20:50:11 +00:00
|
|
|
gint posx = 27;
|
2015-02-19 15:30:18 +00:00
|
|
|
ges_timeline_element_get_child_properties (GES_TIMELINE_ELEMENT
|
|
|
|
(element), "posx", &posx, NULL);
|
2021-05-01 20:50:11 +00:00
|
|
|
fail_unless_equals_int (posx, 42);
|
2013-09-23 16:40:34 +00:00
|
|
|
}
|
2013-03-30 17:54:50 +00:00
|
|
|
}
|
2019-04-09 12:58:24 +00:00
|
|
|
g_list_free_full (track_elements, g_object_unref);
|
2013-03-30 17:54:50 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-04-09 12:58:24 +00:00
|
|
|
|
|
|
|
g_list_free_full (tracks, g_object_unref);
|
2013-03-30 17:54:50 +00:00
|
|
|
}
|
|
|
|
|
2013-09-23 16:40:34 +00:00
|
|
|
GST_START_TEST (test_project_add_properties)
|
2013-03-30 17:54:50 +00:00
|
|
|
{
|
|
|
|
GESProject *project;
|
|
|
|
GESTimeline *timeline;
|
2019-01-28 02:24:29 +00:00
|
|
|
gchar *uri;
|
|
|
|
|
|
|
|
ges_init ();
|
2013-03-30 17:54:50 +00:00
|
|
|
|
2019-01-28 02:24:29 +00:00
|
|
|
uri = ges_test_file_uri ("test-properties.xges");
|
2013-03-30 17:54:50 +00:00
|
|
|
project = ges_project_new (uri);
|
2019-04-09 12:58:24 +00:00
|
|
|
g_free (uri);
|
2013-03-30 17:54:50 +00:00
|
|
|
mainloop = g_main_loop_new (NULL, FALSE);
|
|
|
|
|
|
|
|
/* Connect the signals */
|
|
|
|
g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
|
|
|
|
g_signal_connect (project, "missing-uri", (GCallback) _set_new_uri, NULL);
|
|
|
|
|
|
|
|
/* Now extract a timeline from it */
|
|
|
|
GST_LOG ("Loading project");
|
|
|
|
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
|
|
|
|
|
|
|
|
g_main_loop_run (mainloop);
|
|
|
|
|
|
|
|
GST_LOG ("Test first loading");
|
|
|
|
|
|
|
|
|
2013-09-23 16:40:34 +00:00
|
|
|
_add_properties (timeline);
|
2013-03-30 17:54:50 +00:00
|
|
|
|
2014-10-27 15:51:42 +00:00
|
|
|
uri = ges_test_get_tmp_uri ("test-properties-save.xges");
|
2019-04-09 12:58:24 +00:00
|
|
|
fail_unless (ges_project_save (project, timeline, uri, NULL, TRUE, NULL));
|
2013-03-30 17:54:50 +00:00
|
|
|
gst_object_unref (timeline);
|
|
|
|
gst_object_unref (project);
|
|
|
|
|
|
|
|
project = ges_project_new (uri);
|
2019-04-09 12:58:24 +00:00
|
|
|
g_free (uri);
|
2013-03-30 17:54:50 +00:00
|
|
|
|
|
|
|
ASSERT_OBJECT_REFCOUNT (project, "Our + cache", 2);
|
|
|
|
|
|
|
|
g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
|
|
|
|
|
|
|
|
GST_LOG ("Loading saved project");
|
|
|
|
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
|
|
|
|
fail_unless (GES_IS_TIMELINE (timeline));
|
|
|
|
|
|
|
|
g_main_loop_run (mainloop);
|
|
|
|
|
2013-09-23 16:40:34 +00:00
|
|
|
_check_properties (timeline);
|
2013-03-30 17:54:50 +00:00
|
|
|
|
|
|
|
gst_object_unref (timeline);
|
|
|
|
gst_object_unref (project);
|
|
|
|
|
|
|
|
g_main_loop_unref (mainloop);
|
|
|
|
g_signal_handlers_disconnect_by_func (project, (GCallback) project_loaded_cb,
|
|
|
|
mainloop);
|
|
|
|
g_signal_handlers_disconnect_by_func (project, (GCallback) asset_added_cb,
|
|
|
|
NULL);
|
2019-01-28 02:24:29 +00:00
|
|
|
|
|
|
|
ges_deinit ();
|
2013-03-30 17:54:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GST_END_TEST;
|
|
|
|
|
2012-09-23 00:13:38 +00:00
|
|
|
GST_START_TEST (test_project_load_xges)
|
|
|
|
{
|
|
|
|
gboolean saved;
|
2015-05-18 19:24:25 +00:00
|
|
|
GESProject *loaded_project, *saved_project;
|
2012-09-23 00:13:38 +00:00
|
|
|
GESTimeline *timeline;
|
|
|
|
GESAsset *formatter_asset;
|
2019-01-28 02:24:29 +00:00
|
|
|
gchar *uri;
|
2019-04-09 12:58:24 +00:00
|
|
|
GList *tmp;
|
2019-01-28 02:24:29 +00:00
|
|
|
|
|
|
|
ges_init ();
|
2012-09-23 00:13:38 +00:00
|
|
|
|
2019-01-28 02:24:29 +00:00
|
|
|
uri = ges_test_file_uri ("test-project.xges");
|
2015-05-18 19:24:25 +00:00
|
|
|
loaded_project = ges_project_new (uri);
|
2012-12-29 22:36:07 +00:00
|
|
|
mainloop = g_main_loop_new (NULL, FALSE);
|
2015-05-18 19:24:25 +00:00
|
|
|
fail_unless (GES_IS_PROJECT (loaded_project));
|
2012-09-23 00:13:38 +00:00
|
|
|
|
|
|
|
/* Connect the signals */
|
2015-05-18 19:24:25 +00:00
|
|
|
g_signal_connect (loaded_project, "asset-added", (GCallback) asset_added_cb,
|
|
|
|
NULL);
|
|
|
|
g_signal_connect (loaded_project, "loaded", (GCallback) project_loaded_cb,
|
|
|
|
mainloop);
|
2012-09-23 00:13:38 +00:00
|
|
|
|
|
|
|
/* Make sure we update the project's dummy URL to some actual URL */
|
2015-05-18 19:24:25 +00:00
|
|
|
g_signal_connect (loaded_project, "missing-uri", (GCallback) _set_new_uri,
|
|
|
|
NULL);
|
2012-09-23 00:13:38 +00:00
|
|
|
|
|
|
|
/* Now extract a timeline from it */
|
|
|
|
GST_LOG ("Loading project");
|
2015-05-18 19:24:25 +00:00
|
|
|
timeline =
|
|
|
|
GES_TIMELINE (ges_asset_extract (GES_ASSET (loaded_project), NULL));
|
2012-09-23 00:13:38 +00:00
|
|
|
fail_unless (GES_IS_TIMELINE (timeline));
|
2019-04-09 12:58:24 +00:00
|
|
|
tmp = ges_project_get_loading_assets (loaded_project);
|
|
|
|
assert_equals_int (g_list_length (tmp), 1);
|
|
|
|
g_list_free_full (tmp, g_object_unref);
|
2012-09-23 00:13:38 +00:00
|
|
|
|
|
|
|
g_main_loop_run (mainloop);
|
|
|
|
GST_LOG ("Test first loading");
|
2015-05-18 19:24:25 +00:00
|
|
|
_test_project (loaded_project, timeline);
|
2012-09-23 00:13:38 +00:00
|
|
|
g_free (uri);
|
|
|
|
|
2014-10-27 15:51:42 +00:00
|
|
|
uri = ges_test_get_tmp_uri ("test-project_TMP.xges");
|
2012-09-23 00:13:38 +00:00
|
|
|
formatter_asset = ges_asset_request (GES_TYPE_FORMATTER, "ges", NULL);
|
|
|
|
saved =
|
2015-05-18 19:24:25 +00:00
|
|
|
ges_project_save (loaded_project, timeline, uri, formatter_asset, TRUE,
|
|
|
|
NULL);
|
2012-09-23 00:13:38 +00:00
|
|
|
fail_unless (saved);
|
|
|
|
gst_object_unref (timeline);
|
|
|
|
|
2015-05-18 19:24:25 +00:00
|
|
|
saved_project = ges_project_new (uri);
|
|
|
|
ASSERT_OBJECT_REFCOUNT (saved_project, "Our + cache", 2);
|
|
|
|
g_signal_connect (saved_project, "asset-added", (GCallback) asset_added_cb,
|
|
|
|
NULL);
|
|
|
|
g_signal_connect (saved_project, "loaded", (GCallback) project_loaded_cb,
|
|
|
|
mainloop);
|
2012-09-23 00:13:38 +00:00
|
|
|
|
|
|
|
GST_LOG ("Loading saved project");
|
2015-05-18 19:24:25 +00:00
|
|
|
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (saved_project), NULL));
|
2012-09-23 00:13:38 +00:00
|
|
|
fail_unless (GES_IS_TIMELINE (timeline));
|
|
|
|
g_main_loop_run (mainloop);
|
2015-05-18 19:24:25 +00:00
|
|
|
_test_project (saved_project, timeline);
|
|
|
|
|
|
|
|
fail_unless (ges_meta_container_get_string (GES_META_CONTAINER
|
|
|
|
(loaded_project), GES_META_FORMAT_VERSION));
|
|
|
|
fail_unless_equals_string (ges_meta_container_get_string (GES_META_CONTAINER
|
|
|
|
(loaded_project), GES_META_FORMAT_VERSION),
|
|
|
|
ges_meta_container_get_string (GES_META_CONTAINER (loaded_project),
|
|
|
|
GES_META_FORMAT_VERSION));
|
2012-09-23 00:13:38 +00:00
|
|
|
gst_object_unref (timeline);
|
2015-05-18 19:24:25 +00:00
|
|
|
gst_object_unref (saved_project);
|
|
|
|
gst_object_unref (loaded_project);
|
2012-09-23 00:13:38 +00:00
|
|
|
g_free (uri);
|
|
|
|
|
2015-05-18 19:24:25 +00:00
|
|
|
ASSERT_OBJECT_REFCOUNT (saved_project, "Still 1 ref for asset cache", 1);
|
2012-09-23 00:13:38 +00:00
|
|
|
|
|
|
|
g_main_loop_unref (mainloop);
|
2015-05-18 19:24:25 +00:00
|
|
|
g_signal_handlers_disconnect_by_func (saved_project,
|
|
|
|
(GCallback) project_loaded_cb, mainloop);
|
|
|
|
g_signal_handlers_disconnect_by_func (saved_project,
|
|
|
|
(GCallback) asset_added_cb, NULL);
|
2019-01-28 02:24:29 +00:00
|
|
|
|
|
|
|
ges_deinit ();
|
2012-09-23 00:13:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GST_END_TEST;
|
|
|
|
|
2013-04-24 12:25:20 +00:00
|
|
|
GST_START_TEST (test_project_auto_transition)
|
|
|
|
{
|
2019-04-09 12:58:24 +00:00
|
|
|
GList *layers, *tmp;
|
2013-04-24 12:25:20 +00:00
|
|
|
GESProject *project;
|
|
|
|
GESTimeline *timeline;
|
|
|
|
GESLayer *layer = NULL;
|
|
|
|
GESAsset *formatter_asset;
|
|
|
|
gboolean saved;
|
2019-01-28 02:24:29 +00:00
|
|
|
gchar *tmpuri, *uri;
|
|
|
|
|
|
|
|
ges_init ();
|
2013-04-24 12:25:20 +00:00
|
|
|
|
2019-01-28 02:24:29 +00:00
|
|
|
uri = ges_test_file_uri ("test-auto-transition.xges");
|
2013-04-24 12:25:20 +00:00
|
|
|
project = ges_project_new (uri);
|
|
|
|
mainloop = g_main_loop_new (NULL, FALSE);
|
|
|
|
fail_unless (GES_IS_PROJECT (project));
|
|
|
|
|
|
|
|
/* Connect the signals */
|
|
|
|
g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
|
|
|
|
g_signal_connect (project, "missing-uri", (GCallback) _set_new_uri, NULL);
|
|
|
|
|
|
|
|
/* Now extract a timeline from it */
|
|
|
|
GST_LOG ("Loading project");
|
|
|
|
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
|
|
|
|
|
|
|
|
g_main_loop_run (mainloop);
|
|
|
|
|
|
|
|
/* Check timeline and layers auto-transition, must be FALSE */
|
|
|
|
fail_if (ges_timeline_get_auto_transition (timeline));
|
|
|
|
layers = ges_timeline_get_layers (timeline);
|
2019-04-09 12:58:24 +00:00
|
|
|
for (tmp = layers; tmp; tmp = tmp->next) {
|
|
|
|
layer = tmp->data;
|
2013-04-24 12:25:20 +00:00
|
|
|
fail_if (ges_layer_get_auto_transition (layer));
|
|
|
|
}
|
|
|
|
|
|
|
|
g_list_free_full (layers, gst_object_unref);
|
|
|
|
g_free (uri);
|
|
|
|
|
|
|
|
/* Set timeline and layers auto-transition to TRUE */
|
|
|
|
ges_timeline_set_auto_transition (timeline, TRUE);
|
|
|
|
|
2014-10-27 15:51:42 +00:00
|
|
|
tmpuri = ges_test_get_tmp_uri ("test-auto-transition-save.xges");
|
2013-04-24 12:25:20 +00:00
|
|
|
formatter_asset = ges_asset_request (GES_TYPE_FORMATTER, "ges", NULL);
|
|
|
|
saved =
|
|
|
|
ges_project_save (project, timeline, tmpuri, formatter_asset, TRUE, NULL);
|
|
|
|
fail_unless (saved);
|
|
|
|
|
|
|
|
gst_object_unref (timeline);
|
|
|
|
gst_object_unref (project);
|
|
|
|
|
|
|
|
project = ges_project_new (tmpuri);
|
|
|
|
|
|
|
|
ASSERT_OBJECT_REFCOUNT (project, "Our + cache", 2);
|
|
|
|
|
|
|
|
g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
|
|
|
|
|
|
|
|
GST_LOG ("Loading saved project");
|
|
|
|
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
|
|
|
|
fail_unless (GES_IS_TIMELINE (timeline));
|
|
|
|
|
|
|
|
g_main_loop_run (mainloop);
|
|
|
|
|
|
|
|
/* Check timeline and layers auto-transition, must be TRUE */
|
|
|
|
fail_unless (ges_timeline_get_auto_transition (timeline));
|
|
|
|
layers = ges_timeline_get_layers (timeline);
|
2019-04-09 12:58:24 +00:00
|
|
|
for (tmp = layers; tmp; tmp = tmp->next) {
|
|
|
|
layer = tmp->data;
|
2013-04-24 12:25:20 +00:00
|
|
|
fail_unless (ges_layer_get_auto_transition (layer));
|
|
|
|
}
|
|
|
|
|
|
|
|
g_list_free_full (layers, gst_object_unref);
|
|
|
|
gst_object_unref (timeline);
|
|
|
|
gst_object_unref (project);
|
|
|
|
g_free (tmpuri);
|
|
|
|
|
|
|
|
g_main_loop_unref (mainloop);
|
|
|
|
g_signal_handlers_disconnect_by_func (project, (GCallback) project_loaded_cb,
|
|
|
|
mainloop);
|
|
|
|
g_signal_handlers_disconnect_by_func (project, (GCallback) asset_added_cb,
|
|
|
|
NULL);
|
2019-01-28 02:24:29 +00:00
|
|
|
|
|
|
|
ges_deinit ();
|
2013-04-24 12:25:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GST_END_TEST;
|
|
|
|
|
2012-09-23 00:13:38 +00:00
|
|
|
/* FIXME This test does not pass for some bad reason */
|
|
|
|
#if 0
|
|
|
|
static void
|
|
|
|
project_loaded_now_play_cb (GESProject * project, GESTimeline * timeline)
|
|
|
|
{
|
|
|
|
GstBus *bus;
|
|
|
|
GstMessage *message;
|
|
|
|
gboolean carry_on = TRUE;
|
|
|
|
|
2013-07-01 14:27:54 +00:00
|
|
|
GESPipeline *pipeline = ges_pipeline_new ();
|
2012-09-23 00:13:38 +00:00
|
|
|
|
2014-02-04 09:45:58 +00:00
|
|
|
fail_unless (ges_pipeline_set_timeline (pipeline, timeline));
|
2012-09-23 00:13:38 +00:00
|
|
|
|
|
|
|
bus = gst_element_get_bus (GST_ELEMENT (pipeline));
|
|
|
|
fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
|
|
|
|
GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE);
|
|
|
|
|
|
|
|
GST_DEBUG ("Let's poll the bus");
|
|
|
|
|
|
|
|
while (carry_on) {
|
|
|
|
message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 10);
|
|
|
|
if (message) {
|
|
|
|
GST_ERROR ("GOT MESSAGE: %" GST_PTR_FORMAT, message);
|
|
|
|
switch (GST_MESSAGE_TYPE (message)) {
|
|
|
|
case GST_MESSAGE_EOS:
|
|
|
|
/* we should check if we really finished here */
|
|
|
|
GST_WARNING ("Got an EOS, we did not even start!");
|
|
|
|
carry_on = FALSE;
|
|
|
|
fail_if (TRUE);
|
|
|
|
break;
|
|
|
|
case GST_MESSAGE_SEGMENT_START:
|
|
|
|
case GST_MESSAGE_SEGMENT_DONE:
|
|
|
|
/* We shouldn't see any segement messages, since we didn't do a segment seek */
|
|
|
|
GST_WARNING ("Saw a Segment start/stop");
|
|
|
|
fail_if (TRUE);
|
|
|
|
break;
|
|
|
|
case GST_MESSAGE_ERROR:
|
|
|
|
fail_error_message (message);
|
|
|
|
break;
|
|
|
|
case GST_MESSAGE_ASYNC_DONE:
|
|
|
|
GST_DEBUG ("prerolling done");
|
|
|
|
carry_on = FALSE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
gst_mini_object_unref (GST_MINI_OBJECT (message));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
|
|
|
|
GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
|
|
|
|
gst_object_unref (pipeline);
|
|
|
|
g_main_loop_quit (mainloop);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GST_START_TEST (test_load_xges_and_play)
|
|
|
|
{
|
|
|
|
GESProject *project;
|
|
|
|
GESTimeline *timeline;
|
|
|
|
gchar *uri = ges_test_file_uri ("test-project_TMP.xges");
|
|
|
|
|
|
|
|
project = ges_project_new (uri);
|
|
|
|
fail_unless (GES_IS_PROJECT (project));
|
|
|
|
|
|
|
|
mainloop = g_main_loop_new (NULL, FALSE);
|
|
|
|
/* Connect the signals */
|
|
|
|
g_signal_connect (project, "loaded", (GCallback) project_loaded_now_play_cb,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* Now extract a timeline from it */
|
|
|
|
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
|
|
|
|
fail_unless (GES_IS_TIMELINE (timeline));
|
|
|
|
|
|
|
|
g_main_loop_run (mainloop);
|
|
|
|
|
|
|
|
g_free (uri);
|
|
|
|
gst_object_unref (project);
|
|
|
|
gst_object_unref (timeline);
|
|
|
|
g_main_loop_unref (mainloop);
|
|
|
|
}
|
|
|
|
|
|
|
|
GST_END_TEST;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static Suite *
|
|
|
|
ges_suite (void)
|
|
|
|
{
|
|
|
|
Suite *s = suite_create ("ges-project");
|
|
|
|
TCase *tc_chain = tcase_create ("project");
|
|
|
|
|
|
|
|
suite_add_tcase (s, tc_chain);
|
|
|
|
|
|
|
|
tcase_add_test (tc_chain, test_project_simple);
|
|
|
|
tcase_add_test (tc_chain, test_project_add_assets);
|
|
|
|
tcase_add_test (tc_chain, test_project_load_xges);
|
2013-09-23 16:40:34 +00:00
|
|
|
tcase_add_test (tc_chain, test_project_add_properties);
|
2013-04-24 12:25:20 +00:00
|
|
|
tcase_add_test (tc_chain, test_project_auto_transition);
|
2012-09-23 00:13:38 +00:00
|
|
|
/*tcase_add_test (tc_chain, test_load_xges_and_play); */
|
|
|
|
tcase_add_test (tc_chain, test_project_unexistant_effect);
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2013-05-28 02:10:03 +00:00
|
|
|
GST_CHECK_MAIN (ges);
|