00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <string.h>
00041 #include <math.h>
00042
00043 #include "ogg_utils.h"
00044
00045 static void splt_ogg_submit_headers_to_stream(ogg_stream_state *stream, splt_ogg_state *oggstate);
00046 static char *splt_ogg_trackstring(int number, int *error);
00047 static void splt_ogg_v_comment(splt_state *state, vorbis_comment *vc, char *artist,
00048 char *album, char *title, char *tracknum, char *date, char *genre, char *comment,
00049 int *error);
00050 static void delete_all_non_null_tags(vorbis_comment *vc,
00051 const char *artist, const char *album, const char *title,
00052 const char *tracknum, const char *date, const char *genre,
00053 const char *comment, int *error);
00054
00055 long splt_ogg_get_blocksize(splt_ogg_state *oggstate, vorbis_info *vi, ogg_packet *op)
00056 {
00057
00058 int this = vorbis_packet_blocksize(vi, op);
00059 int ret = (this + oggstate->prevW)/4;
00060
00061 oggstate->prevW = this;
00062
00063 return ret;
00064 }
00065
00066 ogg_int64_t splt_ogg_compute_first_granulepos(splt_state *state, splt_ogg_state *oggstate, ogg_packet *packet, int bs)
00067 {
00068 ogg_int64_t first_granpos = 0;
00069
00070 if (packet->granulepos >= 0)
00071 {
00072
00073
00074
00075
00076 if ((packet->granulepos > oggstate->total_blocksize + bs) &&
00077 (oggstate->total_blocksize > 0) &&
00078 !packet->e_o_s &&
00079 (oggstate->first_granpos == 0))
00080 {
00081 first_granpos = packet->granulepos;
00082 oggstate->first_granpos = first_granpos;
00083 splt_c_put_info_message_to_client(state,
00084 _(" warning: unexpected position in ogg vorbis stream - split from 0.0 to EOF to fix.\n"));
00085 }
00086
00087 oggstate->total_blocksize = packet->granulepos;
00088 }
00089 else if (oggstate->total_blocksize == -1)
00090 {
00091 oggstate->total_blocksize = 0;
00092 }
00093 else {
00094 oggstate->total_blocksize += bs;
00095
00096
00097 }
00098
00099 return first_granpos;
00100 }
00101
00102 int splt_ogg_update_sync(splt_state *state, ogg_sync_state *sync_in, FILE *f, int *error)
00103 {
00104 char *buffer = ogg_sync_buffer(sync_in, SPLT_OGG_BUFSIZE);
00105 if (!buffer)
00106 {
00107 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00108 return -1;
00109 }
00110 int bytes = fread(buffer,1,SPLT_OGG_BUFSIZE,f);
00111
00112 if (ogg_sync_wrote(sync_in, bytes) != 0)
00113 {
00114 splt_e_set_error_data(state, splt_t_get_filename_to_split(state));
00115 *error = SPLT_ERROR_INVALID;
00116 return -1;
00117 }
00118
00119 return bytes;
00120 }
00121
00122 splt_v_packet *splt_ogg_clone_packet(ogg_packet *packet, int *error)
00123 {
00124 splt_v_packet *p = NULL;
00125
00126 p = malloc(sizeof(splt_v_packet));
00127 if (!p)
00128 {
00129 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00130 return p;
00131 }
00132
00133 p->length = packet->bytes;
00134 p->packet = malloc(p->length);
00135 if (! p->packet)
00136 {
00137 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00138 free(p);
00139 p = NULL;
00140 return p;
00141 }
00142 memcpy(p->packet, packet->packet, p->length);
00143
00144 return p;
00145 }
00146
00147 void splt_ogg_free_packet(splt_v_packet **p)
00148 {
00149 if (!p || !*p)
00150 {
00151 return;
00152 }
00153
00154 if ((*p)->packet)
00155 {
00156 free((*p)->packet);
00157 (*p)->packet = NULL;
00158 }
00159
00160 free(*p);
00161 *p = NULL;
00162 }
00163
00164 void splt_ogg_free_oggstate_headers(splt_ogg_state *oggstate)
00165 {
00166 if (!oggstate->headers)
00167 {
00168 return;
00169 }
00170
00171 int i = 0;
00172 for (i = 0;i < TOTAL_HEADER_PACKETS; i++)
00173 {
00174 splt_ogg_free_packet(&oggstate->headers[i]);
00175 }
00176
00177 free(oggstate->headers);
00178 oggstate->headers = NULL;
00179 }
00180
00181
00182 int splt_ogg_write_pages_to_file(splt_state *state, ogg_stream_state *stream,
00183 FILE *file, int flush, int *error, const char *output_fname)
00184 {
00185 ogg_page page;
00186
00187 if (flush)
00188 {
00189 while (ogg_stream_flush(stream, &page))
00190 {
00191 if (splt_io_fwrite(state, page.header, 1, page.header_len, file) < page.header_len)
00192 {
00193 goto write_error;
00194 }
00195 if (splt_io_fwrite(state, page.body, 1, page.body_len, file) < page.body_len)
00196 {
00197 goto write_error;
00198 }
00199 }
00200 }
00201 else
00202 {
00203 while (ogg_stream_pageout(stream, &page))
00204 {
00205 if (splt_io_fwrite(state, page.header,1,page.header_len, file) < page.header_len)
00206 {
00207 goto write_error;
00208 }
00209 if (splt_io_fwrite(state, page.body,1,page.body_len, file) < page.body_len)
00210 {
00211 goto write_error;
00212 }
00213 }
00214 }
00215
00216 return 0;
00217
00218 write_error:
00219 splt_e_set_error_data(state, output_fname);
00220 *error = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
00221 return -1;
00222 }
00223
00224 int splt_ogg_write_header_packets(splt_state *state, splt_ogg_state *oggstate,
00225 ogg_stream_state *stream_out, const char *output_fname, int *error)
00226 {
00227 splt_ogg_submit_headers_to_stream(stream_out, oggstate);
00228 return splt_ogg_write_pages_to_file(state, stream_out, oggstate->out, 1,
00229 error, output_fname);
00230 }
00231
00232 void splt_ogg_set_tags_in_headers(splt_ogg_state *oggstate, int *error)
00233 {
00234 ogg_packet header_comm;
00235 vorbis_commentheader_out(&oggstate->vc, &header_comm);
00236 splt_ogg_free_packet(&oggstate->headers[1]);
00237 oggstate->headers[1] = splt_ogg_clone_packet(&header_comm, error);
00238 ogg_packet_clear(&header_comm);
00239
00240 splt_ogg_free_vorbis_comment(&oggstate->vc, oggstate->cloned_vorbis_comment);
00241 oggstate->cloned_vorbis_comment = 2;
00242 }
00243
00244 vorbis_comment *splt_ogg_clone_vorbis_comment(vorbis_comment *comment)
00245 {
00246 vorbis_comment *cloned_comment = malloc(sizeof(vorbis_comment));
00247 if (cloned_comment == NULL)
00248 {
00249 return NULL;
00250 }
00251 memset(cloned_comment, 0x0, sizeof(vorbis_comment));
00252
00253 vorbis_comment_init(cloned_comment);
00254
00255 int err = splt_su_copy(comment->vendor, &cloned_comment->vendor);
00256 if (err < 0)
00257 {
00258 free(cloned_comment);
00259 return NULL;
00260 }
00261
00262 long number_of_comments = comment->comments;
00263 cloned_comment->comments = number_of_comments;
00264
00265 if (number_of_comments <= 0)
00266 {
00267 cloned_comment->comment_lengths = NULL;
00268 cloned_comment->user_comments = NULL;
00269 return cloned_comment;
00270 }
00271
00272 cloned_comment->comment_lengths = malloc(sizeof(int) * number_of_comments);
00273 if (cloned_comment->comment_lengths == NULL)
00274 {
00275 splt_ogg_free_vorbis_comment(cloned_comment, SPLT_TRUE);
00276 free(cloned_comment);
00277 return NULL;
00278 }
00279 memset(cloned_comment->comment_lengths, 0x0, sizeof(int) * number_of_comments);
00280
00281 cloned_comment->user_comments = malloc(sizeof(char *) * number_of_comments);
00282 if (cloned_comment->user_comments == NULL)
00283 {
00284 splt_ogg_free_vorbis_comment(cloned_comment, SPLT_TRUE);
00285 free(cloned_comment);
00286 return NULL;
00287 }
00288 memset(cloned_comment->user_comments, 0x0, sizeof(char *) * number_of_comments);
00289
00290 int i = 0;
00291 for (i = 0;i < number_of_comments; i++)
00292 {
00293 int err = splt_su_copy(comment->user_comments[i], &cloned_comment->user_comments[i]);
00294 if (err < 0)
00295 {
00296 splt_ogg_free_vorbis_comment(cloned_comment, SPLT_TRUE);
00297 free(cloned_comment);
00298 return NULL;
00299 }
00300 cloned_comment->comment_lengths[i] = comment->comment_lengths[i];
00301 }
00302
00303 return cloned_comment;
00304 }
00305
00306 void splt_ogg_put_tags(splt_state *state, int *error)
00307 {
00308 splt_d_print_debug(state,"Setting ogg tags ...\n");
00309
00310 splt_ogg_state *oggstate = state->codec;
00311
00312 splt_ogg_free_vorbis_comment(&oggstate->vc, oggstate->cloned_vorbis_comment);
00313 oggstate->cloned_vorbis_comment = 2;
00314
00315 if (splt_o_get_int_option(state, SPLT_OPT_TAGS) == SPLT_NO_TAGS)
00316 {
00317 return;
00318 }
00319
00320 splt_tags *tags = splt_tu_get_current_tags(state);
00321 if (!tags)
00322 {
00323 return;
00324 }
00325
00326 char *track_string = splt_ogg_trackstring(tags->track, error);
00327 if (*error < 0) { return; }
00328
00329 char *artist_or_performer = splt_tu_get_artist_or_performer_ptr(tags);
00330
00331 vorbis_comment *original_vc =
00332 (vorbis_comment *) splt_tu_get_original_tags_data(state);
00333
00334 if (tags->set_original_tags && original_vc)
00335 {
00336 vorbis_comment *cloned_vc = splt_ogg_clone_vorbis_comment(original_vc);
00337 if (cloned_vc == NULL)
00338 {
00339 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00340 goto error;
00341 }
00342
00343 oggstate->vc = *cloned_vc;
00344 free(cloned_vc);
00345 oggstate->cloned_vorbis_comment = SPLT_TRUE;
00346 }
00347 else {
00348 vorbis_comment_init(&oggstate->vc);
00349 oggstate->cloned_vorbis_comment = SPLT_FALSE;
00350 }
00351
00352 splt_ogg_v_comment(state, &oggstate->vc,
00353 artist_or_performer, tags->album, tags->title, track_string,
00354 tags->year, tags->genre, tags->comment, error);
00355
00356 error:
00357 free(track_string);
00358 track_string = NULL;
00359 }
00360
00361 void splt_ogg_free_vorbis_comment(vorbis_comment *vc, short cloned_vorbis_comment)
00362 {
00363 if (!vc || cloned_vorbis_comment == 2)
00364 {
00365 return;
00366 }
00367
00368 vorbis_comment *comment = vc;
00369
00370 if (!cloned_vorbis_comment)
00371 {
00372 vorbis_comment_clear(comment);
00373 return;
00374 }
00375
00376 long i = 0;
00377 for (i = 0;i < comment->comments; i++)
00378 {
00379 if (comment->user_comments[i])
00380 {
00381 free(comment->user_comments[i]);
00382 comment->user_comments[i] = NULL;
00383 }
00384 }
00385
00386 if (comment->user_comments)
00387 {
00388 free(comment->user_comments);
00389 comment->user_comments = NULL;
00390 }
00391
00392 if (comment->comment_lengths)
00393 {
00394 free(comment->comment_lengths);
00395 comment->comment_lengths = NULL;
00396 }
00397
00398 if (comment->vendor)
00399 {
00400 free(comment->vendor);
00401 comment->vendor = NULL;
00402 }
00403 }
00404
00405
00406
00407
00408 static void splt_ogg_v_comment(splt_state *state, vorbis_comment *vc, char *artist,
00409 char *album, char *title, char *tracknum, char *date, char *genre, char *comment,
00410 int *error)
00411 {
00412 if (splt_o_get_int_option(state, SPLT_OPT_TAGS) == SPLT_TAGS_ORIGINAL_FILE &&
00413 state->original_tags.tags.tags_version == 0)
00414 {
00415 return;
00416 }
00417
00418 delete_all_non_null_tags(vc, artist, album, title, tracknum, date, genre, comment, error);
00419
00420 if (title != NULL) { vorbis_comment_add_tag(vc, SPLT_OGG_TITLE, title); }
00421 if (artist != NULL) { vorbis_comment_add_tag(vc, SPLT_OGG_ARTIST, artist); }
00422 if (album != NULL) { vorbis_comment_add_tag(vc, SPLT_OGG_ALBUM, album); }
00423 if (date != NULL && strlen(date) > 0) { vorbis_comment_add_tag(vc, SPLT_OGG_DATE, date); }
00424 if (genre != NULL) { vorbis_comment_add_tag(vc, SPLT_OGG_GENRE, genre); }
00425 if (tracknum != NULL) { vorbis_comment_add_tag(vc, SPLT_OGG_TRACKNUMBER, tracknum); }
00426 if (comment != NULL) { vorbis_comment_add_tag(vc, SPLT_OGG_COMMENT, comment); }
00427 }
00428
00429 static void add_tag_and_equal(const char *tag_name, const char *value, splt_array *to_delete,
00430 int *error)
00431 {
00432 if (value == NULL) { return; }
00433
00434 size_t size = strlen(tag_name) + 2;
00435 char *tag_and_equal = malloc(size);
00436 if (tag_and_equal == NULL)
00437 {
00438 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00439 return;
00440 }
00441 snprintf(tag_and_equal, size, "%s=", tag_name);
00442
00443 int err = splt_array_append(to_delete, tag_and_equal);
00444 if (err == -1)
00445 {
00446 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00447 }
00448 }
00449
00450 static splt_array *build_tag_and_equal_to_delete(const char *artist,
00451 const char *album, const char *title, const char *tracknum,
00452 const char *date, const char *genre, const char *comment, int *error)
00453 {
00454 splt_array *to_delete = splt_array_new();
00455
00456 add_tag_and_equal(SPLT_OGG_TITLE, title, to_delete, error);
00457 if (*error < 0) { goto error; }
00458 add_tag_and_equal(SPLT_OGG_ARTIST, artist, to_delete, error);
00459 if (*error < 0) { goto error; }
00460 add_tag_and_equal(SPLT_OGG_ALBUM, album, to_delete, error);
00461 if (*error < 0) { goto error; }
00462 if (date != NULL && strlen(date) > 0) { add_tag_and_equal(SPLT_OGG_DATE, date, to_delete, error); }
00463 if (*error < 0) { goto error; }
00464 add_tag_and_equal(SPLT_OGG_GENRE, genre, to_delete, error);
00465 if (*error < 0) { goto error; }
00466 add_tag_and_equal(SPLT_OGG_TRACKNUMBER, tracknum, to_delete, error);
00467 if (*error < 0) { goto error; }
00468 add_tag_and_equal(SPLT_OGG_COMMENT, comment, to_delete, error);
00469 if (*error < 0) { goto error; }
00470
00471 return to_delete;
00472
00473 error:
00474 splt_array_free(&to_delete);
00475 return NULL;
00476 }
00477
00478 static void delete_all_non_null_tags(vorbis_comment *vc,
00479 const char *artist, const char *album, const char *title,
00480 const char *tracknum, const char *date, const char *genre,
00481 const char *comment, int *error)
00482 {
00483 char *vendor_backup = NULL;
00484 splt_array *tag_and_equal_to_delete = NULL;
00485 splt_array *comments = NULL;
00486 long i = 0, j = 0;
00487
00488 tag_and_equal_to_delete =
00489 build_tag_and_equal_to_delete(artist, album, title, tracknum, date, genre, comment, error);
00490 if (*error < 0) { return; }
00491
00492 comments = splt_array_new();
00493 if (comments == NULL) { goto end; }
00494
00495 for (i = 0;i < vc->comments; i++)
00496 {
00497 short keep_comment = SPLT_TRUE;
00498
00499 long number_of_tags_to_delete = splt_array_get_number_of_elements(tag_and_equal_to_delete);
00500 for (j = 0;j < number_of_tags_to_delete; j++)
00501 {
00502 char *tag_and_equal = (char *) splt_array_get(tag_and_equal_to_delete, j);
00503
00504 if (strncasecmp(vc->user_comments[i],
00505 tag_and_equal, strlen(tag_and_equal)) == 0)
00506 {
00507 keep_comment = SPLT_FALSE;
00508 break;
00509 }
00510 }
00511
00512 if (keep_comment)
00513 {
00514 char *user_comment = NULL;
00515 int err = splt_su_append(&user_comment,
00516 vc->user_comments[i], vc->comment_lengths[i], NULL);
00517 if (err < 0) { *error = err; goto end; }
00518 err = splt_array_append(comments, user_comment);
00519 if (err == -1) { *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY; goto end; }
00520 }
00521 }
00522
00523 int err = splt_su_copy(vc->vendor, &vendor_backup);
00524 if (err < 0) { *error = err; goto end; }
00525
00526 vorbis_comment_clear(vc);
00527
00528 long tags_to_keep = splt_array_get_number_of_elements(comments);
00529 for (i = 0;i < tags_to_keep; i++)
00530 {
00531 char *user_comment = splt_array_get(comments, i);
00532 vorbis_comment_add(vc, user_comment);
00533 free(user_comment);
00534 user_comment = NULL;
00535 }
00536
00537 if (vendor_backup)
00538 {
00539 splt_su_set(&vc->vendor, vendor_backup, strlen(vendor_backup), NULL);
00540 }
00541
00542 end:
00543 if (vendor_backup)
00544 {
00545 free(vendor_backup);
00546 vendor_backup = NULL;
00547 }
00548
00549 splt_array_free(&comments);
00550
00551 long number_of_tags_to_delete = splt_array_get_number_of_elements(tag_and_equal_to_delete);
00552 for (j = 0;j < number_of_tags_to_delete; j++)
00553 {
00554 char *tag_and_equal = (char *) splt_array_get(tag_and_equal_to_delete, j);
00555 if (tag_and_equal) { free(tag_and_equal); }
00556 }
00557 splt_array_free(&tag_and_equal_to_delete);
00558 }
00559
00560 static void splt_ogg_submit_headers_to_stream(ogg_stream_state *stream,
00561 splt_ogg_state *oggstate)
00562 {
00563 int i;
00564 for(i = 0;i < TOTAL_HEADER_PACKETS;i++)
00565 {
00566 ogg_packet p;
00567 p.bytes = oggstate->headers[i]->length;
00568 p.packet = oggstate->headers[i]->packet;
00569 p.b_o_s = ((i==0)?1:0);
00570 p.e_o_s = 0;
00571 p.granulepos=0;
00572
00573 ogg_stream_packetin(stream, &p);
00574 }
00575 }
00576
00577 static char *splt_ogg_trackstring(int number, int *error)
00578 {
00579 char *track = NULL;
00580
00581 if (number > 0)
00582 {
00583 int len = 0, i;
00584 len = ((int) (log10((double) (number)))) + 1;
00585
00586 if ((track = malloc(len + 1))==NULL)
00587 {
00588 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00589 return NULL;
00590 }
00591 memset(track, 0, len + 1);
00592 for (i=len-1; i >= 0; i--)
00593 {
00594 track[i] = ((number%10) | 0x30);
00595 number /= 10;
00596 }
00597 }
00598
00599 return track;
00600 }
00601