3 * unit test for cddabasesrc
5 * Copyright (C) <2005> Tim-Philipp Müller <tim centricular net>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 * - test different modes (when seeking to tracks in track mode, buffer
25 * timestamps should start from 0, when seeking to tracks in disc mode,
26 * buffer timestamps should increment, etc.)
35 #include <gst/check/gstcheck.h>
36 #include <gst/check/gstbufferstraw.h>
38 #include <gst/cdda/gstcddabasesrc.h>
41 #define CD_FRAMESIZE_RAW 2352
43 #define GST_TYPE_CD_FOO_SRC (gst_cd_foo_src_get_type())
44 #define GST_CD_FOO_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CD_FOO_SRC,GstCdFooSrc))
45 #define GST_CD_FOO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CD_FOO_SRC,GstCdFooSrcClass))
46 #define GST_IS_CD_FOO_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CD_FOO_SRC))
47 #define GST_IS_CD_FOO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CD_FOO_SRC))
48 #define GST_CD_FOO_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CDDA_BASAE_SRC, GstCdFooSrcClass))
50 typedef struct _GstCdFooSrc GstCdFooSrc;
51 typedef struct _GstCdFooSrcClass GstCdFooSrcClass;
54 /* Neue Heimat (CD 2) */
55 static GstCddaBaseSrcTrack nh_cd2_tracks[] = {
56 {TRUE, 1, 0, 20664, NULL,},
57 {TRUE, 2, 20665, 52377, NULL,},
58 {TRUE, 3, 52378, 84100, NULL,},
59 {TRUE, 4, 84101, 105401, NULL,},
60 {TRUE, 5, 105402, 123060, NULL,},
61 {TRUE, 6, 123061, 146497, NULL,},
62 {TRUE, 7, 146498, 175693, NULL,},
63 {TRUE, 8, 175694, 203272, NULL,},
64 {TRUE, 9, 203273, 217909, NULL,},
65 {TRUE, 10, 217910, 240938, NULL,},
66 {TRUE, 11, 240939, 256169, NULL,},
67 {TRUE, 12, 256170, 282237, NULL,},
68 {TRUE, 13, 282238, 307606, NULL,},
69 {TRUE, 14, 307607, 337245, NULL,}
72 /* Offspring - Smash */
73 static GstCddaBaseSrcTrack offspring_tracks[] = {
74 {TRUE, 1, 0, 1924, NULL,},
75 {TRUE, 2, 1925, 12947, NULL,},
76 {TRUE, 3, 12948, 29739, NULL,},
77 {TRUE, 4, 29740, 47202, NULL,},
78 {TRUE, 5, 47203, 63134, NULL,},
79 {TRUE, 6, 63135, 77954, NULL,},
80 {TRUE, 7, 77955, 92789, NULL,},
81 {TRUE, 8, 92790, 112127, NULL,},
82 {TRUE, 9, 112128, 124372, NULL,},
83 {TRUE, 10, 124373, 133574, NULL,},
84 {TRUE, 11, 133575, 143484, NULL,},
85 {TRUE, 12, 143485, 149279, NULL,},
86 {TRUE, 13, 149280, 162357, NULL,},
87 {TRUE, 14, 162358, 210372, NULL,}
90 /* this matches the sample TOC from the DiscIDCalculation
91 * page in the Musicbrainz wiki. It's a tricky one because
92 * it's got a data track as well. */
93 static GstCddaBaseSrcTrack mb_sample_tracks[] = {
94 {TRUE, 1, 0, 18640, NULL,},
95 {TRUE, 2, 18641, 34666, NULL,},
96 {TRUE, 3, 34667, 56349, NULL,},
97 {TRUE, 4, 56350, 77005, NULL,},
98 {TRUE, 5, 77006, 106093, NULL,},
99 {TRUE, 6, 106094, 125728, NULL,},
100 {TRUE, 7, 125729, 149784, NULL,},
101 {TRUE, 8, 149785, 168884, NULL,},
102 {TRUE, 9, 168885, 185909, NULL,},
103 {TRUE, 10, 185910, 205828, NULL,},
104 {TRUE, 11, 205829, 230141, NULL,},
105 {TRUE, 12, 230142, 246658, NULL,},
106 {TRUE, 13, 246659, 265613, NULL,},
107 {TRUE, 14, 265614, 289478, NULL,},
108 {FALSE, 15, 289479, 325731, NULL,}
111 /* Nicola Conte - Other Directions (also
112 * tricky due to the extra data track) */
113 static GstCddaBaseSrcTrack nconte_odir_tracks[] = {
114 {TRUE, 1, 0, 17852, NULL,},
115 {TRUE, 2, 17853, 39956, NULL,},
116 {TRUE, 3, 39957, 68449, NULL,},
117 {TRUE, 4, 68450, 88725, NULL,},
118 {TRUE, 5, 88726, 106413, NULL,},
119 {TRUE, 6, 106414, 131966, NULL,},
120 {TRUE, 7, 131967, 152372, NULL,},
121 {TRUE, 8, 152373, 168602, NULL,},
122 {TRUE, 9, 168603, 190348, NULL,},
123 {TRUE, 10, 190349, 209044, NULL,},
124 {TRUE, 11, 209045, 235586, NULL,},
125 {TRUE, 12, 235587, 253830, NULL,},
126 {TRUE, 13, 253831, 272213, NULL,},
127 {FALSE, 14, 272214, 332849, NULL,}
130 /* Pink Martini - Sympathique (11 track version) */
131 static GstCddaBaseSrcTrack pm_symp_tracks[] = {
132 {TRUE, 1, 0, 21667, NULL,},
133 {TRUE, 2, 21668, 49576, NULL,},
134 {TRUE, 3, 49577, 62397, NULL,},
135 {TRUE, 4, 62398, 81087, NULL,},
136 {TRUE, 5, 81088, 106595, NULL,},
137 {TRUE, 6, 106596, 122012, NULL,},
138 {TRUE, 7, 122013, 138469, NULL,},
139 {TRUE, 8, 138470, 157306, NULL,},
140 {TRUE, 9, 157307, 179635, NULL,},
141 {TRUE, 10, 179636, 203673, NULL,},
142 {TRUE, 11, 203674, 213645, NULL,}
145 #define NUM_TEST_DISCS 5
149 GstCddaBaseSrcTrack *tracks;
152 const gchar *musicbrainz_discid;
155 /* FIXME: now we just need to find out how to treat
156 * data tracks for the cddb id calculation .... */
157 static struct _test_disc test_discs[NUM_TEST_DISCS] = {
158 {nh_cd2_tracks, G_N_ELEMENTS (nh_cd2_tracks), 0xae11900e,
160 {mb_sample_tracks, G_N_ELEMENTS (mb_sample_tracks), 0x00000000,
161 "MUtMmKN402WPj3_VFsgUelxpc8U-"},
162 {offspring_tracks, G_N_ELEMENTS (offspring_tracks), 0xc20af40e,
163 "ahg7JUcfR3vCYBphSDIogOOWrr0-"},
164 {nconte_odir_tracks, G_N_ELEMENTS (nconte_odir_tracks), 0x00000000,
165 /* hKx_PejjG47X161ND_Sh0HyqaS0- according to libmusicbrainz, but that's
166 * wrong according to the wiki docs (or not?) (neither discid is listed) */
167 "fboaOQtfqwENv8WyXa9tRyvyUbQ-"},
168 {pm_symp_tracks, G_N_ELEMENTS (pm_symp_tracks), 0xa00b200b,
169 "iP0DOLdr4vt_IfKSIXoRUR.q_Wc-"}
174 GstCddaBaseSrc cddabasesrc;
176 struct _test_disc *cur_test;
180 struct _GstCdFooSrcClass
182 GstCddaBaseSrcClass parent_class;
185 GType gst_cd_foo_src_get_type (void);
186 GST_BOILERPLATE (GstCdFooSrc, gst_cd_foo_src, GstCddaBaseSrc,
187 GST_TYPE_CDDA_BASE_SRC);
189 static GstBuffer *gst_cd_foo_src_read_sector (GstCddaBaseSrc * src,
191 static gboolean gst_cd_foo_src_open (GstCddaBaseSrc * src,
192 const gchar * device);
193 static void gst_cd_foo_src_close (GstCddaBaseSrc * src);
195 static const GstElementDetails cdfoo_details =
196 GST_ELEMENT_DETAILS ("CD Audio (cdda) Source, FooBar",
198 "Read audio from CD",
199 "Foo Bar <foo@bar.com>");
202 gst_cd_foo_src_base_init (gpointer g_class)
204 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
206 gst_element_class_set_details (element_class, &cdfoo_details);
210 gst_cd_foo_src_init (GstCdFooSrc * src, GstCdFooSrcClass * klass)
216 gst_cd_foo_src_class_init (GstCdFooSrcClass * klass)
218 GstCddaBaseSrcClass *cddabasesrc_class = GST_CDDA_BASE_SRC_CLASS (klass);
220 cddabasesrc_class->open = gst_cd_foo_src_open;
221 cddabasesrc_class->close = gst_cd_foo_src_close;
222 cddabasesrc_class->read_sector = gst_cd_foo_src_read_sector;
226 gst_cd_foo_src_open (GstCddaBaseSrc * cddabasesrc, const gchar * device)
228 GstCddaBaseSrcTrack *tracks;
232 src = GST_CD_FOO_SRC (cddabasesrc);
234 /* if this fails, the test is wrong */
235 g_assert (src->cur_disc < NUM_TEST_DISCS);
237 src->cur_test = &test_discs[src->cur_disc];
240 tracks = src->cur_test->tracks;
241 for (i = 0; i < src->cur_test->num_tracks; ++i) {
242 gst_cdda_base_src_add_track (GST_CDDA_BASE_SRC (src), &tracks[i]);
249 gst_cd_foo_src_close (GstCddaBaseSrc * cddabasesrc)
251 GstCdFooSrc *src = GST_CD_FOO_SRC (cddabasesrc);
253 if (src->cur_test->cddb_discid != 0) {
254 g_assert (cddabasesrc->discid == src->cur_test->cddb_discid);
257 if (src->cur_test->musicbrainz_discid != NULL) {
258 g_assert (g_str_equal (cddabasesrc->mb_discid,
259 src->cur_test->musicbrainz_discid));
264 gst_cd_foo_src_read_sector (GstCddaBaseSrc * cddabasesrc, gint sector)
268 buf = gst_buffer_new_and_alloc (CD_FRAMESIZE_RAW);
269 memset (GST_BUFFER_DATA (buf), 0, CD_FRAMESIZE_RAW);
274 static inline gboolean
275 tag_list_has_tag (GstTagList * list, const gchar * tag, GType type)
277 const GValue *val = gst_tag_list_get_value_index (list, tag, 0);
280 GST_LOG ("no tag '%s' in taglist %" GST_PTR_FORMAT, tag, list);
284 if (!G_VALUE_HOLDS (val, type)) {
285 GST_LOG ("tag '%s' in taglist %" GST_PTR_FORMAT " is not of type %s",
286 tag, list, g_type_name (type));
294 test_uri_parse (const gchar * uri, const gchar * device, gint track)
297 gchar *set_device = NULL;
300 foosrc = gst_element_factory_make ("cdfoosrc", "cdfoosrc");
301 fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc), uri) == TRUE,
302 "couldn't set uri %s", uri);
303 g_object_get (foosrc, "device", &set_device, "track", &set_track, NULL);
304 fail_unless (set_device != NULL);
305 fail_unless (strcmp (set_device, device) == 0,
306 "device set was %s, expected %s", set_device, device);
307 fail_unless (set_track == track, "track set was %d, expected %d", set_track,
310 gst_object_unref (foosrc);
313 GST_START_TEST (test_discid_calculations)
315 GstElement *foosrc, *pipeline, *sink;
318 fail_unless (gst_element_register (NULL, "cdfoosrc", GST_RANK_SECONDARY,
319 GST_TYPE_CD_FOO_SRC));
321 pipeline = gst_pipeline_new ("pipeline");
323 sink = gst_element_factory_make ("fakesink", "sink");
324 fail_unless (sink != NULL, "couldn't create fakesink");
326 foosrc = gst_element_factory_make ("cdfoosrc", "cdfoosrc");
327 fail_unless (foosrc != NULL, "couldn't create cdfoosrc");
329 gst_bin_add (GST_BIN (pipeline), foosrc);
330 gst_bin_add (GST_BIN (pipeline), sink);
331 fail_unless (gst_element_link (foosrc, sink));
333 for (i = 0; i < G_N_ELEMENTS (test_discs); ++i) {
334 GstTagList *tags = NULL;
337 GST_LOG ("Testing disc layout %u ...", i);
338 GST_CD_FOO_SRC (foosrc)->cur_disc = i;
339 gst_element_set_state (pipeline, GST_STATE_PLAYING);
342 gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipeline),
343 GST_CLOCK_TIME_NONE, GST_MESSAGE_TAG);
344 gst_message_parse_tag (msg, &tags);
345 fail_unless (tags != NULL);
346 fail_unless (tag_list_has_tag (tags, "track-count", G_TYPE_UINT));
347 fail_unless (tag_list_has_tag (tags, "track-number", G_TYPE_UINT));
348 fail_unless (tag_list_has_tag (tags, "duration", G_TYPE_UINT64));
349 fail_unless (tag_list_has_tag (tags, "discid", G_TYPE_STRING));
350 fail_unless (tag_list_has_tag (tags, "discid-full", G_TYPE_STRING));
351 fail_unless (tag_list_has_tag (tags, "musicbrainz-discid", G_TYPE_STRING));
352 fail_unless (tag_list_has_tag (tags, "musicbrainz-discid-full",
354 gst_tag_list_free (tags);
355 gst_message_unref (msg);
358 gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipeline),
359 GST_CLOCK_TIME_NONE, GST_MESSAGE_ASYNC_DONE);
360 gst_message_unref (msg);
362 gst_element_set_state (pipeline, GST_STATE_NULL);
365 gst_object_unref (pipeline);
367 gst_task_cleanup_all ();
372 GST_START_TEST (test_buffer_timestamps)
374 GstElement *foosrc, *pipeline, *fakesink;
375 GstClockTime prev_ts, prev_duration, ts;
379 fail_unless (gst_element_register (NULL, "cdfoosrc", GST_RANK_SECONDARY,
380 GST_TYPE_CD_FOO_SRC));
382 pipeline = gst_pipeline_new ("pipeline");
383 foosrc = gst_element_factory_make ("cdfoosrc", "cdfoosrc");
384 fakesink = gst_element_factory_make ("fakesink", "fakesink");
385 gst_bin_add_many (GST_BIN (pipeline), foosrc, fakesink, NULL);
386 fail_unless (gst_element_link (foosrc, fakesink));
387 sinkpad = gst_element_get_static_pad (fakesink, "sink");
389 GST_CD_FOO_SRC (foosrc)->cur_disc = 0;
391 gst_buffer_straw_start_pipeline (pipeline, sinkpad);
393 prev_ts = GST_CLOCK_TIME_NONE;
394 prev_duration = GST_CLOCK_TIME_NONE;
396 for (i = 0; i < 100; ++i) {
399 buf = gst_buffer_straw_get_buffer (pipeline, sinkpad);
400 GST_LOG ("buffer, ts=%" GST_TIME_FORMAT ", dur=%" GST_TIME_FORMAT,
401 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
402 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
403 ts = GST_BUFFER_TIMESTAMP (buf);
404 fail_unless (GST_CLOCK_TIME_IS_VALID (ts));
405 fail_unless (GST_BUFFER_DURATION_IS_VALID (buf));
407 fail_unless (GST_CLOCK_TIME_IS_VALID (prev_ts));
408 fail_unless (GST_CLOCK_TIME_IS_VALID (prev_duration));
409 fail_unless ((prev_ts + prev_duration) == ts);
412 prev_duration = GST_BUFFER_DURATION (buf);
413 gst_buffer_unref (buf);
416 gst_buffer_straw_stop_pipeline (pipeline, sinkpad);
418 gst_task_cleanup_all ();
419 gst_object_unref (pipeline);
420 gst_object_unref (sinkpad);
425 GST_START_TEST (test_uri_parsing)
429 fail_unless (gst_element_register (NULL, "cdfoosrc", GST_RANK_SECONDARY,
430 GST_TYPE_CD_FOO_SRC));
433 foosrc = gst_element_factory_make ("cdfoosrc", "cdfoosrc");
434 fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc),
436 fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc),
437 "cddaq://") == FALSE);
440 test_uri_parse ("cdda://", "/dev/cdrom", 1);
441 test_uri_parse ("cdda://2", "/dev/cdrom", 2);
442 test_uri_parse ("cdda://47", "/dev/cdrom", 47);
443 fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc),
444 "cdda://-1") == FALSE);
445 fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc),
446 "cdda://what") == FALSE);
448 /* cdda://device#track */
449 test_uri_parse ("cdda:///dev/hdb#1", "/dev/hdb", 1);
450 test_uri_parse ("cdda://anything#8", "anything", 8);
451 fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc),
452 "cdda:///dev/hdb#nonsense") == FALSE);
453 fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc),
454 "cdda:///dev/hdb#-2") == FALSE);
456 /* cdda://track#device (device should be ignored - FIXME 0.11) */
457 test_uri_parse ("cdda://8#/dev/hdb", "/dev/cdrom", 8);
459 gst_object_unref (foosrc);
464 GST_START_TEST (test_properties)
470 fail_unless (gst_element_register (NULL, "cdfoosrc", GST_RANK_SECONDARY,
471 GST_TYPE_CD_FOO_SRC));
473 foosrc = gst_element_factory_make ("cdfoosrc", "cdfoosrc");
475 g_object_set (foosrc, "device", "/dev/cdrom", NULL);
476 g_object_get (foosrc, "device", &device, "track", &track, NULL);
477 fail_unless (g_str_equal (device, "/dev/cdrom"));
478 fail_unless_equals_int (track, 1);
481 g_object_set (foosrc, "device", "/dev/cdrom1", "track", 17, NULL);
482 g_object_get (foosrc, "device", &device, "track", &track, NULL);
483 fail_unless (g_str_equal (device, "/dev/cdrom1"));
484 fail_unless_equals_int (track, 17);
487 g_object_set (foosrc, "track", 17, "device", "/dev/cdrom1", NULL);
488 g_object_get (foosrc, "device", &device, "track", &track, NULL);
489 fail_unless (g_str_equal (device, "/dev/cdrom1"));
490 fail_unless_equals_int (track, 17);
493 g_object_set (foosrc, "track", 12, NULL);
494 g_object_get (foosrc, "device", &device, "track", &track, NULL);
495 fail_unless (g_str_equal (device, "/dev/cdrom1"));
496 fail_unless_equals_int (track, 12);
499 gst_object_unref (foosrc);
505 cddabasesrc_suite (void)
507 Suite *s = suite_create ("cddabasesrc");
508 TCase *tc_chain = tcase_create ("general");
510 suite_add_tcase (s, tc_chain);
511 tcase_add_test (tc_chain, test_discid_calculations);
512 tcase_add_test (tc_chain, test_buffer_timestamps);
513 tcase_add_test (tc_chain, test_uri_parsing);
514 tcase_add_test (tc_chain, test_properties);
519 GST_CHECK_MAIN (cddabasesrc)