224 gobject_class->get_property = gst_cdda_base_src_get_property; |
221 gobject_class->get_property = gst_cdda_base_src_get_property; |
225 gobject_class->finalize = gst_cdda_base_src_finalize; |
222 gobject_class->finalize = gst_cdda_base_src_finalize; |
226 |
223 |
227 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEVICE, |
224 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEVICE, |
228 g_param_spec_string ("device", "Device", "CD device location", |
225 g_param_spec_string ("device", "Device", "CD device location", |
229 NULL, G_PARAM_READWRITE)); |
226 NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
230 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MODE, |
227 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MODE, |
231 g_param_spec_enum ("mode", "Mode", "Mode", GST_TYPE_CDDA_BASE_SRC_MODE, |
228 g_param_spec_enum ("mode", "Mode", "Mode", GST_TYPE_CDDA_BASE_SRC_MODE, |
232 GST_CDDA_BASE_SRC_MODE_NORMAL, G_PARAM_READWRITE)); |
229 GST_CDDA_BASE_SRC_MODE_NORMAL, |
|
230 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
233 |
231 |
234 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TRACK, |
232 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TRACK, |
235 g_param_spec_uint ("track", "Track", "Track", 1, 99, 1, |
233 g_param_spec_uint ("track", "Track", "Track", 1, 99, 1, |
236 G_PARAM_READWRITE)); |
234 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
237 |
235 |
238 #if 0 |
236 #if 0 |
239 /* Do we really need this toc adjustment stuff as properties? does the user |
237 /* Do we really need this toc adjustment stuff as properties? does the user |
240 * have a chance to set it in practice, e.g. when using sound-juicer, rb, |
238 * have a chance to set it in practice, e.g. when using sound-juicer, rb, |
241 * totem, whatever? Shouldn't we rather use environment variables |
239 * totem, whatever? Shouldn't we rather use environment variables |
242 * for this? (tpm) */ |
240 * for this? (tpm) */ |
243 |
241 |
244 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TOC_OFFSET, |
242 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TOC_OFFSET, |
245 g_param_spec_int ("toc-offset", "Table of contents offset", |
243 g_param_spec_int ("toc-offset", "Table of contents offset", |
246 "Add <n> sectors to the values reported", G_MININT, G_MAXINT, 0, |
244 "Add <n> sectors to the values reported", G_MININT, G_MAXINT, 0, |
247 G_PARAM_READWRITE)); |
245 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
248 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TOC_BIAS, |
246 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TOC_BIAS, |
249 g_param_spec_boolean ("toc-bias", "Table of contents bias", |
247 g_param_spec_boolean ("toc-bias", "Table of contents bias", |
250 "Assume that the beginning offset of track 1 as reported in the TOC " |
248 "Assume that the beginning offset of track 1 as reported in the TOC " |
251 "will be addressed as LBA 0. Necessary for some Toshiba drives to " |
249 "will be addressed as LBA 0. Necessary for some Toshiba drives to " |
252 "get track boundaries", FALSE, G_PARAM_READWRITE)); |
250 "get track boundaries", FALSE, |
|
251 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
253 #endif |
252 #endif |
254 |
253 |
255 element_class->set_index = GST_DEBUG_FUNCPTR (gst_cdda_base_src_set_index); |
254 element_class->set_index = GST_DEBUG_FUNCPTR (gst_cdda_base_src_set_index); |
256 element_class->get_index = GST_DEBUG_FUNCPTR (gst_cdda_base_src_get_index); |
255 element_class->get_index = GST_DEBUG_FUNCPTR (gst_cdda_base_src_get_index); |
257 |
256 |
1089 n /= 10; |
1087 n /= 10; |
1090 } |
1088 } |
1091 return ret; |
1089 return ret; |
1092 } |
1090 } |
1093 |
1091 |
1094 #include "base64.h" |
|
1095 #include "sha1.h" |
|
1096 |
|
1097 static void |
1092 static void |
1098 gst_cddabasesrc_calculate_musicbrainz_discid (GstCddaBaseSrc * src) |
1093 gst_cddabasesrc_calculate_musicbrainz_discid (GstCddaBaseSrc * src) |
1099 { |
1094 { |
1100 GString *s; |
1095 GString *s; |
1101 SHA_INFO sha; |
1096 GChecksum *sha; |
1102 guchar digest[20], *ptr; |
1097 guchar digest[20]; |
|
1098 gchar *ptr; |
1103 gchar tmp[9]; |
1099 gchar tmp[9]; |
1104 gulong i; |
1100 gulong i; |
1105 guint leadout_sector; |
1101 guint leadout_sector; |
|
1102 gsize digest_len; |
1106 |
1103 |
1107 s = g_string_new (NULL); |
1104 s = g_string_new (NULL); |
1108 |
1105 |
1109 leadout_sector = src->tracks[src->num_tracks - 1].end + 1 + CD_MSF_OFFSET; |
1106 leadout_sector = src->tracks[src->num_tracks - 1].end + 1 + CD_MSF_OFFSET; |
1110 |
1107 |
1111 /* generate SHA digest */ |
1108 /* generate SHA digest */ |
1112 sha_init (&sha); |
1109 sha = g_checksum_new (G_CHECKSUM_SHA1); |
1113 g_snprintf (tmp, sizeof (tmp), "%02X", src->tracks[0].num); |
1110 g_snprintf (tmp, sizeof (tmp), "%02X", src->tracks[0].num); |
1114 g_string_append_printf (s, "%02X", src->tracks[0].num); |
1111 g_string_append_printf (s, "%02X", src->tracks[0].num); |
1115 sha_update (&sha, (SHA_BYTE *) tmp, 2); |
1112 g_checksum_update (sha, (guchar *) tmp, 2); |
1116 |
1113 |
1117 g_snprintf (tmp, sizeof (tmp), "%02X", src->tracks[src->num_tracks - 1].num); |
1114 g_snprintf (tmp, sizeof (tmp), "%02X", src->tracks[src->num_tracks - 1].num); |
1118 g_string_append_printf (s, " %02X", src->tracks[src->num_tracks - 1].num); |
1115 g_string_append_printf (s, " %02X", src->tracks[src->num_tracks - 1].num); |
1119 sha_update (&sha, (SHA_BYTE *) tmp, 2); |
1116 g_checksum_update (sha, (guchar *) tmp, 2); |
1120 |
1117 |
1121 g_snprintf (tmp, sizeof (tmp), "%08X", leadout_sector); |
1118 g_snprintf (tmp, sizeof (tmp), "%08X", leadout_sector); |
1122 g_string_append_printf (s, " %08X", leadout_sector); |
1119 g_string_append_printf (s, " %08X", leadout_sector); |
1123 sha_update (&sha, (SHA_BYTE *) tmp, 8); |
1120 g_checksum_update (sha, (guchar *) tmp, 8); |
1124 |
1121 |
1125 for (i = 0; i < 99; i++) { |
1122 for (i = 0; i < 99; i++) { |
1126 if (i < src->num_tracks) { |
1123 if (i < src->num_tracks) { |
1127 guint frame_offset = src->tracks[i].start + CD_MSF_OFFSET; |
1124 guint frame_offset = src->tracks[i].start + CD_MSF_OFFSET; |
1128 |
1125 |
1129 g_snprintf (tmp, sizeof (tmp), "%08X", frame_offset); |
1126 g_snprintf (tmp, sizeof (tmp), "%08X", frame_offset); |
1130 g_string_append_printf (s, " %08X", frame_offset); |
1127 g_string_append_printf (s, " %08X", frame_offset); |
1131 sha_update (&sha, (SHA_BYTE *) tmp, 8); |
1128 g_checksum_update (sha, (guchar *) tmp, 8); |
1132 } else { |
1129 } else { |
1133 sha_update (&sha, (SHA_BYTE *) "00000000", 8); |
1130 g_checksum_update (sha, (guchar *) "00000000", 8); |
1134 } |
1131 } |
1135 } |
1132 } |
1136 sha_final (digest, &sha); |
1133 digest_len = 20; |
|
1134 g_checksum_get_digest (sha, (guint8 *) & digest, &digest_len); |
1137 |
1135 |
1138 /* re-encode to base64 */ |
1136 /* re-encode to base64 */ |
1139 ptr = rfc822_binary (digest, 20, &i); |
1137 ptr = g_base64_encode (digest, digest_len); |
|
1138 g_checksum_free (sha); |
|
1139 i = strlen (ptr); |
1140 |
1140 |
1141 g_assert (i < sizeof (src->mb_discid) + 1); |
1141 g_assert (i < sizeof (src->mb_discid) + 1); |
1142 memcpy (src->mb_discid, ptr, i); |
1142 memcpy (src->mb_discid, ptr, i); |
1143 src->mb_discid[i] = '\0'; |
1143 src->mb_discid[i] = '\0'; |
1144 free (ptr); |
1144 free (ptr); |
|
1145 |
|
1146 /* Replace '/', '+' and '=' by '_', '.' and '-' as specified on |
|
1147 * http://musicbrainz.org/doc/DiscIDCalculation |
|
1148 */ |
|
1149 for (ptr = src->mb_discid; *ptr != '\0'; ptr++) { |
|
1150 if (*ptr == '/') |
|
1151 *ptr = '_'; |
|
1152 else if (*ptr == '+') |
|
1153 *ptr = '.'; |
|
1154 else if (*ptr == '=') |
|
1155 *ptr = '-'; |
|
1156 } |
1145 |
1157 |
1146 GST_DEBUG_OBJECT (src, "musicbrainz-discid = %s", src->mb_discid); |
1158 GST_DEBUG_OBJECT (src, "musicbrainz-discid = %s", src->mb_discid); |
1147 GST_DEBUG_OBJECT (src, "musicbrainz-discid-full = %s", s->str); |
1159 GST_DEBUG_OBJECT (src, "musicbrainz-discid-full = %s", s->str); |
1148 |
1160 |
1149 gst_tag_list_add (src->tags, GST_TAG_MERGE_REPLACE, |
1161 gst_tag_list_add (src->tags, GST_TAG_MERGE_REPLACE, |
1266 num_sectors = src->tracks[i].end - src->tracks[i].start + 1; |
1278 num_sectors = src->tracks[i].end - src->tracks[i].start + 1; |
1267 gst_cdda_base_src_convert (src, sector_format, num_sectors, |
1279 gst_cdda_base_src_convert (src, sector_format, num_sectors, |
1268 GST_FORMAT_TIME, &duration); |
1280 GST_FORMAT_TIME, &duration); |
1269 |
1281 |
1270 gst_tag_list_add (src->tracks[i].tags, |
1282 gst_tag_list_add (src->tracks[i].tags, |
1271 GST_TAG_MERGE_REPLACE_ALL, |
1283 GST_TAG_MERGE_REPLACE, |
1272 GST_TAG_TRACK_NUMBER, i + 1, |
1284 GST_TAG_TRACK_NUMBER, i + 1, |
1273 GST_TAG_TRACK_COUNT, src->num_tracks, GST_TAG_DURATION, duration, NULL); |
1285 GST_TAG_TRACK_COUNT, src->num_tracks, GST_TAG_DURATION, duration, NULL); |
1274 } |
1286 } |
1275 |
1287 |
1276 /* now fill in per-album tags and include each track's tags |
1288 /* now fill in per-album tags and include each track's tags |
1280 /* /////////////////////////////// FIXME should we rather insert num_tracks |
1292 /* /////////////////////////////// FIXME should we rather insert num_tracks |
1281 * tags by the name of 'track-tags' and have the caller use |
1293 * tags by the name of 'track-tags' and have the caller use |
1282 * gst_tag_list_get_value_index() rather than use tag names incl. |
1294 * gst_tag_list_get_value_index() rather than use tag names incl. |
1283 * the track number ?? *//////////////////////////////////////// |
1295 * the track number ?? *//////////////////////////////////////// |
1284 |
1296 |
1285 gst_tag_list_add (src->tags, GST_TAG_MERGE_REPLACE_ALL, |
1297 gst_tag_list_add (src->tags, GST_TAG_MERGE_REPLACE, |
1286 GST_TAG_TRACK_COUNT, src->num_tracks, NULL); |
1298 GST_TAG_TRACK_COUNT, src->num_tracks, NULL); |
1287 #if 0 |
1299 #if 0 |
1288 for (i = 0; i < src->num_tracks; ++i) { |
1300 for (i = 0; i < src->num_tracks; ++i) { |
1289 gst_tag_list_add (src->tags, GST_TAG_MERGE_APPEND, |
1301 gst_tag_list_add (src->tags, GST_TAG_MERGE_APPEND, |
1290 GST_TAG_CDDA_TRACK_TAGS, src->tracks[i].tags, NULL); |
1302 GST_TAG_CDDA_TRACK_TAGS, src->tracks[i].tags, NULL); |