1 /*
2 gnauralXML.c
3 code for managing XML data-styled data in the Gnaural context
4 Depends on:
5 main.h
6 gnauralXML.h
7 gnauralnet.h
8
9 Copyright (C) 20100608 Bret Logan
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <string.h> //needed for strcpy
30 #include "main.h"
31 #include "gnauralnet.h"
32 #include "ScheduleXML.h"
33 #include "gnauralXML.h"
34 #include "voiceGUI.h"
35 #include "gnauralRecentMenu.h"
36
37 int gxml_ParserXML_VoiceCount = 0; //this is a *true* count of Voices (as opposed to listed count in file) taken from pre-reads of the XML file; has priority
38 int gxml_ParserXML_EntryCount = 0; //this is a *true* count of Entries (as opposed to listed count in file) taken from pre-reads of the XML file; has priority
39 int gxml_GnauralFile = 0; //just a way to know internally if a file being opened isn't a valid Gnaurl2 file
40
41 /////////////////////////////////////////////////////
42 //Writes a Gnaural format XML file
gxml_XMLWriteFile(char * filename)43 void gxml_XMLWriteFile (char *filename)
44 {
45 //First count how many DPs to copy. One reason to do this first is to be sure
46 //there really are selected DPs before throwing away the old buffer:
47 SG_DataPoint *curDP;
48 int DP_count = 0;
49 int voice_count = 0;
50 SG_Voice *curVoice = SG_FirstVoice;
51
52 while (curVoice != NULL)
53 {
54 curDP = curVoice->FirstDataPoint;
55 ++voice_count;
56 while (curDP != NULL)
57 {
58 ++DP_count;
59 //all list loops need this:
60 curDP = curDP->NextDataPoint;
61 }
62 curVoice = curVoice->NextVoice;
63 }
64
65 SG_DBGOUT_INT ("WriteFileXML: DataPoints to copy:", DP_count);
66 SG_DBGOUT_INT ("WriteFileXML: Total Voices:", voice_count);
67
68 //if there are no selected DPs, don't do anything:
69 if (DP_count < 1)
70 return;
71
72 //prepare file access:
73 FILE *stream;
74
75 if ((stream = fopen (filename, "w")) == NULL)
76 {
77 SG_ERROUT ("Failed to open file for writing!");
78 return;
79 }
80
81 gchar strbuf[G_ASCII_DTOSTR_BUF_SIZE];
82
83 const int strsize = sizeof (strbuf);
84
85 fprintf (stream, "<?xml version=\"1.0\"?>\n"); //added 20101010 to keep browswers from seeing datafiles as webpages
86 fprintf (stream, "<!-- See http://gnaural.sourceforge.net -->\n");
87 fprintf (stream, "<schedule>\n");
88 fprintf (stream, "<gnauralfile_version>%s</gnauralfile_version>\n", gxml_VERSION_GNAURAL_XMLFILE); //always keep this first
89 fprintf (stream, "<gnaural_version>%s</gnaural_version>\n", VERSION);
90 time_t curtime;
91
92 struct tm *loctime;
93
94 curtime = time (NULL);
95 loctime = (struct tm *) localtime (&curtime);
96 fprintf (stream, "<date>%s</date>\n", asctime (loctime));
97 fprintf (stream, "<title>%s</title>\n",
98 main_Info_Title == NULL ? "[none]" : main_Info_Title);
99 fprintf (stream, "<schedule_description>%s</schedule_description>\n",
100 main_Info_Description == NULL ? "[none]" : main_Info_Description);
101 fprintf (stream, "<author>%s</author>\n",
102 main_Info_Author == NULL ? "[none]" : main_Info_Author);
103 fprintf (stream, "<totaltime>%s</totaltime>\n",
104 g_ascii_formatd (strbuf, strsize, "%g", SG_TotalScheduleDuration));
105 fprintf (stream, "<voicecount>%d</voicecount>\n", voice_count);
106 fprintf (stream, "<totalentrycount>%d</totalentrycount>\n", DP_count);
107 fprintf (stream, "<loops>%d</loops>\n", BB_Loops);
108 fprintf (stream, "<overallvolume_left>%s</overallvolume_left>\n",
109 g_ascii_formatd (strbuf, strsize, "%g", BB_VolumeOverall_left));
110 fprintf (stream, "<overallvolume_right>%s</overallvolume_right>\n",
111 g_ascii_formatd (strbuf, strsize, "%g", BB_VolumeOverall_right));
112 fprintf (stream, "<stereoswap>%d</stereoswap>\n", BB_StereoSwap);
113 fprintf (stream, "<graphview>%d</graphview>\n", SG_GraphType);
114
115 //#define GXML_MAKEARRAYS
116 #ifdef GXML_MAKEARRAYS
117 //this is for making a schedule internal:
118 FILE *array = fopen ("VoiceArray.h", "w");
119 #endif
120
121 // Now put all the selected DPs in to the copy buffer:
122 DP_count = 0;
123 voice_count = 0;
124 curVoice = SG_FirstVoice;
125 while (curVoice != NULL)
126 {
127 //first count the number of DP's in this voice:
128 curDP = curVoice->FirstDataPoint;
129 int dpcount_local = 0;
130
131 while (curDP != NULL)
132 {
133 ++dpcount_local;
134 //all list loops need this:
135 curDP = curDP->NextDataPoint;
136 }
137
138 #ifdef GXML_MAKEARRAYS
139 fprintf (array,
140 "/* First three Type, Count, Mono,\nrest are Dur, VolL, VolR, Beat, Base */\n");
141 fprintf (array, "static final float BB_ScheduleArray%d[] = {\n%d,%d,%d",
142 voice_count, curVoice->type, dpcount_local, curVoice->mono);
143 #endif
144
145 //now do it again with that info:
146 curDP = curVoice->FirstDataPoint;
147 fprintf (stream, "<voice>\n");
148 fprintf (stream, "<description>%s</description>\n",
149 curVoice->description == NULL ? "[none]" : curVoice->description);
150 fprintf (stream, "<id>%d</id>\n", voice_count);
151 fprintf (stream, "<type>%d</type>\n", curVoice->type);
152 fprintf (stream, "<voice_state>%d</voice_state>\n", curVoice->state);
153 fprintf (stream, "<voice_hide>%d</voice_hide>\n", curVoice->hide);
154 fprintf (stream, "<voice_mute>%d</voice_mute>\n", curVoice->mute);
155 fprintf (stream, "<voice_mono>%d</voice_mono>\n", curVoice->mono);
156 fprintf (stream, "<entrycount>%d</entrycount>\n", dpcount_local);
157 fprintf (stream, "<entries>\n");
158
159 while (curDP != NULL)
160 {
161 #ifdef GXML_MAKEARRAYS
162 fprintf (array, ",\n%gf,%gf,%gf,%gf,%gf",
163 curDP->duration,
164 curDP->volume_left,
165 curDP->volume_right, curDP->beatfreq, curDP->basefreq);
166 #endif
167
168 //NEW STYLE FORMAT
169 //START entry writing:
170 fprintf (stream, "<entry parent=\"%d\" duration=\"%s\" ", voice_count,
171 g_ascii_formatd (strbuf, strsize, "%g", curDP->duration));
172 fprintf (stream, "volume_left=\"%s\" ",
173 g_ascii_formatd (strbuf, strsize, "%g", curDP->volume_left));
174 fprintf (stream, "volume_right=\"%s\" ",
175 g_ascii_formatd (strbuf, strsize, "%g", curDP->volume_right));
176 fprintf (stream, "beatfreq=\"%s\" ",
177 g_ascii_formatd (strbuf, strsize, "%g", curDP->beatfreq));
178 fprintf (stream, "basefreq=\"%s\" state=\"%d\"/>\n",
179 g_ascii_formatd (strbuf, strsize, "%g", curDP->basefreq),
180 curDP->state);
181 //END entry writing:
182 //END NEW STYLE FORMAT
183 ++DP_count;
184 //all list loops need this:
185 curDP = curDP->NextDataPoint;
186 }
187 curVoice = curVoice->NextVoice;
188 fprintf (stream, "</entries>\n");
189 fprintf (stream, "</voice>\n");
190 ++voice_count;
191
192 #ifdef GXML_MAKEARRAYS
193 fprintf (array, "};\n\n");
194 #endif
195
196 }
197 fprintf (stream, "</schedule>\n");
198 fclose (stream);
199 SG_DBGOUT_INT ("Wrote DataPoints:", DP_count);
200
201 #ifdef GXML_MAKEARRAYS
202 fclose (array);
203 #endif
204 }
205
206 ///////////////////////////////////////////////
207 //this is only called by main_XMLParser; don't call yerself.
208 //point of this is to keep Event data separate, since it is the
209 //most numerous and thus should probably be done with Attributes
gxml_XMLEventDataParser(const gchar * DataType,const gchar * Value,const int internal_EntryCount)210 int gxml_XMLEventDataParser (const gchar * DataType,
211 const gchar * Value,
212 const int internal_EntryCount)
213 {
214 //==START OF EVENT PROPERTIES
215 if (!strcmp (DataType, "parent"))
216 {
217 //must add 1, because 0 would look to Restore() like a NULL pointer:
218 SG_UndoRedo.DPdata[internal_EntryCount].parent =
219 (void *) (atoi (Value) + 1);
220 SG_DBGOUT_PNT ("parent:", SG_UndoRedo.DPdata[internal_EntryCount].parent);
221 return 0;
222 }
223
224 if (!strcmp (DataType, "duration"))
225 {
226 SG_UndoRedo.DPdata[internal_EntryCount].duration =
227 g_ascii_strtod (Value, NULL);
228 SG_DBGOUT_FLT ("duration:",
229 SG_UndoRedo.DPdata[internal_EntryCount].duration);
230 return 0;
231 }
232
233 if (!strcmp (DataType, "volume_left"))
234 {
235 SG_UndoRedo.DPdata[internal_EntryCount].volume_left =
236 g_ascii_strtod (Value, NULL);
237 SG_DBGOUT_FLT ("volume_left:",
238 SG_UndoRedo.DPdata[internal_EntryCount].volume_left);
239 return 0;
240 }
241
242 if (!strcmp (DataType, "volume_right"))
243 {
244 SG_UndoRedo.DPdata[internal_EntryCount].volume_right =
245 g_ascii_strtod (Value, NULL);
246 SG_DBGOUT_FLT ("volume_right:",
247 SG_UndoRedo.DPdata[internal_EntryCount].volume_right);
248 return 0;
249 }
250
251 if (!strcmp (DataType, "beatfreq"))
252 {
253 SG_UndoRedo.DPdata[internal_EntryCount].beatfreq =
254 g_ascii_strtod (Value, NULL);
255 SG_DBGOUT_FLT ("beatfreq:",
256 SG_UndoRedo.DPdata[internal_EntryCount].beatfreq);
257 return 0;
258 }
259
260 if (!strcmp (DataType, "basefreq"))
261 {
262 SG_UndoRedo.DPdata[internal_EntryCount].basefreq =
263 g_ascii_strtod (Value, NULL);
264 SG_DBGOUT_FLT ("basefreq:",
265 SG_UndoRedo.DPdata[internal_EntryCount].basefreq);
266 return 0;
267 }
268
269 if (!strcmp (DataType, "state"))
270 {
271 SG_UndoRedo.DPdata[internal_EntryCount].state = atoi (Value);
272 SG_DBGOUT_INT ("state:", SG_UndoRedo.DPdata[internal_EntryCount].state);
273 return 0;
274 }
275 //==END OF EVENT PROPERTIES
276 //=========================
277 return 1;
278 }
279
280 ///////////////////////////////////////////////
281 //this is only called by main_XMLReadFile; don't call
gxml_XMLParser(const gchar * CurrentElement,const gchar * Attribute,const gchar * Value)282 void gxml_XMLParser (const gchar * CurrentElement, //this must always be a valid string
283 const gchar * Attribute, //beware: this will equal NULL if there are none
284 const gchar * Value)
285 { //beware: this will equal NULL to announce end of CurrnetElement
286 //Essential to do things in this order:
287 // 1) Check if this call represents the end of CurrentElement; if so, increment counter vars then return
288 // 2) See if there are Attributes with this CurrentElement; if so, assign them, then return;
289 // 3) If I got here, just slog through Elements and Values to assign to vars
290 static int internal_EntryCount = 0;
291
292 static int internal_VoiceCount = 0;
293
294 //See if this is the end of CurrentElement:
295 if (Value == NULL)
296 {
297 if (0 == strcmp (CurrentElement, "entry"))
298 {
299 ++internal_EntryCount;
300 SG_DBGOUT_STR ("==END ", CurrentElement);
301 }
302 else if (0 == strcmp (CurrentElement, "voice"))
303 {
304 ++internal_VoiceCount;
305 SG_DBGOUT_STR ("==END ", CurrentElement);
306 }
307 return;
308 }
309
310 //Now deal with Attributes if there are any:
311 if (Attribute != NULL)
312 {
313 // ParserXML_AbortFlag = TRUE;
314 // SG_DBGOUT_STR(Attribute, Value);
315 gxml_XMLEventDataParser (Attribute, Value, internal_EntryCount);
316 return;
317 }
318
319 //got here, so must slog through assigning vars Element-by-Element (the old way).
320 //The first line exists in order to allow old pre-Attribute file versions to
321 //still be openable:
322 if (0 ==
323 gxml_XMLEventDataParser (CurrentElement, Value, internal_EntryCount))
324 {
325 }
326 else if (!strcmp (CurrentElement, "description"))
327 {
328 //20070627: fixed bug here if user had no desc. (because Value would equal NULL)
329 // SG_UndoRedo.Voice[internal_VoiceCount].description =
330 SG_StringAllocateAndCopy (&
331 (SG_UndoRedo.Voice[internal_VoiceCount].
332 description), Value);
333 SG_DBGOUT_STR ("description:",
334 SG_UndoRedo.Voice[internal_VoiceCount].description);
335 }
336 else if (!strcmp (CurrentElement, "type"))
337 {
338 SG_UndoRedo.Voice[internal_VoiceCount].type = atoi (Value);
339 SG_DBGOUT_INT ("voicetype:", SG_UndoRedo.Voice[internal_VoiceCount].type);
340 }
341 else if (!strcmp (CurrentElement, "voice_state"))
342 {
343 SG_UndoRedo.Voice[internal_VoiceCount].state = atoi (Value);
344 SG_DBGOUT_INT ("voice_state:",
345 SG_UndoRedo.Voice[internal_VoiceCount].state);
346 }
347 else if (!strcmp (CurrentElement, "voice_hide"))
348 {
349 SG_UndoRedo.Voice[internal_VoiceCount].hide = atoi (Value);
350 SG_DBGOUT_INT ("voice_hide:", SG_UndoRedo.Voice[internal_VoiceCount].hide);
351 }
352 else if (!strcmp (CurrentElement, "voice_mute"))
353 {
354 SG_UndoRedo.Voice[internal_VoiceCount].mute = atoi (Value);
355 SG_DBGOUT_INT ("voice_mute:", SG_UndoRedo.Voice[internal_VoiceCount].mute);
356 }
357 else if (!strcmp (CurrentElement, "voice_mono"))
358 {
359 SG_UndoRedo.Voice[internal_VoiceCount].mono = atoi (Value);
360 SG_DBGOUT_INT ("voice_mono:", SG_UndoRedo.Voice[internal_VoiceCount].mono);
361 }
362 //By the totalentrycount entry, I have all the info needed to make the critical memory allotments:
363 else if (!strcmp (CurrentElement, "totalentrycount"))
364 {
365 int listedcount = atoi (Value);
366
367 if (listedcount > gxml_ParserXML_EntryCount)
368 {
369 SG_ERROUT_INT ("Listed entry count larger than actual count by",
370 listedcount - gxml_ParserXML_EntryCount);
371 SG_DBGOUT_INT (" Listed count:", listedcount);
372 SG_DBGOUT_INT (" Actual count:", gxml_ParserXML_EntryCount);
373 }
374 else if (listedcount < gxml_ParserXML_EntryCount)
375 {
376 SG_ERROUT_INT ("Listed entry count smaller than actual count by",
377 gxml_ParserXML_EntryCount - listedcount);
378 SG_DBGOUT_INT (" Listed count:", listedcount);
379 SG_DBGOUT_INT (" Actual count:", gxml_ParserXML_EntryCount);
380 }
381 else
382 {
383 SG_DBGOUT_INT ("Listed entry count matched actual count:",
384 gxml_ParserXML_EntryCount);
385 }
386
387 // SG_UndoRedo.TotalDataPoints = atoi (Value); //this is weak, as this number could be wrong (I need to count myself)
388 SG_UndoRedo.TotalDataPoints = gxml_ParserXML_EntryCount; //I trust the read count more than listed
389 SG_AllocateBackupData (&SG_UndoRedo, SG_UndoRedo.TotalVoices,
390 SG_UndoRedo.TotalDataPoints);
391 SG_DBGOUT_INT ("TotalEntryCount:", SG_UndoRedo.TotalDataPoints);
392 SG_DBGOUT ("==Allocated Loadup Data==");
393 }
394 else if (!strcmp (CurrentElement, "voicecount"))
395 {
396 int listedcount = atoi (Value);
397
398 if (listedcount > gxml_ParserXML_VoiceCount)
399 {
400 SG_ERROUT_INT ("Listed voice count larger than actual count by",
401 listedcount - gxml_ParserXML_VoiceCount);
402 SG_DBGOUT_INT (" Listed count:", listedcount);
403 SG_DBGOUT_INT (" Actual count:", gxml_ParserXML_VoiceCount);
404 }
405 else if (listedcount < gxml_ParserXML_VoiceCount)
406 {
407 SG_ERROUT_INT ("Listed voice count smaller than actual count by",
408 gxml_ParserXML_VoiceCount - listedcount);
409 SG_DBGOUT_INT (" Listed count:", listedcount);
410 SG_DBGOUT_INT (" Actual count:", gxml_ParserXML_VoiceCount);
411 }
412 else
413 {
414 SG_DBGOUT_INT ("Listed voice count matched actual count:",
415 gxml_ParserXML_VoiceCount);
416 }
417 SG_UndoRedo.TotalVoices = gxml_ParserXML_VoiceCount; // I trust the real count more than listed
418 }
419
420 //finally the rarely called, low-priority global entries:
421 else if (!strcmp (CurrentElement, "title"))
422 {
423 SG_StringAllocateAndCopy (&main_Info_Title, Value);
424 }
425 else if (!strcmp (CurrentElement, "schedule_description"))
426 {
427 SG_StringAllocateAndCopy (&main_Info_Description, Value);
428 }
429 else if (!strcmp (CurrentElement, "author"))
430 {
431 SG_StringAllocateAndCopy (&main_Info_Author, Value);
432 }
433 else if (!strcmp (CurrentElement, "loops"))
434 {
435 main_SetLoops (atoi (Value));
436 SG_DBGOUT_INT ("Loops:", BB_Loops);
437 }
438 else if (!strcmp (CurrentElement, "overallvolume_left"))
439 {
440 BB_VolumeOverall_left = g_ascii_strtod (Value, NULL);
441 SG_DBGOUT_FLT ("BB_VolumeOverall_left", BB_VolumeOverall_left);
442 }
443 else if (!strcmp (CurrentElement, "overallvolume_right"))
444 {
445 BB_VolumeOverall_right = g_ascii_strtod (Value, NULL);
446 SG_DBGOUT_FLT ("BB_VolumeOverall_right", BB_VolumeOverall_right);
447 }
448 else if (!strcmp (CurrentElement, "stereoswap"))
449 {
450 BB_StereoSwap = atoi (Value);
451 SG_DBGOUT_INT ("BB_StereoSwap", BB_StereoSwap);
452 }
453 else if (!strcmp (CurrentElement, "graphview"))
454 {
455 SG_GraphType = atoi (Value);
456 SG_DBGOUT_INT ("SG_GraphType", SG_GraphType);
457 }
458 else if (!strcmp (CurrentElement, "gnauralfile_version"))
459 {
460 gxml_GnauralFile = ~0;
461 SG_DBGOUT ("Zeroing running voice and entry counts");
462 internal_EntryCount = internal_VoiceCount = 0;
463 SG_DBGOUT_STR ("File Version:", Value);
464 if (strcmp (gxml_VERSION_GNAURAL_XMLFILE, Value))
465 {
466 //SG_ERROUT("File format version too old: Aborting!");
467 //ParserXML_AbortFlag = 1;
468 SG_ERROUT ("Unknown File Version:");
469 SG_ERROUT ("Expected:");
470 SG_ERROUT (gxml_VERSION_GNAURAL_XMLFILE);
471 SG_ERROUT ("Got:");
472 SG_ERROUT (Value);
473 // if (0 == main_MessageDialogBox ("Unknown Gnaural file version or format. Is this a Gnaural 1 file?", GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO)) { }
474 }
475 else
476 {
477 SG_DBGOUT ("Useable file version, continuing:");
478 }
479 }
480 }
481
482 /////////////////////////////////////////////////////
483 //Returns 0 on success
484 //widget refers to main_drawing_area, BTW
485 //To maximize reusing code, this procedure actually fills
486 //ScheduleGUI's variable "SG_UndoRedo" with the incoming
487 //data, then treats that data like any ordinary restore.
488 //RETURNS 0 on success;
489 //20070705: changed a lot of address bugs with console mode
490 //trying to update a non-existent GUI.
491 //NOTE: if MergeRestore == TRUE, adds restore to whatever is already
492 //in SG; if FALSE, erases everything currently in SG
gxml_XMLReadFile(char * filename,GtkWidget * widget,gboolean MergeRestore)493 int gxml_XMLReadFile (char *filename,
494 GtkWidget * widget, gboolean MergeRestore)
495 {
496 if (filename == NULL)
497 {
498 return -1;
499 }
500
501 //to check if maybe it is a Gnaural1 file:
502 gxml_GnauralFile = 0;
503
504 //Set a few things in case they're skipped later:
505 main_SetLoops (1);
506 main_Info_Author[0] = '\0';
507 main_Info_Title[0] = '\0';
508 main_Info_Description[0] = '\0';
509 BB_ResetAllVoices (); //never hurts to do this, and might help a lot
510 // BB_LoopCount = 1;
511
512 //to parse a Gnaural file:
513 // 1) zero any SG internal variables used to count voice/event progress (ESSENTIAL)
514 // 2) Give ParserXML SG's internal callback function
515 // 3) call ParserXML_parse_file_xml:
516 //Mustn't forget this:
517 gxml_ParserXML_VoiceCount = 0;
518 gxml_ParserXML_EntryCount = 0;
519 SetUserParserXMLHandler (gxml_XMLParser_counter);
520 SG_DBGOUT ("Parsing XML file for true voice and entry counts");
521 if (0 == ParserXML_parse_file_xml (filename))
522 {
523 SG_DBGOUT_INT ("Total new Voice count: ", gxml_ParserXML_VoiceCount);
524 SG_DBGOUT_INT ("Total new Entry count: ", gxml_ParserXML_EntryCount);
525 }
526 else
527 {
528 SG_DBGOUT ("Something's wrong with the XML file, can't count");
529 }
530 SetUserParserXMLHandler (gxml_XMLParser);
531 SG_DBGOUT ("Starting with real XML file parse:");
532 if (0 == ParserXML_parse_file_xml (filename))
533 {
534 SG_DBGOUT ("XML file parsed, putting data in engine:");
535 SG_DBGOUT_INT ("Total new Voice count: ", gxml_ParserXML_VoiceCount);
536 SG_DBGOUT_INT ("Total new Entry count: ", gxml_ParserXML_EntryCount);
537 SG_RestoreDataPoints (widget, MergeRestore);
538 SG_DrawGraph (widget);
539 SG_DBGOUT_STR ("Title:", main_Info_Title);
540 SG_DBGOUT_STR ("Author:", main_Info_Author);
541 SG_DBGOUT_STR ("Description:", main_Info_Description);
542 main_UpdateGUI_UserDataInfo ();
543 gnauralRecentMenu_add_utf8_filename (filename); //a20101014
544
545 }
546 else
547 {
548 if (gxml_GnauralFile == 0)
549 {
550 SG_DBGOUT ("No Gnaural format file found");
551 //try to open a Gnaural1 file:
552 if (main_gnaural_guiflag == TRUE || //BUG20100928: was "FALSE"
553 0 != main_MessageDialogBox ("Write default file?)", //Is this a pre-2007 Gnaural file?",
554 GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO))
555 {
556 main_WriteDefaultFile ();
557 }
558 else
559 {
560 SG_DBGOUT ("Processing as a pre-2006 Gnaural file");
561 main_GNAURAL1FILE_SchedFilenameToSchedule (filename);
562 // SG_GetScheduleLimits();
563 SG_ConvertDataToXY (widget);
564 // SG_DrawGraph (widget);
565 SG_DataHasChanged = SG_GraphHasChanged = TRUE;
566 }
567 }
568 else
569 {
570 return -1; //THIS SHOULD BE CLEANED UP; it is confusing
571 }
572 }
573
574 //Got here, so file is valid, so load BB and set main_sCurrentGnauralFilenameAndPath:
575 strcpy (main_sCurrentGnauralFilenameAndPath, filename);
576 main_LoadBinauralBeatSoundEngine ();
577
578 //Loaded BB engine, so can get schedule fingerprint for file:
579 GN_Running_GetScheduleFingerprint ();
580 GN_DBGOUT_INT ("Full Schedule Fingerprint:", GN_ScheduleFingerprint);
581
582 //if we have a GUI, might as well do this here:
583 if (main_gnaural_guiflag == TRUE)
584 {
585 main_SetGraphToggle (main_drawing_area);
586 main_UpdateGUI_FileInfo (filename);
587 VG_DestroyTreeView (); //20100624
588 main_UpdateGUI_Voices (main_vboxVoices);
589 main_OnButton_Stop (NULL);
590 }
591 return 0;
592 }
593
594 ///////////////////////////////////////////////
595 //this is only called by ParserXML; don't call it has one job:
596 //to count the number of voices and number of datapoints
gxml_XMLParser_counter(const gchar * CurrentElement,const gchar * Attribute,const gchar * Value)597 void gxml_XMLParser_counter (const gchar * CurrentElement, //this must always be a valid string
598 const gchar * Attribute, //beware: this will equal NULL if there are none
599 const gchar * Value) //beware: this will equal NULL to announce end of CurrnetElement
600 {
601 //See if this is the end of CurrentElement:
602 if (Value == NULL)
603 {
604 if (0 == strcmp (CurrentElement, "entry"))
605 {
606 ++gxml_ParserXML_EntryCount;
607 }
608 else if (0 == strcmp (CurrentElement, "voice"))
609 {
610 ++gxml_ParserXML_VoiceCount;
611 }
612 return;
613 }
614 }
615