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 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <ctype.h>
00035 #include <assert.h>
00036 #include <pthread.h>
00037 #include <libxml2/libxml/xmlreader.h>
00038
00039 #include "control.h"
00040 #include "nccparser.h"
00041 #include "ncxparser.h"
00042 #include "nccsmilparser.h"
00043 #include "ncxsmilparser.h"
00044 #include "report.h"
00045 #include "common.h"
00046 #include "snprintf/snprintf.h"
00047
00048
00049
00050 #ifdef LIBXML_READER_ENABLED
00051
00052
00053
00054
00055
00056
00057
00062 static void initAuthorNode (struct AuthorNode* authorNode);
00063
00068 static void initSmilNode (struct SmilNode* smilNode);
00069
00074 static void initNode (struct Node* node);
00075
00081 static void flushSmilNodes (struct DaisyData *daisydata);
00082
00088 static void flushNodes (struct DaisyData *daisydata);
00089
00095 static void flushBookInfo (struct DaisyData *daisydata);
00096
00097
00098
00099
00100
00101
00102
00107 static void initAuthorNode (struct AuthorNode* authorNode)
00108 {
00109 authorNode->name = NULL;
00110 authorNode->audiofilename = NULL;
00111 authorNode->audioStartPos = NULL;
00112 authorNode->audioStopPos = NULL;
00113 authorNode->image = NULL;
00114 authorNode->next = NULL;
00115 authorNode->prev = NULL;
00116 }
00117
00122 static void initSmilNode (struct SmilNode* smilNode)
00123 {
00124 smilNode->id = NULL;
00125 smilNode->anchor = NULL;
00126 smilNode->fragmentIdentifier = NULL;
00127 smilNode->textpassage = NULL;
00128 smilNode->audiofilename = NULL;
00129 smilNode->audioStartPos = NULL;
00130 smilNode->audioStopPos = NULL;
00131 smilNode->image = NULL;
00132 smilNode->header = NULL;
00133 smilNode->next = NULL;
00134 smilNode->prev = NULL;
00135 smilNode->optional = 0;
00136 }
00137
00142 static void initNode (struct Node* node)
00143 {
00144 node->audiofilename = NULL;
00145 node->audioStartPos = NULL;
00146 node->audioStopPos = NULL;
00147 node->fragmentIdentifier = NULL;
00148 node->image = NULL;
00149 node->textPassage = NULL;
00150 node->textfilename = NULL;
00151 node->next = NULL;
00152 node->prev = NULL;
00153 }
00154
00160 static void flushSmilNodes (struct DaisyData *daisydata)
00161 {
00162 struct SmilNode *tmp = daisydata->smilHead->next;
00163 while (tmp != daisydata->smilTail)
00164 {
00165 if (tmp->id != NULL)
00166 free (tmp->id);
00167 if (tmp->anchor != NULL)
00168 free (tmp->anchor);
00169 if (tmp->fragmentIdentifier != NULL)
00170 free (tmp->fragmentIdentifier);
00171 if (tmp->header != NULL)
00172 free (tmp->header);
00173 tmp = tmp->next;
00174 free (tmp->prev);
00175 }
00176 daisydata->smilHead->next = daisydata->smilTail;
00177 daisydata->smilTail->prev = daisydata->smilHead;
00178 daisydata->smilPos = daisydata->smilHead;
00179 }
00180
00186 static void flushNodes (struct DaisyData *daisydata)
00187 {
00188 struct Node *tmp = daisydata->nodeHead->next;
00189 while (tmp != daisydata->nodeTail)
00190 {
00191 if (tmp->audiofilename != NULL)
00192 free (tmp->audiofilename);
00193 if (tmp->audioStartPos != NULL)
00194 free (tmp->audioStartPos);
00195 if (tmp->audioStopPos != NULL)
00196 free (tmp->audioStopPos);
00197 if (tmp->textPassage != NULL)
00198 free (tmp->textPassage);
00199 tmp = tmp->next;
00200 free (tmp->prev);
00201 }
00202 daisydata->nodeHead->next = daisydata->nodeTail;
00203 daisydata->nodeTail->prev = daisydata->nodeHead;
00204 daisydata->nodePos = daisydata->nodeHead;
00205 }
00206
00212 static void flushBookInfo (struct DaisyData *daisydata)
00213 {
00214 struct AuthorNode *tmp;
00215
00216 if (daisydata->bookInfo->titleText != NULL)
00217 {
00218 free (daisydata->bookInfo->titleText);
00219 daisydata->bookInfo->titleText = NULL;
00220 }
00221 if (daisydata->bookInfo->titleAudiofilename != NULL)
00222 {
00223 free (daisydata->bookInfo->titleAudiofilename);
00224 daisydata->bookInfo->titleAudiofilename = NULL;
00225 }
00226 if (daisydata->bookInfo->titleAudioStartPos != NULL)
00227 {
00228 free (daisydata->bookInfo->titleAudioStartPos);
00229 daisydata->bookInfo->titleAudioStartPos = NULL;
00230 }
00231 if (daisydata->bookInfo->titleAudioStopPos != NULL)
00232 {
00233 free (daisydata->bookInfo->titleAudioStopPos);
00234 daisydata->bookInfo->titleAudioStopPos = NULL;
00235 }
00236 if (daisydata->bookInfo->titleImage != NULL)
00237 {
00238 free (daisydata->bookInfo->titleImage);
00239 daisydata->bookInfo->titleImage = NULL;
00240 }
00241 if (daisydata->bookInfo->totalTime != NULL)
00242 {
00243 free (daisydata->bookInfo->totalTime);
00244 daisydata->bookInfo->totalTime = NULL;
00245 }
00246
00247 tmp = daisydata->authorHead->next;
00248 while (tmp != daisydata->authorTail)
00249 {
00250 if (tmp->name != NULL)
00251 free (tmp->name);
00252 if (tmp->audiofilename != NULL)
00253 free (tmp->audiofilename);
00254 if (tmp->audioStartPos != NULL)
00255 free (tmp->audioStartPos);
00256 if (tmp->audioStopPos != NULL)
00257 free (tmp->audioStopPos);
00258 if (tmp->image != NULL)
00259 free (tmp->image);
00260 tmp = tmp->next;
00261 free (tmp->prev);
00262 }
00263 daisydata->authorHead->next = daisydata->authorTail;
00264 daisydata->authorHead->prev = daisydata->authorHead;
00265 daisydata->bookInfo->author = daisydata->authorHead;
00266 }
00267
00268
00269
00270
00271
00272
00273
00278 struct DaisyData *parseInit (void)
00279 {
00280
00281 struct DaisyData *daisydata = (struct DaisyData *) malloc (sizeof(struct DaisyData));
00282
00283
00284
00285
00286
00287
00288
00289 LIBXML_TEST_VERSION
00290
00291
00292
00293 daisydata->bookInfo = (struct BookInfo *) malloc (sizeof (struct BookInfo));
00294 daisydata->bookInfo->titleText = NULL;
00295 daisydata->bookInfo->titleAudiofilename = NULL;
00296 daisydata->bookInfo->titleAudioStartPos = NULL;
00297 daisydata->bookInfo->titleAudioStopPos = NULL;
00298 daisydata->bookInfo->titleImage = NULL;
00299 daisydata->bookInfo->totalTime = NULL;
00300 daisydata->authorHead = (struct AuthorNode *) malloc (sizeof (struct AuthorNode));
00301 initAuthorNode (daisydata->authorHead);
00302 daisydata->authorTail = (struct AuthorNode *) malloc (sizeof (struct AuthorNode));
00303 initAuthorNode (daisydata->authorTail);
00304 daisydata->authorHead->next = daisydata->authorTail;
00305 daisydata->authorHead->prev = daisydata->authorHead;
00306 daisydata->bookInfo->author = daisydata->authorHead;
00307
00308
00309 daisydata->smilHead = (struct SmilNode *) malloc (sizeof (struct SmilNode));
00310 initSmilNode (daisydata->smilHead);
00311 daisydata->smilTail = (struct SmilNode *) malloc (sizeof (struct SmilNode));
00312 initSmilNode (daisydata->smilTail);
00313 daisydata->smilHead->next = daisydata->smilTail;
00314 daisydata->smilTail->prev = daisydata->smilHead;
00315 daisydata->smilPos = daisydata->smilHead;
00316
00317
00318 daisydata->nodeHead = (struct Node *) malloc (sizeof (struct Node));
00319 initNode (daisydata->nodeHead);
00320 daisydata->nodeTail = (struct Node *) malloc (sizeof (struct Node));
00321 initNode (daisydata->nodeTail);
00322 daisydata->nodeHead->next = daisydata->nodeTail;
00323 daisydata->nodeTail->prev = daisydata->nodeHead;
00324 daisydata->nodePos = daisydata->nodeHead;
00325
00326 return daisydata;
00327 }
00328
00334 void parseTerminate (struct DaisyData *daisydata)
00335 {
00336
00337
00338 flushNodes(daisydata);
00339 free (daisydata->nodeHead);
00340 free (daisydata->nodeTail);
00341
00342
00343 flushSmilNodes(daisydata);
00344 free (daisydata->smilHead);
00345 free (daisydata->smilTail);
00346
00347
00348 flushBookInfo(daisydata);
00349 free (daisydata->authorHead);
00350 free (daisydata->authorTail);
00351 free (daisydata->bookInfo);
00352
00353
00354 free (daisydata);
00355
00356
00357 xmlCleanupParser ();
00358
00359
00360 xmlMemoryDump ();
00361
00362 }
00363
00370 char* removewhitespaces(char* string)
00371 {
00372 unsigned int start = 0;
00373 int end = 0;
00374 int i = 0;
00375 int n = 0;
00376 char* newstring = NULL;
00377
00378
00379 for (start = 0; start < strlen(string); start++)
00380 {
00381 if (string[start] != ' ' && string[start] != '\t' && string[start] != '\n')
00382 break;
00383 }
00384
00385
00386 if (start == strlen(string)) return NULL;
00387
00388
00389 for (end = strlen(string)-1; end >= 0; end--)
00390 {
00391 if (string[end] != ' ' && string[end] != '\t' && string[end] != '\n')
00392 break;
00393 }
00394
00395
00396 newstring = malloc(end-start+2);
00397 for (i = start; i <= end; i++)
00398 {
00399 newstring[n++] = string[i];
00400 }
00401 newstring[n] = '\0';
00402 return newstring;
00403 }
00404
00410 char* tolowercase(const char* string)
00411 {
00412 unsigned int n = 0;
00413 char* newstring = NULL;
00414
00415 newstring = malloc(strlen(string)+1);
00416
00417 for (n = 0; n < strlen(string); n++)
00418 {
00419 newstring[n] = tolower(string[n]);
00420
00421 }
00422 newstring[n] = '\0';
00423 return newstring;
00424 }
00425
00426
00432 char* getTime(char* time)
00433 {
00434 char* tmp, *min, *sec, *frac = NULL;
00435 char* value = (char *) malloc(6);
00436 int minutes = 0, seconds = 0;
00437
00438
00439 tmp = (char *) malloc (strlen (time)+1);
00440 strcpy (tmp, time);
00441
00442 min = strtok (tmp, ":");
00443 minutes = atoi (min);
00444
00445 tmp = strtok (NULL, ":");
00446
00447 sec = strtok (tmp, ".");
00448
00449 seconds = atoi(sec);
00450 seconds = (minutes * 60) + seconds;
00451
00452 frac = strtok (NULL, ".");
00453
00454 snprintf(value, sizeof (value), "%d", seconds);
00455
00456 strcat (value, ".");
00457 strcat (value, frac);
00458 return value;
00459 }
00460
00465 void addNewAuthor (struct DaisyData *daisydata)
00466 {
00467
00468 struct AuthorNode *tmpAuthor = (struct AuthorNode *) malloc (sizeof(struct AuthorNode));
00469
00470
00471 initAuthorNode(tmpAuthor);
00472
00473
00474 if (daisydata->authorHead->next != daisydata->authorTail)
00475 {
00476 tmpAuthor->next = daisydata->authorHead->next;
00477 tmpAuthor->prev = daisydata->authorHead;
00478 daisydata->authorHead->next->prev = tmpAuthor;
00479 daisydata->authorHead->next = tmpAuthor;
00480 }
00481
00482 else
00483 {
00484 daisydata->authorHead->next = tmpAuthor;
00485 daisydata->authorTail->prev = tmpAuthor;
00486 tmpAuthor->next = daisydata->authorTail;
00487 tmpAuthor->prev = daisydata->authorHead;
00488 }
00489 daisydata->bookInfo->author = tmpAuthor;
00490 }
00491
00498 struct SmilNode* addNewSmilNode (struct DaisyData *daisydata)
00499 {
00500 struct SmilNode *tmp;
00501
00502
00503 struct SmilNode *smilNode = (struct SmilNode *) malloc (sizeof(struct SmilNode));
00504
00505
00506 initSmilNode (smilNode);
00507
00508
00509 tmp = daisydata->smilTail->prev;
00510 tmp->next = smilNode;
00511 smilNode->prev = tmp;
00512 smilNode->next = daisydata->smilTail;
00513 daisydata->smilTail->prev = smilNode;
00514
00515 return smilNode;
00516 }
00517
00524 struct Node* addNewNode (struct DaisyData *daisydata)
00525 {
00526 struct Node *tmp;
00527
00528
00529 struct Node *node = (struct Node *) malloc (sizeof(struct Node));
00530
00531
00532 initNode(node);
00533
00534
00535 tmp = daisydata->nodeTail->prev;
00536 tmp->next = node;
00537 node->prev = tmp;
00538 node->next = daisydata->nodeTail;
00539 daisydata->nodeTail->prev = node;
00540
00541 return node;
00542 }
00543
00552 int parse (struct DaisyData *daisydata, char* filename)
00553 {
00554 char buffer[STRLEN];
00555 int i = 0, j = 0, n = 0, ret = 0;
00556 i = (int) strlen(filename);
00557
00558
00559 flushNodes (daisydata);
00560 flushSmilNodes (daisydata);
00561 flushBookInfo (daisydata);
00562
00563
00564 if((filename[i-1] == 'x' && filename[i-2] == 'c' && filename[i-3] == 'n' && filename[i-4] == '.')
00565 || (filename[i-1] == 'X' && filename[i-2] == 'C' && filename[i-3] == 'N' && filename[i-4] == '.'))
00566 {
00567
00568 daisydata->format = 1;
00569
00570 for(i = (int) strlen(filename)-1; i > 0; i--)
00571 {
00572 if(filename[i] == '/')
00573 break;
00574 }
00575
00576 for (j = 0; j <= i; j++)
00577 {
00578 buffer[n++] = filename[j];
00579 }
00580 buffer[n] = '\0';
00581 daisydata->path = (char*) malloc (sizeof (buffer)+1);
00582 assert (daisydata->path != NULL);
00583 strcpy (daisydata->path, buffer);
00584 ret = parseNCX (daisydata, filename);
00585 }
00586
00587 else if((filename[i-1] == 'l' && filename[i-2] == 'm' && filename[i-3] == 't' && filename[i-4] == 'h'
00588 && filename[i-5] == '.' && filename[i-6] == 'c' && filename[i-7] == 'c' && filename[i-8] == 'n' && filename[i-9] == '/')
00589 || (filename[i-1] == 'L' && filename[i-2] == 'M' && filename[i-3] == 'T' && filename[i-4] == 'H'
00590 && filename[i-5] == '.' && filename[i-6] == 'C' && filename[i-7] == 'C' && filename[i-8] == 'N' && filename[i-9] == '/'))
00591 {
00592
00593 daisydata->format = 0;
00594
00595
00596 for (j = 0; j <= (int) strlen(filename)-9; j++)
00597 {
00598 buffer[n++] = filename[j];
00599 }
00600 buffer[n] = '\0';
00601 daisydata->path = (char*) malloc (sizeof (buffer)+1);
00602 assert (daisydata->path != NULL);
00603 strcpy (daisydata->path, buffer);
00604 ret = parseNCC (daisydata, filename);
00605 }
00606 else
00607 {
00608
00609 return -1;
00610 }
00611 return ret;
00612 }
00613
00621 int seek (struct DaisyData *daisydata, int type)
00622 {
00623 int ret = 1;
00624
00625 if (daisydata->smilHead->next == daisydata->smilTail) return 0;
00626
00627 switch (type)
00628 {
00629 case DAISY_SEEK_PREV_PASSAGE:
00630 if (daisydata->nodePos == daisydata->nodeHead || daisydata->nodePos == daisydata->nodeHead->next)
00631 {
00632 if (daisydata->smilPos == daisydata->smilHead)
00633 {
00634 daisydata->smilPos = daisydata->smilHead->next;
00635 flushNodes (daisydata);
00636 if(daisydata->format == 0)
00637 ret = parseNCCSmil(daisydata);
00638 else
00639 ret = parseNCXSmil(daisydata);
00640 if (ret != 1) return ret;
00641 daisydata->nodePos = daisydata->nodeHead->next;
00642 return ret;
00643 }
00644 else if (daisydata->smilPos == daisydata->smilHead->next)
00645 {
00646 daisydata->nodePos = daisydata->nodeHead->next;
00647 return ret;
00648 }
00649 else
00650 {
00651 daisydata->smilPos = daisydata->smilPos->prev;
00652 flushNodes(daisydata);
00653 if(daisydata->format == 0)
00654 ret = parseNCCSmil(daisydata);
00655 else
00656 ret = parseNCXSmil(daisydata);
00657 if (ret != 1) return ret;
00658 daisydata->nodePos = daisydata->nodeTail->prev;
00659 return ret;
00660 }
00661 }
00662 else
00663 {
00664 daisydata->nodePos = daisydata->nodePos->prev;
00665 return ret;
00666 }
00667
00668 case DAISY_SEEK_PREV_CHAPTER:
00669 if (daisydata->smilPos == daisydata->smilHead)
00670 {
00671 daisydata->smilPos = daisydata->smilHead->next;
00672 flushNodes(daisydata);
00673 if(daisydata->format == 0)
00674 ret = parseNCCSmil(daisydata);
00675 else
00676 ret = parseNCXSmil(daisydata);
00677 if (ret != 1) return ret;
00678 daisydata->nodePos = daisydata->nodeHead->next;
00679 return ret;
00680 }
00681 else if (daisydata->smilPos == daisydata->smilHead->next)
00682 {
00683 daisydata->nodePos = daisydata->nodeHead->next;
00684 return ret;
00685 }
00686 else
00687 {
00688 daisydata->smilPos = daisydata->smilPos->prev;
00689 flushNodes(daisydata);
00690 if(daisydata->format == 0)
00691 ret = parseNCCSmil(daisydata);
00692 else
00693 ret = parseNCXSmil(daisydata);
00694 if (ret != 1) return ret;
00695 daisydata->nodePos = daisydata->nodeHead->next;
00696 return ret;
00697 }
00698
00699 case DAISY_SEEK_NEXT_CHAPTER:
00700 if (daisydata->smilPos == daisydata->smilTail)
00701 {
00702 return 0;
00703 }
00704 else if (daisydata->smilPos == daisydata->smilTail->prev)
00705 {
00706 daisydata->smilPos = daisydata->smilTail;
00707 return 0;
00708 }
00709 else {
00710 daisydata->smilPos = daisydata->smilPos->next;
00711 flushNodes(daisydata);
00712 if(daisydata->format == 0)
00713 ret = parseNCCSmil(daisydata);
00714 else
00715 ret = parseNCXSmil(daisydata);
00716 if (ret != 1) return ret;
00717 daisydata->nodePos = daisydata->nodeHead->next;
00718 return ret;
00719 }
00720
00721 case DAISY_SEEK_NEXT_PASSAGE:
00722 if (daisydata->nodePos == daisydata->nodeTail || daisydata->nodePos == daisydata->nodeTail->prev)
00723 {
00724 if (daisydata->smilPos == daisydata->smilTail)
00725 {
00726 daisydata->nodePos = daisydata->nodeTail;
00727 return 0;
00728 }
00729 else if (daisydata->smilPos == daisydata->smilTail->prev)
00730 {
00731 daisydata->smilPos = daisydata->smilTail;
00732 daisydata->nodePos = daisydata->nodeTail;
00733 return 0;
00734 }
00735 else
00736 {
00737 daisydata->smilPos = daisydata->smilPos->next;
00738 flushNodes (daisydata);
00739 if(daisydata->format == 0)
00740 ret = parseNCCSmil(daisydata);
00741 else
00742 ret = parseNCXSmil(daisydata);
00743 if (ret != 1) return ret;
00744 daisydata->nodePos = daisydata->nodeHead->next;
00745 return ret;
00746 }
00747 }
00748 else
00749 {
00750 daisydata->nodePos = daisydata->nodePos->next;
00751 return ret;
00752 }
00753
00754 case DAISY_SEEK_TO_BEGINNING:
00755 if (daisydata->smilPos != daisydata->smilHead->next)
00756 {
00757 daisydata->smilPos = daisydata->smilHead->next;
00758 flushNodes (daisydata);
00759 if(daisydata->format == 0)
00760 ret = parseNCCSmil(daisydata);
00761 else
00762 ret = parseNCXSmil(daisydata);
00763 if (ret != 1) return ret;
00764 }
00765 daisydata->nodePos = daisydata->nodeHead->next;
00766 return ret;
00767
00768 default:
00769 return -1;
00770
00771 }
00772 }
00773
00779 int getSmilPos (struct DaisyData *daisydata)
00780 {
00781 int smilPos = 1;
00782 struct SmilNode *tmpSmil = daisydata->smilHead->next;
00783
00784 if (daisydata->smilPos != daisydata->smilHead && daisydata->smilPos != daisydata->smilTail)
00785 {
00786 while (tmpSmil != daisydata->smilPos && tmpSmil != daisydata->smilTail)
00787 {
00788 smilPos++;
00789 tmpSmil = tmpSmil->next;
00790 }
00791 if (tmpSmil == daisydata->smilTail)
00792 return -1;
00793 } else
00794 return -1;
00795
00796 return smilPos;
00797 }
00798
00804 int getNodePos (struct DaisyData *daisydata)
00805 {
00806 int nodePos = 1;
00807 struct Node *tmpNode = daisydata->nodeHead->next;
00808
00809 if (daisydata->nodePos != daisydata->nodeHead && daisydata->nodePos != daisydata->nodeTail)
00810 {
00811 while (tmpNode != daisydata->nodePos && tmpNode != daisydata->nodeTail)
00812 {
00813 nodePos++;
00814 tmpNode = tmpNode->next;
00815 }
00816 if (tmpNode == daisydata->nodeTail)
00817 return -1;
00818 } else
00819 return -1;
00820
00821 return nodePos;
00822 }
00823
00830 int gotoSmilPosition (struct DaisyData *daisydata, int newSmilPos)
00831 {
00832 int i = 1;
00833 struct SmilNode *tmpSmil = daisydata->smilHead->next;
00834
00835
00836 if (newSmilPos < 1)
00837 return -1;
00838
00839
00840 for (i=1; i<newSmilPos && tmpSmil != daisydata->smilTail; i++)
00841 {
00842 tmpSmil = tmpSmil->next;
00843 }
00844 if (tmpSmil == daisydata->smilTail)
00845 return -1;
00846
00847
00848 daisydata->smilPos = tmpSmil;
00849
00850
00851 flushNodes (daisydata);
00852 if(daisydata->format == 0)
00853 i = parseNCCSmil(daisydata);
00854 else
00855 i = parseNCXSmil(daisydata);
00856 if (i != 1) return i;
00857
00858 return 1;
00859 }
00860
00867 int gotoNodePosition (struct DaisyData *daisydata, int newNodePos)
00868 {
00869 int i = 1;
00870 struct Node *tmpNode = daisydata->nodeHead->next;
00871
00872
00873 if (newNodePos < 1)
00874 return -1;
00875
00876
00877 for (i=1; i<newNodePos && tmpNode != daisydata->nodeTail; i++)
00878 {
00879 tmpNode = tmpNode->next;
00880 }
00881 if (tmpNode == daisydata->nodeTail)
00882 return -1;
00883
00884
00885 daisydata->nodePos = tmpNode;
00886
00887 return 1;
00888 }
00889
00890
00891 #endif