aboutsummaryrefslogtreecommitdiff
path: root/src/lib/hd24transferengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/hd24transferengine.cpp')
-rw-r--r--src/lib/hd24transferengine.cpp2143
1 files changed, 2143 insertions, 0 deletions
diff --git a/src/lib/hd24transferengine.cpp b/src/lib/hd24transferengine.cpp
new file mode 100644
index 0000000..32db2d8
--- /dev/null
+++ b/src/lib/hd24transferengine.cpp
@@ -0,0 +1,2143 @@
1#include "hd24transferengine.h"
2#include <config.h>
3#include <hd24fs.h>
4#include <hd24sndfile.h>
5
6#define HD24TRANSFERDEBUG 0
7#define MAXCHANNELS 24
8#define TRACKACTION_UNDEF -1
9
10hd24transferjob::hd24transferjob()
11{
12#if (HD24TRANSFERDEBUG==1)
13 cout << "hd24transferjob::hd24transferjob();" << endl;
14#endif
15 init_vars();
16}
17
18hd24transferjob::~hd24transferjob()
19{
20#if (HD24TRANSFERDEBUG==1)
21 cout << "hd24transferjob::~hd24transferjob();" << endl;
22#endif
23
24 if (trackselected!=NULL)
25 {
26 delete trackselected;
27 trackselected=NULL;
28 }
29 usecustomrate=0; // by default, match export samrate with song rate
30 if (m_projectdir!=NULL)
31 {
32 delete m_projectdir;
33 m_projectdir=NULL;
34 }
35}
36
37void hd24transferjob::init_vars()
38{
39#if (HD24TRANSFERDEBUG==1)
40 cout << "hd24transferjob::init_vars()" << endl;
41#endif
42 this->wantsplit=1;
43 trackselected=new int[MAXCHANNELS];
44 for (int i=0;i<MAXCHANNELS;i++)
45 {
46 trackselected[i]=0;
47 }
48 m_projectdir=NULL;
49 llsizelimit=1024*1024*1024;
50 mixleft=0;
51 mixright=0;
52 m_selectedformat=0;
53 usecustomrate=0;
54 stamprate=48000;
55 wantsplit=1;
56
57 jobsourcesong=NULL;
58 jobtargetsong=NULL;
59 jobsourcefs=NULL;
60 jobtargetfs=NULL;
61 have_smpte=false;
62
63 m_startoffset=0;
64 m_endoffset=0;
65 for (int i=0;i<24;i++)
66 {
67 this->filepath[i]=NULL;
68 this->filehandle[i]=NULL;
69 this->m_trackaction[i]=TRACKACTION_UNDEF; // undefined trackaction
70 }
71 return;
72}
73
74void hd24transferjob::trackaction(int base1tracknum,int action)
75{
76#if (HD24TRANSFERDEBUG==1)
77 cout << "hd24transferjob::trackaction(base1track="
78 << base1tracknum << ", action=" << action << ")" << endl;
79#endif
80
81 m_trackaction[base1tracknum-1]=action;
82}
83
84int hd24transferjob::trackaction(int base1tracknum)
85{
86#if (HD24TRANSFERDEBUG==1)
87 cout << "returning hd24transferjob::trackaction(base1track="
88 << base1tracknum << ")=" << m_trackaction[base1tracknum-1]
89 << endl;
90#endif
91 return m_trackaction[base1tracknum-1];
92}
93
94void hd24transferengine::trackaction(int base1tracknum,int action)
95{
96 job->trackaction(base1tracknum,action);
97}
98
99int hd24transferengine::trackaction(int base1tracknum)
100{
101 return job->trackaction(base1tracknum);
102}
103
104char* hd24transferjob::sourcefilename(int base1tracknum)
105{
106 if (base1tracknum<1) return NULL;
107 if (base1tracknum>24) return NULL;
108 return filepath[base1tracknum-1];
109}
110
111void hd24transferjob::sourcefilename(int base1tracknum,const char* filename)
112{
113 /* set nth filename to the given char string */
114 if (base1tracknum<1) return;
115 if (base1tracknum>24) return;
116
117 if (filepath[base1tracknum-1]!=NULL)
118 {
119 free(filepath[base1tracknum-1]);
120 }
121 __uint32 n=strlen(filename);
122 char* tmpbuf=(char*)malloc(n);
123 filepath[base1tracknum-1]=tmpbuf;
124 strncpy(tmpbuf,filename,n+1);
125 return;
126}
127
128void hd24transferengine::sourcefilename(int base1tracknum,const char* filename)
129{
130 job->sourcefilename(base1tracknum,filename);
131}
132
133char* hd24transferengine::sourcefilename(int base1tracknum)
134{
135 return job->sourcefilename(base1tracknum);
136}
137
138void hd24transferjob::startoffset(__uint32 newoff)
139{
140 m_startoffset=newoff;
141}
142
143void hd24transferjob::endoffset(__uint32 newoff)
144{
145 m_endoffset=newoff;
146}
147
148__uint32 hd24transferjob::startoffset()
149{
150 return m_startoffset;
151}
152
153__uint32 hd24transferjob::endoffset()
154{
155 return m_endoffset;
156}
157
158hd24fs* hd24transferjob::sourcefs()
159{
160 return this->jobsourcefs;
161}
162
163hd24song* hd24transferjob::sourcesong()
164{
165 return this->jobsourcesong;
166}
167
168void hd24transferjob::sourcefs(hd24fs* fs)
169{
170 this->jobsourcefs=fs;
171}
172
173void hd24transferjob::sourcesong(hd24song* song)
174{
175 this->jobsourcesong=song;
176 this->jobsourcefs=jobsourcesong->parentfs;
177}
178
179hd24fs* hd24transferjob::targetfs()
180{
181 return this->jobtargetfs;
182}
183
184hd24song* hd24transferjob::targetsong()
185{
186 return this->jobtargetsong;
187}
188
189void hd24transferjob::targetfs(hd24fs* fs)
190{
191 this->jobtargetfs=fs;
192}
193
194void hd24transferjob::targetsong(hd24song* song)
195{
196 this->jobtargetsong=song;
197 this->jobtargetfs=jobtargetsong->parentfs;
198}
199
200void hd24transferjob::projectdir(const char* projdir)
201{
202#if (HD24TRANSFERDEBUG==1)
203 cout << "hd24transferjob::projectdir("<<projdir<< ")"<<endl;
204#endif
205 if (m_projectdir!=NULL)
206 {
207 delete m_projectdir;
208 m_projectdir=NULL;
209 }
210 m_projectdir=new string(projdir);
211 return;
212}
213
214const char* hd24transferjob::projectdir()
215{
216#if (HD24TRANSFERDEBUG==1)
217 cout << "returning hd24transferjob::projectdir()=";
218 if (m_projectdir==NULL)
219 {
220 cout <<" NULL " << endl;
221 } else {
222 cout <<*m_projectdir<<endl;
223 }
224#endif
225 return m_projectdir->c_str();
226}
227
228void hd24transferengine::lasterror(const char* errormessage)
229{
230 if (m_lasterror!=NULL)
231 {
232 delete m_lasterror;
233 }
234 m_lasterror=new string(errormessage);
235 return;
236}
237
238string* hd24transferengine::lasterror()
239{
240 return m_lasterror;
241}
242
243
244int hd24transferengine::format_outputchannels(int format)
245{
246 return m_format_outputchannels[format];
247}
248
249const char* hd24transferengine::projectdir()
250{
251 cout << "returning hd24transferengine::projectdir()"<<endl;
252 return job->projectdir();
253}
254
255void hd24transferengine::projectdir(const char* projdir)
256{
257#if (HD24TRANSFERDEBUG==1)
258 cout << "hd24transferengine::projectdir("<<projdir<< ")"<<endl;
259#endif
260 job->projectdir(projdir);
261 return;
262}
263
264hd24transferengine::hd24transferengine()
265{
266#if (HD24TRANSFERDEBUG==1)
267 cout <<"hd24transferengine::hd24transferengine()" << endl;
268#endif
269 init_vars();
270}
271
272hd24transferengine::~hd24transferengine()
273{
274#if (HD24TRANSFERDEBUG==1)
275 cout <<"hd24transferengine::~hd24transferengine()" << endl;
276#endif
277 if (m_lasterror!=NULL)
278 {
279 delete m_lasterror;
280 m_lasterror=NULL;
281 }
282 if (job!=NULL)
283 {
284 delete job;
285 job=NULL;
286 }
287}
288
289void hd24transferengine::init_vars()
290{
291 songnum=0;
292 totsongs=0;
293 ui=NULL;
294 totbytestotransfer=0;
295 totbytestransferred=0;
296 prefix=0;
297 transfer_cancel=0;
298 trackspergroup=0;
299 transfermixer=NULL;
300 job=NULL;
301 m_lasterror=NULL;
302 job=new hd24transferjob();
303 this->uiconfirmfunction=NULL;
304 this->setstatusfunction=NULL;
305 soundfile=NULL;
306#if (HD24TRANSFERDEBUG==1)
307 cout << "hd24transferengine::init_vars() - job="<<job<<endl;
308#endif
309 m_format_outputextension=new vector<string>;
310 m_format_shortdesc=new vector<string>;
311 populate_formatlist();
312}
313
314void hd24transferengine::populate_formatlist()
315{
316#if (HD24TRANSFERDEBUG==1)
317 cout << "hd24transferengine::populate_formatlist()" << endl;
318#endif
319/* Set up transfer format list */
320 formatcount=0;
321 m_format_shortdesc->push_back("WAV (24 bit), mono");
322 m_format_outputformat[formatcount]=SF_FORMAT_WAV|SF_FORMAT_PCM_24|SF_ENDIAN_LITTLE;
323 m_format_outputchannels[formatcount]=1; // mono
324 m_format_bitdepth[formatcount]=24;
325 m_format_sndfile[formatcount]=false; // do not use libsndfile for this file format.
326 m_format_outputextension->push_back(".wav");
327 formatcount++;
328
329 m_format_shortdesc->push_back("WAV (24 bit), stereo");
330 m_format_outputformat[formatcount]=SF_FORMAT_WAV|SF_FORMAT_PCM_24|SF_ENDIAN_LITTLE;
331 m_format_outputchannels[formatcount]=2; // stereo
332 m_format_bitdepth[formatcount]=24;
333 m_format_sndfile[formatcount]=true;
334 m_format_outputextension->push_back(".wav");
335 formatcount++;
336
337 m_format_shortdesc->push_back("WAV (24 bit), multi");
338 m_format_outputformat[formatcount]=SF_FORMAT_WAV|SF_FORMAT_PCM_24|SF_ENDIAN_LITTLE;
339 m_format_outputchannels[formatcount]=0; // multi
340 m_format_bitdepth[formatcount]=24;
341 m_format_sndfile[formatcount]=true;
342 m_format_outputextension->push_back(".wav");
343 formatcount++;
344
345 m_format_shortdesc->push_back("AIF (24 bit), mono");
346 m_format_outputformat[formatcount]=SF_FORMAT_AIFF|SF_FORMAT_PCM_24;
347 m_format_outputchannels[formatcount]=1; // mono
348 m_format_bitdepth[formatcount]=24;
349 m_format_sndfile[formatcount]=false;
350 m_format_outputextension->push_back(".aif");
351 formatcount++;
352
353 m_format_shortdesc->push_back("AIF (24 bit), stereo");
354 m_format_outputformat[formatcount]=SF_FORMAT_AIFF|SF_FORMAT_PCM_24;
355 m_format_outputchannels[formatcount]=2; // stereo
356 m_format_bitdepth[formatcount]=24;
357 m_format_sndfile[formatcount]=true;
358 m_format_outputextension->push_back(".aif");
359 formatcount++;
360
361 m_format_shortdesc->push_back("AIF (24 bit), multi");
362 m_format_outputformat[formatcount]=SF_FORMAT_AIFF|SF_FORMAT_PCM_24;
363 m_format_outputchannels[formatcount]=0; // stereo
364 m_format_bitdepth[formatcount]=24;
365 m_format_sndfile[formatcount]=true;
366 m_format_outputextension->push_back(".aif");
367 formatcount++;
368 selectedformat(0);
369}
370
371const char* hd24transferengine::getformatdesc(int formatnum)
372{
373 return ((*m_format_shortdesc)[formatnum]).c_str();
374}
375
376int hd24transferengine::supportedformatcount()
377{
378 return formatcount;
379}
380
381void hd24transferengine::trackselected(__uint32 base0tracknum,bool selected)
382{
383 if (base0tracknum<0) return;
384 if (base0tracknum>=MAXCHANNELS) return;
385
386 if (selected)
387 {
388 job->trackselected[base0tracknum]=1;
389 } else {
390 job->trackselected[base0tracknum]=0;
391 }
392 return;
393}
394
395bool hd24transferengine::trackselected(__uint32 base0tracknum)
396{
397 if (base0tracknum<0) return false;
398 if (base0tracknum>=MAXCHANNELS) return false;
399
400 return ((job->trackselected[base0tracknum])==1);
401}
402
403
404void hd24transferengine::openbuffers(unsigned char** audiobuf,
405 unsigned int channels,
406 unsigned int bufsize)
407{
408#if (HD24TRANSFERDEBUG==1)
409 cout << "hd24transferengine::openbuffers" << endl;
410#endif
411
412 for (unsigned int handle=0;handle<channels;handle++)
413 {
414 if (!trackselected(handle)) {
415 // channel not selected for export
416 continue;
417 }
418 audiobuf[handle]=
419 (unsigned char *)memutils::mymalloc("openbuffers",
420 bufsize,1);
421 }
422 #if (HD24TRANSFERDEBUG==1)
423 cout << "opened buffers" << endl;
424 #endif
425}
426
427void hd24transferengine::closebuffers(unsigned char** audiobuf,unsigned int channels)
428{
429#if (HD24TRANSFERDEBUG==1)
430 cout << "hd24transferengine::closebuffers" << endl;
431#endif
432 for (__uint32 handle=0;handle<channels;handle++)
433 {
434 if (!trackselected(handle)) {
435 // channel not selected for export
436 continue;
437 }
438 if (audiobuf[handle]!=NULL)
439 {
440 memutils::myfree("closebuffers",audiobuf[handle]);
441 }
442 }
443}
444
445void hd24transferengine::writerawbuf(hd24sndfile* filehandle,unsigned char* buf,long subblockbytes)
446{
447#if (HD24TRANSFERDEBUG==2)
448 cout << "writerawbuf (filehandle="<<filehandle<<", buf="<<buf<<", subblockbytes="<<subblockbytes<<endl;
449#endif
450 filehandle->writerawbuf(buf,subblockbytes);
451#if (HD24TRANSFERDEBUG==2 )
452 cout << "end writerawbuf (filehandle="<<filehandle<<", buf="<<buf<<", subblockbytes="<<subblockbytes<<endl;
453#endif
454}
455
456bool hd24transferengine::openinputfiles(SNDFILE** filehandle,SF_INFO* sfinfoin,unsigned int channels)
457{
458 int cannotopen=0;
459 cout << "TODO: hd24transferengine::openinputfiles" << endl;
460 if (job==NULL)
461 {
462 lasterror("No job found, transfer aborted.");
463 return false;
464 }
465
466 int trackcount=0;
467 for (unsigned int handle=0;handle<channels;handle++)
468 {
469#if (HD24TRANSFERDEBUG!=0)
470 cout << "Openinputfiles - handle=" << handle << endl;
471#endif
472 if (job->sourcefilename(handle+1)==NULL) {
473#if (HD24TRANSFERDEBUG!=0)
474 cout << "Channel not selected for transfer, skipping" << endl;
475#endif
476 continue;
477 }
478 if (strlen(job->sourcefilename(handle+1))==0) {
479#if (HD24TRANSFERDEBUG!=0)
480 cout << "Channel not selected for transfer, skipping" << endl;
481#endif
482 continue;
483 }
484 trackcount++;
485
486#if (HD24TRANSFERDEBUG!=0)
487 cout << "Channel selected for transfer" << endl;
488 cout << "That brings the total track count to "
489 << trackcount << endl;
490 cout << "job=" << job << endl;
491 cout << "soundfile=" << soundfile << endl;
492 cout << "sourcefilename=" << job->sourcefilename(handle+1)
493 << endl;
494#endif
495
496 job->filehandle[handle]=soundfile->sf_open(job->sourcefilename(handle+1),SFM_READ,&sfinfoin[handle]);
497 if (!(job->filehandle[handle]))
498 {
499 cannotopen=1;
500 continue;
501 }
502 }
503
504 return (cannotopen==0); // return true if successful, flase otherwise
505}
506
507bool hd24transferengine::openoutputfiles(hd24sndfile** filehandle,unsigned int channels,unsigned int partnum,int prefix)
508{
509 trackspergroup=0;
510
511 SF_INFO sfinfoout;
512 bool uselibsndfile=m_format_sndfile[selectedformat()];
513 sfinfoout.format=m_format_outputformat[selectedformat()];
514 int chcount=0;
515 if (m_format_outputchannels[selectedformat()]==0) {
516 // count channels
517 for (unsigned int handle=0;handle<channels;handle++)
518 {
519 if (job->trackselected[handle]!=0) {
520 chcount++;
521 }
522 }
523 sfinfoout.channels=chcount;
524 } else {
525 sfinfoout.channels=m_format_outputchannels[selectedformat()];
526 }
527 if (job->usecustomrate==1) {
528 long samrate=job->stamprate;
529 sfinfoout.samplerate=samrate;
530 } else {
531 sfinfoout.samplerate=job->sourcesong()->samplerate();
532 }
533 // chcount and lasthandle are intended to allow
534 // support for writing multichannel files.
535 int lasthandle=0;
536 int lasttrack=-1;
537 int trackcount=0;
538 int cannotopen=0;
539 chcount=0;
540 for (unsigned int handle=0;handle<channels;handle++)
541 {
542
543 islastchanofgroup[handle]=false;
544 isfirstchanofgroup[handle]=false;
545
546 if (job->trackselected[handle]==0) {
547 // channel not selected for export
548 continue;
549 }
550 trackcount++;
551 lasttrack=handle;
552
553 string* fname=generate_filename(handle,partnum,prefix);
554 if (fname==NULL)
555 {
556 /* cannot generate filename. Most likely cause is
557 no song set */
558 return false; // problem opening files.
559 }
560 if (chcount==0) {
561 isfirstchanofgroup[handle]=true;
562 if (uselibsndfile)
563 {
564 filehandle[handle]->sndfilehandle=NULL;
565 if (soundfile->sf_open) {
566 filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout,soundfile);
567 }
568 if (!(filehandle[handle]->handle()))
569 {
570 cannotopen=1;
571 }
572 }
573 else
574 {
575 filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout);
576 }
577 lasthandle=handle;
578 } else {
579 // copy handle of previously opened file to current track
580 filehandle[handle]->handle(filehandle[lasthandle]->handle(),filehandle[lasthandle]->handletype());
581 if (!(filehandle[handle]->handle()))
582 {
583 cannotopen=1;
584 }
585 }
586 chcount++;
587 if ((sfinfoout.channels)!=0)
588 {
589 // sfinfoout.channels=0 means full multitrack file
590 // so only a single file will be opened.
591 chcount=chcount%(sfinfoout.channels);
592 if (chcount==0) {
593 islastchanofgroup[handle]=true;
594 if (trackspergroup==0) {
595 trackspergroup=trackcount;
596 }
597 }
598 }
599
600 delete fname;
601 }
602 if (lasttrack>=0)
603 {
604 if (trackspergroup==0) {
605 trackspergroup=trackcount;
606 }
607
608 islastchanofgroup[lasttrack]=true;
609 }
610 return (cannotopen==0); // return true if successful, false otherwise
611}
612
613void hd24transferengine::closeinputfiles(SNDFILE** filehandle,unsigned int channels)
614{
615 SNDFILE* lasthandle=NULL;
616 for (unsigned int handle=0;handle<channels;handle++)
617 {
618 if (job->trackselected[handle]==0) continue;
619 if (filehandle[handle]!=lasthandle) {
620 soundfile->sf_close(filehandle[handle]);
621 lasthandle=filehandle[handle];
622 filehandle[handle]=NULL;
623 }
624 }
625}
626
627void hd24transferengine::closeoutputfiles(hd24sndfile** filehandle,unsigned int channels)
628{
629 void* lasthandle=NULL;
630
631 for (unsigned int handle=0;handle<channels;handle++)
632 {
633 if (job->trackselected[handle]==0) continue;
634 if (filehandle[handle]->handle()!=lasthandle) {
635 lasthandle=(void*)filehandle[handle]->handle();
636 if (lasthandle!=NULL) {
637 filehandle[handle]->close();
638 }
639 }
640 }
641}
642
643bool hd24transferengine::confirmfileoverwrite()
644{
645 if (this->uiconfirmfunction==NULL)
646 {
647 lasterror("Output files already exist, transfer aborted.");
648 return false;
649 }
650
651 return uiconfirmfunction(ui,"One or more output files already exist. "
652 "Do you want to overwrite them?");
653}
654
655bool hd24transferengine::overwritegivesproblems(hd24song* thesong,int partnum)
656{
657 /* this function will return TRUE if overwriting
658 existing files causes a problem, FALSE otherwise.
659
660 Overwriting files does NOT cause problems if
661 - no files are going to be overwritten
662 or
663 - Files are going to be overwritten but the user
664 permits us to do so.
665
666 */
667
668 if (anyfilesexist(thesong))
669 {
670 return (!(confirmfileoverwrite()));
671 }
672 return false;
673}
674
675bool hd24transferengine::dontopenoutputfiles(hd24sndfile** filehandle,unsigned int channels,unsigned int partnum,int prefix)
676{
677 // HACK
678 trackspergroup=0;
679
680 SF_INFO sfinfoout;
681 //bool uselibsndfile=m_format_sndfile[selectedformat()];
682 sfinfoout.format=m_format_outputformat[selectedformat()];
683 int chcount=0;
684 if (m_format_outputchannels[selectedformat()]==0) {
685 // count channels
686 for (unsigned int handle=0;handle<channels;handle++)
687 {
688 if (job->trackselected[handle]!=0) {
689 chcount++;
690 }
691 }
692 sfinfoout.channels=chcount;
693 } else {
694 sfinfoout.channels=m_format_outputchannels[selectedformat()];
695 }
696 if (job->usecustomrate==1) {
697 long samrate=job->stamprate;
698 sfinfoout.samplerate=samrate;
699 } else {
700 sfinfoout.samplerate=job->sourcesong()->samplerate();
701 }
702 // chcount and lasthandle are intended to allow
703 // support for writing multichannel files.
704 int lasthandle=0;
705 int lasttrack=-1;
706 int trackcount=0;
707 int cannotopen=0;
708 chcount=0;
709 for (unsigned int handle=0;handle<channels;handle++)
710 {
711
712 islastchanofgroup[handle]=false;
713 isfirstchanofgroup[handle]=false;
714
715 if (job->trackselected[handle]==0) {
716 // channel not selected for export
717 continue;
718 }
719 trackcount++;
720 lasttrack=handle;
721
722 string* fname=generate_filename(handle,partnum,prefix);
723 if (fname==NULL)
724 {
725 // Cannot generate filename. No song set?
726 return false; // problem (not) opening files.
727 }
728 if (chcount==0) {
729 isfirstchanofgroup[handle]=true;
730 // if (uselibsndfile)
731 // {
732 // filehandle[handle]->sndfilehandle=NULL;
733 // if (soundfile->sf_open) {
734 // filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout,soundfile);
735 // }
736 // if (!(filehandle[handle]->handle()))
737 // {
738 // cannotopen=1;
739 // }
740 // }
741 // else
742 // {
743 // filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout);
744 // }
745 lasthandle=handle;
746 } else {
747 // copy handle of previously opened file to current track
748 // filehandle[handle]->handle(filehandle[lasthandle]->handle(),filehandle[lasthandle]->handletype());
749 // if (!(filehandle[handle]->handle()))
750 // {
751 // cannotopen=1;
752 // }
753 }
754 chcount++;
755 // if ((sfinfoout.channels)!=0)
756 // {
757 // // sfinfoout.channels=0 means full multitrack file
758 // // so only a single file will be opened.
759 // chcount=chcount%(sfinfoout.channels);
760 // if (chcount==0) {
761 // islastchanofgroup[handle]=true;
762 // if (trackspergroup==0) {
763 // trackspergroup=trackcount;
764 // }
765 // }
766 // }
767
768 delete fname;
769 }
770
771 if (lasttrack>=0)
772 {
773 if (trackspergroup==0) {
774 trackspergroup=trackcount;
775 }
776
777 islastchanofgroup[lasttrack]=true;
778 }
779 return (cannotopen==0); // return true if successful, false otherwise
780}
781void hd24transferengine::flushbuffer(hd24sndfile** filehandle,unsigned char** buffer,__uint32 flushbytes,unsigned int channels)
782{
783 #if (HD24TRANSFERDEBUG==1)
784 cout << "Flushbuffer " << flushbytes << " bytes" <<endl;
785 #endif
786 for (unsigned int handle=0;handle<channels;handle++)
787 {
788 if (job->trackselected[handle]==0) continue;
789
790 writerawbuf(&(*filehandle)[handle],buffer[handle],flushbytes);
791 }
792 #if (HD24TRANSFERDEBUG==1)
793 cout << "Flushed" << endl;
794 #endif
795}
796
797void hd24transferengine::prepare_transfer_to_pc(__uint32 songnum,
798 __uint32 totsongs,__sint64 totbytestotransfer,
799 __sint64 totbytestransferred,
800 int wantsplit,__uint32 prefix)
801{
802 // set properties as needed
803 cout << "prepare transfer to pc:" << endl;
804 cout << "song "<< songnum<< "/" << totsongs << ", ";
805 cout << totbytestotransfer << " total bytes to transfer" << endl;
806 cout << totbytestransferred << " transferred so far" << endl;
807 cout << "wantsplit=" << wantsplit ;
808 cout << ", prefix=" << prefix << endl;
809 this->totbytestotransfer=totbytestotransfer;
810 // this->transfer_to_pc();
811}
812
813void hd24transferengine::transfer_in_progress(bool active)
814{
815 // TODO: callback function
816 // stop_transfer->show();
817}
818
819void hd24transferengine::mixleft(bool select)
820{
821 if (select) { job->mixleft=1; }
822}
823
824bool hd24transferengine::mixleft()
825{
826 if (job->mixleft==1)
827 {
828 return true;
829 }
830 return false;
831}
832
833void hd24transferengine::mixright(bool select)
834{
835 if (select) { job->mixright=1; }
836}
837
838bool hd24transferengine::mixright()
839{
840 if (job->mixright==1)
841 {
842 return true;
843 }
844 return false;
845}
846
847
848__sint64 hd24transferengine::transfer_to_pc()
849{
850 // function returns bytes transferred for the transfer of only the current file.
851
852 __sint64 totsamcount; /* Total number of samples exported */
853 __sint64 partsamcount; /* When splitting up the song into multiple parts,
854 number of samples exported to current part */
855 __sint64 blockcount; /* Allows us to keep a write buffer as cache for
856 better export performance */
857 if (job->sourcesong()==NULL)
858 {
859 return 0;
860 }
861 if (transfer_cancel==1)
862 {
863 return 0;
864 }
865
866 // limit which tracks need to be actually read from HD24 disk
867 for (__uint32 i=1;i<=MAXCHANNELS;i++)
868 {
869 if (job->trackselected[i-1]==1)
870 {
871 job->sourcesong()->readenabletrack(i,true);
872 } else {
873 job->sourcesong()->readenabletrack(i,false);
874 }
875 }
876 bool mustmixdown=false;
877 if (job->mixleft==1)
878 {
879 mustmixdown=true;
880 }
881 if (job->mixright==1)
882 {
883 mustmixdown=true;
884 }
885 if (transfermixer==NULL)
886 {
887 /* as much as we'd like, there is no mixer so we can't mix. */
888 mustmixdown=false;
889 }
890
891 #if (HD24TRANSFERDEBUG==1)
892 cout << "start export 1" << endl;
893 #endif
894 __uint32 lastremain=0xffffffff; //a
895 __uint64 songlen_sam=job->sourcesong()->songlength_in_samples()*(job->sourcesong()->physical_channels()/job->sourcesong()->logical_channels());
896 __uint32 channels=job->sourcesong()->logical_channels();
897 __uint32 bytespersam=(job->sourcesong()->bitdepth()/8);
898 int mustdeinterlace=0;
899 if ((job->sourcesong()->samplerate())>=88200)
900 {
901 mustdeinterlace=1;
902 }
903 __uint32 oldmixersamplerate=0;
904 if (mustmixdown)
905 {
906 if (transfermixer!=NULL) {
907 oldmixersamplerate=transfermixer->samplerate();
908 transfermixer->samplerate(job->sourcesong()->samplerate());
909 }
910 }
911
912 #if (HD24TRANSFERDEBUG==1)
913 cout << "Channels="<<channels << endl;
914 cout << "Songlen="<<songlen_sam << endl;
915 #endif
916 double oldpct=0;
917 #if (HD24TRANSFERDEBUG==1)
918 cout << "start export 2" << endl;
919 #endif
920
921 //SNDFILE* filehandle[channels];
922 hd24sndfile* filehandle[24];
923
924 for (int i=0;i<MAXCHANNELS;i++)
925 {
926 filehandle[i]=new hd24sndfile(m_format_outputformat[selectedformat()],soundfile);
927 }
928
929 __uint32 partnum=0;
930 __uint64 MAXBYTES=job->sizelimit();
931
932 /*
933 if total number of samples is likely to overflow
934 max allowable length, ask if user wants to split up
935 the files.
936 */
937 if (job->wantsplit==1) {
938 partnum=1; // count part numbers in filename
939 } else {
940 partnum=0; // do not count part numbers in filename
941 MAXBYTES=songlen_sam*bytespersam; // allow the full song length in a single file
942 }
943
944 /* Start location 0 is absolute, all other offsets
945 are relative to the start offset. The only difference
946 is in the timecode.
947 Because of this, if startoffset>0 is given, we
948 can ignore this. */
949 __uint64 translen;
950 __uint64 tottranslen=0; // for percentage calc in multi-song exports
951 signed int stepsize;
952 if (job->startoffset()>job->endoffset())
953 {
954 __uint32 tempoffset=job->startoffset();
955 job->startoffset(job->endoffset());
956 job->endoffset(tempoffset);
957 }
958
959 translen=(job->endoffset()-job->startoffset())*(job->sourcesong()->physical_channels()/job->sourcesong()->logical_channels());
960 #if (HD24TRANSFERDEBUG==1)
961 cout << "startoffset=" << job->startoffset() << endl;
962 cout << "endoffset=" << job->endoffset() << endl;
963 #endif
964
965 if (translen==0)
966 {
967 lasterror("Start offset equals end offset- nothing to do!");
968 }
969 stepsize=1;
970
971 bool canopen=true;
972 MixerChannelControl* mixerchannel[24];
973 for (unsigned int tracknum=0;tracknum<MAXCHANNELS;tracknum++)
974 {
975 mixerchannel[tracknum]=NULL;
976 }
977
978 if (mustmixdown)
979 {
980 for (unsigned int tracknum=0;tracknum<MAXCHANNELS;tracknum++)
981 {
982 mixerchannel[tracknum]=transfermixer->parentui()->mixerchannel[tracknum]->control;
983 }
984 // HACK
985 canopen=dontopenoutputfiles(
986 (hd24sndfile**)&filehandle[0],
987 channels,
988 partnum,
989 prefix); // partnum is for splitting large files
990 } else {
991 canopen=openoutputfiles(
992 (hd24sndfile**)&filehandle[0],
993 channels,
994 partnum,
995 prefix); // partnum is for splitting large files
996 }
997
998 if (!canopen)
999 {
1000 #if (HD24TRANSFERDEBUG==1)
1001 cout << "error opening output files" << endl;
1002 #endif
1003 transfer_cancel=1;
1004 return 0;
1005 } else {
1006 transfer_cancel=0;
1007 }
1008
1009 this->transfer_in_progress(true);
1010 time (&starttime);
1011
1012 partsamcount=0; totsamcount=0;
1013 int trackwithingroup=0;
1014 #if (HD24TRANSFERDEBUG==1)
1015 cout << "songlen in samples=" << songlen_sam << endl;
1016 #endif
1017 blockcount=0; // for buffered writing.
1018 hd24fs* currenthd24=job->sourcefs();
1019 if (currenthd24==NULL)
1020 {
1021 cout << "Critical error- current FS not defined." << endl;
1022 }
1023 int blocksize=currenthd24->getbytesperaudioblock();
1024 // to hold normally read audio data:
1025 unsigned char* audiodata=(unsigned char*)memutils::mymalloc("ftransfer_to_pc",blocksize,1);
1026
1027 // for high-samplerate block deinterlacing:
1028 unsigned char* deinterlacedata=(unsigned char*)memutils::mymalloc("ftransfer_to_pc",blocksize,1);
1029
1030 // for interlacing multi-track data:
1031 unsigned char* interlacedata=(unsigned char*)memutils::mymalloc("ftransfer_to_pc",blocksize,1);
1032
1033
1034 __uint32 samplesperblock=(blocksize/channels)/bytespersam;
1035 float* outputBuffer=NULL;
1036 SF_INFO infoblock;
1037 hd24sndfile* mixdownfile=NULL;
1038 if (mustmixdown)
1039 {
1040 outputBuffer=(float*)malloc(2*samplesperblock*sizeof(float)); // 2 because it is stereo
1041 mixdownfile=new hd24sndfile(SF_FORMAT_WAV|SF_FORMAT_PCM_32
1042 |SF_FORMAT_FLOAT,soundfile);
1043 infoblock.channels=2;
1044 infoblock.samplerate=job->sourcesong()->samplerate();
1045 infoblock.format=SF_FORMAT_WAV|SF_FORMAT_PCM_32|SF_FORMAT_FLOAT;
1046
1047 int mixdownfilenum=0;
1048 int fileopensuccess=0;
1049 do {
1050 string* mixdownfilename=new string("");
1051 *mixdownfilename+=*job->m_projectdir;
1052 string* currsongname=job->sourcesong()->songname();
1053 *mixdownfilename+=*currsongname;
1054 delete currsongname;
1055 *mixdownfilename+="_mixdown";
1056 if (mixdownfilenum>0)
1057 {
1058 *mixdownfilename+="_";
1059 string* mixnumstr=Convert::int2str(mixdownfilenum);
1060 *mixdownfilename+=*mixnumstr;
1061 delete mixnumstr;
1062 }
1063 *mixdownfilename+=".wav";
1064 if (!hd24utils::fileExists(mixdownfilename->c_str()))
1065 {
1066 mixdownfile->open(mixdownfilename->c_str(),SFM_WRITE,&infoblock,soundfile);
1067 fileopensuccess=1;
1068 }
1069 mixdownfilenum++;
1070 delete mixdownfilename;
1071 } while (fileopensuccess==0);
1072 }
1073
1074
1075 __uint32 samplesinfirstblock=samplesperblock;
1076 if (job->startoffset()!=0) {
1077 if (job->startoffset()>=samplesperblock) {
1078 samplesinfirstblock=samplesperblock-(job->startoffset()%samplesperblock);
1079 } else {
1080 samplesinfirstblock=samplesperblock-(job->startoffset());
1081 }
1082 }
1083 #if (HD24TRANSFERDEBUG==1)
1084 cout << "go to startoffset " << job->startoffset() << endl;
1085 #endif
1086 job->sourcesong()->golocatepos(job->startoffset());
1087 #if (HD24TRANSFERDEBUG==1)
1088 cout << "got to startoffset " << job->startoffset() << endl;
1089 cout << "translen= " << translen << endl;
1090 #endif
1091 __uint32 subblocksize=samplesperblock*bytespersam;
1092 __uint32 samplesinblock=samplesinfirstblock;
1093 if (translen<samplesperblock)
1094 {
1095 samplesinfirstblock=translen;
1096 }
1097
1098 __sint64 difseconds=0;
1099 __sint64 olddifseconds=0;
1100 __uint64 bytestransferred=0;
1101
1102 for (__uint32 samplenum=0;
1103 samplenum<translen;
1104 samplenum+=samplesinblock)
1105 {
1106 if (transfer_cancel==1)
1107 {
1108 break;
1109 }
1110 __uint32 subblockbytes=subblocksize;
1111 if (translen==samplesinfirstblock)
1112 {
1113 #if (HD24TRANSFERDEBUG==1)
1114 cout << "translen==samplesinfirstblock" << endl;
1115 subblockbytes=translen*bytespersam;
1116 samplesinblock=samplesinfirstblock;
1117 #endif
1118 } else {
1119 if (samplenum==0) {
1120 samplesinblock=samplesinfirstblock;
1121 }
1122 else
1123 {
1124 samplesinblock=samplesperblock;
1125 }
1126
1127 if (samplenum+samplesinblock>=translen)
1128 {
1129 subblockbytes=((translen-samplesinfirstblock) % samplesperblock ) *bytespersam;
1130 } else {
1131 if (samplesinblock!=samplesperblock)
1132 {
1133 subblockbytes=samplesinblock*bytespersam;
1134 }
1135 }
1136 }
1137
1138 #if (HD24TRANSFERDEBUG==1)
1139 cout << "samplenum=" << samplenum << ", sams in block=" << samplesinblock << endl;
1140 #endif
1141
1142 int skipsams=job->sourcesong()->getmtrackaudiodata(samplenum+job->startoffset(),samplesinblock,&audiodata[0],hd24song::READMODE_COPY);
1143 unsigned char* whattowrite=&audiodata[0];
1144 if (mustdeinterlace==1)
1145 {
1146 job->sourcesong()->deinterlaceblock(&audiodata[0],&deinterlacedata[0]);
1147 whattowrite=&deinterlacedata[0];
1148 }
1149
1150 #if (HD24TRANSFERDEBUG==1)
1151 cout << "check for split" << endl;
1152 #endif
1153 if (job->wantsplit==1)
1154 {
1155 __uint64 filesize=partsamcount;
1156 filesize+=samplesinblock;
1157 filesize*=bytespersam;
1158 if (filesize>MAXBYTES) /// total filesize reached for current part
1159 {
1160 closeoutputfiles((hd24sndfile**)&filehandle[0],channels);
1161 partnum++;
1162 openoutputfiles((hd24sndfile**)&filehandle[0],channels,partnum,prefix); // partnum is for splitting large files
1163 partsamcount=0;
1164 }
1165 }
1166
1167 // check if we need to save a mixdown
1168 if (mustmixdown)
1169 {
1170#if (HD24TRANSFERDEBUG==1)
1171 cout << "Mixing " << endl;
1172#endif
1173
1174 for (__uint32 tracknum=0;tracknum<channels;tracknum++)
1175 {
1176 unsigned char* currsam=&whattowrite[tracknum*subblocksize
1177 +((mustdeinterlace+1)*skipsams*bytespersam)];
1178 for (__uint32 samnum=0;samnum<subblockbytes;samnum+=3)
1179 {
1180 float subsamval=currsam[samnum+0]
1181 +(currsam[samnum+1]<<8)
1182 +(currsam[samnum+2]<<16);
1183
1184 if (subsamval>=(1<<23)) {
1185 subsamval-=(1<<24);
1186 }
1187 subsamval=(subsamval/(double)0x800000);
1188 mixerchannel[tracknum]->sample(samnum/3,subsamval);
1189 }
1190 }
1191 transfermixer->mix(subblockbytes/3);
1192
1193 if (outputBuffer!=NULL)
1194 {
1195 // if stereo output, interlace (TODO: check if this is what we want)
1196 for (__uint32 i=0;i<(subblockbytes/3);i++)
1197 {
1198 ((float*)outputBuffer)[i*2] = transfermixer->masterout(0,i); // left
1199 ((float*)outputBuffer)[i*2+1] = transfermixer->masterout(1,i); // right
1200 }
1201 mixdownfile->write_float(outputBuffer,(subblockbytes/3)*infoblock.channels);
1202 }
1203 }
1204 // when mixing down, let's not export raw files as well.
1205
1206 for (__uint32 tracknum=0;tracknum<channels;tracknum++)
1207 {
1208 if (job->trackselected[tracknum]==0)
1209 {
1210 // track not selected for export
1211#if (HD24TRANSFERDEBUG==1)
1212 cout << "Track " << tracknum+1 << " not selected for export " << endl;
1213#endif
1214 continue;
1215 }
1216
1217 if (transfer_cancel==1)
1218 {
1219#if (HD24TRANSFERDEBUG==1)
1220 cout << "Transfer cancelled by user. " << endl;
1221#endif
1222 break;
1223 }
1224
1225 // Mono files or multiple tracks?
1226 if (
1227 (isfirstchanofgroup[tracknum])
1228 &&(islastchanofgroup[tracknum])
1229 ) {
1230 // file is mono
1231 if (!mustmixdown) {
1232 writerawbuf(filehandle[tracknum],&whattowrite[tracknum*subblocksize+((mustdeinterlace+1)*skipsams*bytespersam)],subblockbytes);
1233 }
1234 bytestransferred+=subblockbytes;
1235 } else {
1236 if (isfirstchanofgroup[tracknum]) {
1237 // first channel of group, clear interlace buffer
1238 trackwithingroup=0;
1239#if (HD24TRANSFERDEBUG==1)
1240 cout << "first track " << samplenum << endl;
1241#endif
1242 } else {
1243 trackwithingroup++;
1244 #if (HD24TRANSFERDEBUG==1)
1245 cout << "nonfirst track " << samplenum << endl;
1246 #endif
1247 }
1248 // interlace channel onto multi channel file buffer
1249 if (!mustmixdown) {
1250 hd24utils::interlacetobuffer(&whattowrite[tracknum*subblocksize+((mustdeinterlace+1)*skipsams*bytespersam)],&interlacedata[0],subblockbytes,bytespersam,trackwithingroup,trackspergroup);
1251 }
1252
1253 if (islastchanofgroup[tracknum]) {
1254 // last channel of group, write interlace buffer to file
1255 #if (HD24TRANSFERDEBUG==1)
1256 cout << "write track " << samplenum << endl;
1257 #endif
1258 //soundfile->sf_write_raw(filehandle[tracknum],&interlacedata[0],subblockbytes*trackspergroup);
1259 if (!mustmixdown) {
1260 writerawbuf(filehandle[tracknum],&interlacedata[0],subblockbytes*trackspergroup);
1261 }
1262 bytestransferred+=subblockbytes*trackspergroup;
1263 }
1264 }
1265 }
1266 partsamcount+=(subblockbytes/bytespersam);
1267 // totsamcount+=subblockbytes;
1268
1269 __uint32 pct; // to use for display percentage
1270 double dblpct; // to use for ETA calculation
1271 #if (HD24TRANSFERDEBUG==1)
1272 cout << "about to calc pct" << endl;
1273 cout << "totbytestransferred=" << totbytestransferred;
1274 cout << ", currbytestransferred=" << bytestransferred;
1275 cout << ", totbytestotransfer=" << totbytestotransfer;
1276 cout << endl;
1277 #endif
1278
1279 /* following two calculations give the same mathematical result
1280 but help keep the required word length narrow for large numbers
1281 and reduce floating point rounding errors for small numbers.
1282 */
1283 if (tottranslen<100000)
1284 {
1285 dblpct=(
1286 (
1287 (
1288 (double)totbytestransferred
1289 +(double)bytestransferred
1290 )
1291 *(double)100
1292 )
1293 /
1294 (double)totbytestotransfer
1295 );
1296 }
1297 else
1298 {
1299 dblpct=(
1300 (
1301 (double)totbytestransferred
1302 +(double)bytestransferred
1303 )
1304 /
1305 (double)
1306 (
1307 (double)totbytestotransfer
1308 /
1309 (double)100
1310 )
1311 );
1312 }
1313 pct=(__uint32)(dblpct);
1314
1315 #if (HD24TRANSFERDEBUG==1)
1316 cout << "about to calc pct2" << endl;
1317 #endif
1318
1319 #if (HD24TRANSFERDEBUG==1)
1320 cout << "computed pct " << samplenum << endl;
1321 #endif
1322 time (&endtime);
1323 olddifseconds=difseconds;
1324 difseconds=(long long int)difftime(endtime,starttime);
1325
1326 if (((dblpct-oldpct)>=1) || ((difseconds-olddifseconds)>=1))
1327 {
1328 /* update on percentage change, and also every
1329 so many samples (to allow frequent enough
1330 screen updates with large audio files) */
1331 oldpct=dblpct;
1332
1333 string pctmsg="Transferring audio to PC... ";
1334 if (totsongs>1)
1335 {
1336 pctmsg+="Song ";
1337 string* cursongnum=Convert::int2str(songnum);
1338 pctmsg+=*cursongnum+"/";
1339 delete cursongnum;
1340 string* totsongnum=Convert::int2str(totsongs);
1341 pctmsg+=*totsongnum+", ";
1342 delete totsongnum;
1343 }
1344 string* strpct=Convert::int2str(pct);
1345 pctmsg+=*strpct+"%";
1346
1347 if (pct>0)
1348 {
1349 __uint32 estimated_seconds=(__uint32)((difseconds*100)/dblpct);
1350 __uint32 remaining_seconds=estimated_seconds-difseconds;
1351
1352 lastremain=remaining_seconds;
1353
1354 __uint32 seconds=(lastremain%60);
1355 __uint32 minutes=(lastremain-seconds)/60;
1356 __uint32 hours=0;
1357
1358 pctmsg+=" Time remaining: ";
1359
1360 if (minutes>59) {
1361 hours=(minutes/60);
1362 minutes=(minutes%60);
1363 string* strhours=Convert::int2str(hours,2,"0");
1364 pctmsg+=*strhours;
1365 pctmsg+=":";
1366 delete(strhours);
1367 }
1368
1369 string* minsec=Convert::int2str(minutes,2,"0");
1370
1371 *minsec+=":";
1372
1373 string* strsecs=Convert::int2str(seconds,2,"0");
1374 *minsec+=*strsecs;
1375 delete(strsecs);
1376
1377 pctmsg+=*minsec;
1378 delete(minsec);
1379 }
1380
1381 delete (strpct);
1382 setstatus(ui,&pctmsg,dblpct);
1383 }
1384 }
1385
1386 closeoutputfiles((hd24sndfile**)&filehandle[0],channels);
1387 for (int i=0;i<MAXCHANNELS;i++) {
1388 if (filehandle[i]!=NULL)
1389 {
1390 delete filehandle[i];
1391 }
1392 }
1393 // from now on we'll read all tracks again
1394 for (__uint32 i=1;i<=MAXCHANNELS;i++)
1395 {
1396 if (job->trackselected[i-1]==1)
1397 {
1398 job->sourcesong()->readenabletrack(i,true);
1399 }
1400 }
1401 if (audiodata!=NULL)
1402 {
1403 free (audiodata);
1404 }
1405 if (deinterlacedata!=NULL)
1406 {
1407 free (deinterlacedata);
1408 }
1409 if (interlacedata!=NULL)
1410 {
1411 free (interlacedata);
1412 }
1413 if (outputBuffer!=NULL)
1414 {
1415 free (outputBuffer);
1416 }
1417 if (mixdownfile!=NULL)
1418 {
1419 mixdownfile->close();
1420 }
1421 if (transfermixer!=NULL) {
1422 transfermixer->samplerate(oldmixersamplerate);
1423 }
1424
1425 return bytestransferred;
1426}
1427
1428void hd24transferengine::selectedformat(int i)
1429{
1430 if (i>=formatcount) return;
1431 job->selectedformat(i);
1432}
1433void hd24transferjob::selectedformat(int i)
1434{
1435 m_selectedformat=i;
1436}
1437
1438int hd24transferengine::selectedformat()
1439{
1440 return job->selectedformat();
1441}
1442int hd24transferjob::selectedformat()
1443{
1444 return m_selectedformat;
1445}
1446
1447void hd24transferengine::mixer(MixerControl* m_mixer)
1448{
1449 this->transfermixer=m_mixer;
1450}
1451
1452MixerControl* hd24transferengine::mixer()
1453{
1454 return this->transfermixer;
1455}
1456
1457string* hd24transferengine::generate_filename(int tracknum,int partnum,int prefix)
1458{
1459#if (HD24TRANSFERDEBUG==1)
1460 cout << "hd24transferengine::generate_filename(track=" << tracknum << ",part="<<partnum<<",prefix="<<prefix<<endl;
1461 cout << "Selected format="<<selectedformat() << endl;
1462#endif
1463#if (HD24TRANSFERDEBUG==1)
1464 cout << "Job="<<job<<endl;
1465#endif
1466#if (HD24TRANSFERDEBUG==1)
1467 cout << "Projdir="<<job->m_projectdir<<endl;
1468#endif
1469 if (job->m_projectdir==NULL)
1470 {
1471 cout << "No project dir set!" << endl;
1472 return NULL;
1473 }
1474 const char* pdir=job->m_projectdir->c_str(); //projectdir();
1475#if (HD24TRANSFERDEBUG==1)
1476 cout << "Projdir (const char*)="<<pdir << endl;
1477#endif
1478
1479 if (pdir==NULL)
1480 {
1481 cout << "No project dir set!" << endl;
1482 return NULL;
1483 }
1484 string* dirname=new string(pdir);
1485 if (dirname->substr(dirname->length()-1,1)!="/") {
1486 *dirname+="/";
1487 }
1488#if (HD24TRANSFERDEBUG==1)
1489 cout << "filename so far is just dir with slash=" << *dirname << endl;
1490#endif
1491 string* fname=new string(dirname->c_str());
1492 delete dirname;
1493 if (prefix!=0)
1494 {
1495 string* strsongnum=Convert::int2str(prefix,2,"0");
1496 *fname+="Song";
1497 *fname+=*strsongnum;
1498 *fname+="-";
1499 delete (strsongnum);
1500 }
1501#if (HD24TRANSFERDEBUG==1)
1502 cout << "filename so far is " << *fname << endl;
1503 cout << "About to add songname" << endl;
1504#endif
1505 if (job->sourcesong()==NULL)
1506 {
1507#if (HD24TRANSFERDEBUG==1)
1508 cout << "No song set!" << endl;
1509#endif
1510 return NULL;
1511 }
1512
1513 string* strsongname=job->sourcesong()->songname();
1514 *fname+=*strsongname;
1515 delete (strsongname);
1516
1517#if (HD24TRANSFERDEBUG==1)
1518 cout << "filename so far is " << *fname << endl;
1519 cout << "About to add track constant" << endl;
1520#endif
1521 *fname+="-Track";
1522#if (HD24TRANSFERDEBUG==1)
1523 cout << "filename so far is " << *fname << endl;
1524 cout << "About to add tracknum" << (tracknum+2) << endl;
1525#endif
1526 string* strtracknum=Convert::int2str(tracknum+1,2,"0");
1527 *fname+=*strtracknum;
1528 delete (strtracknum);
1529 if (partnum>0) {
1530 /* partnum 0 implies no splitting and thus no partnum
1531 added to the filename. In other words, we either use
1532 partnum 0 (invisible in filename), or partnum 1-n. */
1533 *fname+="_part";
1534 *fname+=*Convert::int2str(partnum);
1535 }
1536 string* extension=new string((*m_format_outputextension)[selectedformat()]);
1537 *fname+=*extension;
1538 delete extension;
1539#if (HD24TRANSFERDEBUG==1)
1540 cout << "Generated filename="<<fname<<endl;
1541#endif
1542 return fname;
1543}
1544
1545void hd24transferjob::sizelimit(__sint64 p_sizelimit)
1546{
1547 this->llsizelimit=p_sizelimit;
1548}
1549
1550__sint64 hd24transferjob::sizelimit()
1551{
1552 return this->llsizelimit;
1553}
1554
1555void hd24transferengine::sizelimit(__sint64 p_sizelimit)
1556{
1557 job->sizelimit(p_sizelimit);
1558}
1559
1560__sint64 hd24transferengine::sizelimit()
1561{
1562 return job->sizelimit();
1563}
1564
1565bool hd24transferengine::anyfilesexist(hd24song* thesong)
1566{
1567 bool anyexist=false;
1568 struct stat fi;
1569 __uint32 channels=thesong->logical_channels();
1570 for (unsigned int q=0; q<100; q++)
1571 {
1572 for (unsigned int handle=0;handle<channels;handle++)
1573 {
1574 if (job->trackselected[handle]==0)
1575 {
1576 // channel not selected for export
1577 continue;
1578 }
1579 string* fname=this->generate_filename(handle,0,q);
1580 if (fname==NULL)
1581 {
1582 // cannot generate filename (no song set?)
1583 break;
1584 }
1585#if (HD24TRANSFERDEBUG==1)
1586 cout << "check if file exists:" << *fname << endl;
1587#endif
1588 if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0))
1589 {
1590 anyexist=true;
1591#if (HD24TRANSFERDEBUG==1)
1592 cout << "yes, exists" << *fname << endl;
1593#endif
1594 delete fname;
1595 break;
1596 }
1597
1598 fname=this->generate_filename(handle,1,q);
1599 if (fname==NULL)
1600 {
1601 // cannot generate filename (no song set?)
1602 break;
1603 }
1604#if (HD24TRANSFERDEBUG==1)
1605 cout << "check if file exists:" << *fname << endl;
1606#endif
1607 if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0))
1608 {
1609 anyexist=true;
1610#if (HD24TRANSFERDEBUG==1)
1611 cout << "yes, exists" << *fname << endl;
1612#endif
1613 delete fname;
1614 break;
1615 }
1616#if (HD24TRANSFERDEBUG==1)
1617 cout << "no, doesnt exist" << endl;
1618#endif
1619
1620 delete fname;
1621 }
1622 if (anyexist==true) break;
1623 }
1624 return anyexist;
1625}
1626
1627void hd24transferengine::setstatus(void* ui,string* message,double percentage)
1628{
1629#if (HD24TRANSFERDEBUG==1)
1630 printf(message->c_str(),percentage);
1631 cout << endl;
1632#endif
1633 if (setstatusfunction!=NULL)
1634 {
1635 setstatusfunction(ui,message->c_str(),percentage);
1636 }
1637 return;
1638}
1639
1640void hd24transferengine::set_ui(void* p_ui)
1641{
1642 this->ui=p_ui;
1643}
1644
1645void hd24transferengine::sourcesong(hd24song* song)
1646{
1647#if (HD24TRANSFERDEBUG==1)
1648 cout << "hd24transferengine::sourcesong(" << song << ")" << endl;
1649#endif
1650 if (this->job==NULL)
1651 {
1652 return;
1653 }
1654 this->job->sourcesong(song);
1655}
1656
1657hd24song* hd24transferengine::sourcesong()
1658{
1659#if (HD24TRANSFERDEBUG==1)
1660 cout << "hd24transferengine::sourcesong()="
1661 << this->job->sourcesong()<< endl;
1662#endif
1663 if (this->job==NULL)
1664 {
1665 return NULL;
1666 }
1667 return this->job->sourcesong();
1668}
1669
1670void hd24transferengine::startoffset(__uint32 newoff)
1671{
1672 job->startoffset(newoff);
1673}
1674
1675void hd24transferengine::endoffset(__uint32 newoff)
1676{
1677 job->endoffset(newoff);
1678}
1679
1680__uint32 hd24transferengine::startoffset()
1681{
1682 return job->startoffset();
1683}
1684
1685__uint32 hd24transferengine::endoffset()
1686{
1687 return job->endoffset();
1688}
1689
1690void hd24transferengine::targetsong(hd24song* song)
1691{
1692 if (job==NULL)
1693 {
1694 return;
1695 }
1696 job->targetsong(song);
1697}
1698
1699hd24song* hd24transferengine::targetsong()
1700{
1701 if (job==NULL)
1702 {
1703 return NULL;
1704 }
1705 return job->targetsong();
1706}
1707
1708__sint64 hd24transferengine::transfer_to_hd24()
1709{
1710 if (job->targetsong()==NULL)
1711 {
1712 lasterror("No target song selected, transfer aborted.");
1713 return 0;
1714 }
1715 if (soundfile==NULL)
1716 {
1717 lasterror("soundfile library not defined, transfer aborted");
1718 return 0;
1719 }
1720 job->targetsong()->golocatepos(0);
1721 job->targetsong()->startrecord(hd24song::WRITEMODE_COPY);
1722
1723 //mustdisplaytimer=false;
1724 __sint64 bytestransferred=0;
1725
1726 for (unsigned int currchan=0;currchan<MAXCHANNELS;currchan++) {
1727 job->filehandle[currchan]=NULL;
1728 audiobuf[currchan]=NULL;
1729 }
1730 SF_INFO sfinfoin[24];
1731 bool canopen=this->openinputfiles((SNDFILE**)&(job->filehandle[0]),(SF_INFO*)&sfinfoin[0],job->targetsong()->logical_channels());
1732 if (!canopen)
1733 {
1734 return 0;
1735 }
1736 // Find file with largest number of samples;
1737 // if song is shorter than that, lengthen song to fit it.
1738 __sint64 translen=job->targetsong()->songlength_in_samples();
1739 __uint32 maxlen=(__uint32)translen;
1740 bool mustlengthensong=false;
1741 for (int i=0;i<MAXCHANNELS;i++) {
1742 if (job->filehandle[i]==NULL) continue;
1743 if (((__sint64)sfinfoin[i].frames) > (__sint64)maxlen) {
1744 maxlen=sfinfoin[i].frames;
1745 mustlengthensong=true;
1746 }
1747 }
1748 if (mustlengthensong) {
1749 string* lengthening=new string("Transferring audio to HD24... ");
1750 setstatus(ui,lengthening,0);
1751 delete lengthening;
1752 #if (HD24TRANSFERDEBUG==1)
1753 cout << "about to start lengthening song to maxlen=" << maxlen << endl;
1754 #endif
1755 bool clearnew=false; // do not silence newly allocated part
1756 // (it is done automatically during transfer)
1757 translen=job->targetsong()->songlength_in_samples(maxlen,clearnew);
1758 #if (HD24TRANSFERDEBUG==1)
1759 cout << "verifying actual song length " << endl;
1760 cout << "new len=" << translen << endl;
1761 #endif
1762 if (translen!=maxlen)
1763 {
1764 #if (HD24TRANSFERDEBUG==1)
1765 cout << "new len<> maxlen so not enough space." << endl;
1766 #endif
1767 this->lasterror("Not enough space on HD24 drive.");
1768 return 0;
1769 }
1770 job->targetsong()->save();
1771 // ui_refresh("tohd24");
1772 #if (HD24TRANSFERDEBUG==1)
1773 cout << "translen is now " << translen << endl;
1774 #endif
1775
1776 }
1777 hd24fs* currenthd24=job->targetfs();
1778 int blocksize=currenthd24->getbytesperaudioblock();
1779 // to hold normally read audio data:
1780 unsigned char* audiodata=NULL;
1781 transfer_cancel=0;
1782// ui->stop_transfer->show();
1783
1784 audiodata=(unsigned char*)memutils::mymalloc("button_transfertohd24",blocksize,1);
1785 __uint32 channels=job->targetsong()->logical_channels();
1786 __uint32 bytespersam=(job->targetsong()->bitdepth()/8);
1787 __uint32 samplesperblock=(blocksize/channels)/bytespersam;
1788 job->smptegen=new SMPTEgenerator(job->targetsong()->samplerate());
1789
1790 for (unsigned int fh=0;fh<MAXCHANNELS;fh++) {
1791 int action=job->trackaction(fh+1);
1792 if ((job->filehandle[fh]!=NULL)||(action<=1 /* erase, SMPTE stripe */)) {
1793 __uint32 chans=((action==0)||(action==1))?(1):(sfinfoin[fh].channels);
1794 __uint32 bytestoalloc=chans*samplesperblock*sizeof(int);
1795 audiobuf[fh]=(int*)memutils::mymalloc(
1796 "button_transfertohd24 audiobuf",bytestoalloc,1
1797 );
1798
1799 if (action == 0) {
1800 // clear erase buffer once
1801 int* buf=audiobuf[fh];
1802 for (__uint32 samnum=0;samnum<samplesperblock;samnum++) {
1803 buf[samnum]=0;
1804 }
1805 }
1806 if (action == 1) {
1807 // clear SMPTE buffer once (mostly for debugging purposes)
1808 int* buf=audiobuf[fh];
1809 for (__uint32 samnum=0;samnum<samplesperblock;samnum++) {
1810 buf[samnum]=1;
1811 }
1812 }
1813 // if action==1, we need to repopulate the buffer while striping
1814 } else {
1815 audiobuf[fh]=NULL;
1816 }
1817 }
1818
1819 // number of samples in current block- equal to block samples for full song
1820 // transfer
1821 __uint32 subblocksize=samplesperblock*bytespersam;
1822
1823 int mustinterlace=0;
1824 if ((job->targetsong()->samplerate())>=88200)
1825 {
1826 mustinterlace=1;
1827 }
1828 #if (HD24TRANSFERDEBUG==1)
1829 cout << "Channels="<<channels << endl;
1830 #endif
1831 __uint32 startoffset=0;
1832 //__uint32 endoffset=currsong->songlength_in_samples();
1833 __uint32 samplesinfirstblock=samplesperblock;
1834
1835 job->targetsong()->getlocatepos(25); // 25= virtual endpoint of song
1836 // calc number of samples to transfer.
1837 // for high samplerate songs, this is twice the songlength.
1838 // (for partial transfers, which are not supported at this time, the
1839 // number of samples is based on (endoffset-startoffset) instead of songlength
1840 translen=job->targetsong()->songlength_in_samples()*(job->targetsong()->physical_channels()/job->targetsong()->logical_channels());
1841 __uint64 totbytestotransfer=translen*bytespersam;
1842 //transfer_to_hd24();
1843
1844 if (startoffset!=0) {
1845 if (startoffset>=samplesperblock) {
1846 samplesinfirstblock=samplesperblock-(startoffset%samplesperblock);
1847 } else {
1848 samplesinfirstblock=samplesperblock-startoffset;
1849 }
1850 }
1851 #if (HD24TRANSFERDEBUG==1)
1852 cout << "go to startoffset " << startoffset << endl;
1853 #endif
1854 job->targetsong()->golocatepos(startoffset);
1855 #if (HD24TRANSFERDEBUG==1)
1856 cout << "got to startoffset " << startoffset << endl;
1857 cout << "translen= " << translen << endl;
1858 #endif
1859
1860 __uint32 samplesinblock=samplesinfirstblock;
1861 if (translen<samplesperblock)
1862 {
1863 samplesinfirstblock=translen;
1864 }
1865
1866 __sint64 difseconds=0;
1867 __sint64 olddifseconds=0;
1868 __uint64 totbytestransferred=0; // only for multi song transfer- does not apply.
1869 //deactivate_ui();
1870 for (__uint32 samplenum=0;
1871 samplenum<translen;
1872 samplenum+=samplesinblock)
1873 {
1874 if (transfer_cancel==1)
1875 {
1876 //ui_refresh("tohd24_cancel");
1877 break;
1878 }
1879 #if (HD24TRANSFERDEBUG==1)
1880 cout << "samnum= " << samplenum << endl;
1881 #endif
1882 __uint32 subblockbytes=subblocksize;
1883 if (translen==samplesinfirstblock)
1884 {
1885 #if (HD24TRANSFERDEBUG==1)
1886 cout << "translen==samplesinfirstblock" << endl;
1887 subblockbytes=translen*bytespersam;
1888 samplesinblock=samplesinfirstblock;
1889 #endif
1890 } else {
1891 if (samplenum==0) {
1892 samplesinblock=samplesinfirstblock;
1893 }
1894 else
1895 {
1896 samplesinblock=samplesperblock;
1897 }
1898
1899 if (samplenum+samplesinblock>=translen)
1900 {
1901 subblockbytes=((translen-samplesinfirstblock) % samplesperblock ) *bytespersam;
1902 } else {
1903 if (samplesinblock!=samplesperblock)
1904 {
1905 subblockbytes=samplesinblock*bytespersam;
1906 }
1907 }
1908 }
1909
1910 #if (HD24TRANSFERDEBUG==1)
1911 cout << "samplenum=" << samplenum << ", sams in block=" << samplesinblock << endl;
1912 #endif
1913
1914 /*
1915 // disable multipart files for now (this function transfers TO HD24 drives)
1916 if (wantsplit==1)
1917 {
1918 if (((partsamcount+samplesinblock)*bytespersam)>MAXBYTES) /// total filesize reached for current part
1919 {
1920 this->closeoutputfiles((SNDFILE**)&filehandle[0],channels);
1921 partnum++;
1922 this->openoutputfiles((SNDFILE**)&filehandle[0],channels,partnum,prefix); // partnum is for splitting large files
1923 partsamcount=0;
1924 }
1925 }
1926 */
1927 for (__uint32 tracknum=0;tracknum<channels;tracknum++)
1928 {
1929 if (!(job->targetsong()->trackarmed(tracknum+1)))
1930 {
1931 // track not selected for export
1932 continue;
1933 }
1934 __uint32 samsread=0;
1935 int action=job->trackaction(tracknum+1);
1936 unsigned int trackchans=1;
1937
1938 if (action==0) { /* 0=ERASE */
1939 #if (HD24TRANSFERDEBUG==1)
1940 cout << "track " << tracknum+1 << " marked for erase" << endl;
1941
1942 #endif
1943 samsread=samplesinblock;
1944 } else {
1945 if (action==1)
1946 {
1947 #if (HD24TRANSFERDEBUG==1)
1948 cout << "track " << tracknum+1 << " marked for stripe" << endl;
1949
1950 #endif
1951 /* Stripe track with SMPTE/LTC here */
1952
1953 int* buf=audiobuf[tracknum];
1954
1955 for (__uint32 samnum=0;samnum<samplesinblock;samnum++) {
1956 // smpte stripe:
1957 buf[samnum]=((job->smptegen->getbit(samplenum+samnum)*2)-1)*2000000;
1958 }
1959 /* End of stripe */
1960 samsread=samplesinblock;
1961 } else {
1962 trackchans=sfinfoin[tracknum].channels;
1963 if (job->filehandle[tracknum] == NULL) {
1964 continue;
1965 }
1966 samsread=soundfile->sf_read_int(
1967 job->filehandle[tracknum],
1968 audiobuf[tracknum],
1969 samplesinblock*trackchans);
1970 #if (HD24TRANSFERDEBUG==1)
1971 cout << "sams read="
1972 << samsread
1973 << endl;
1974 #endif
1975 }
1976 }
1977 // we replace the deinterlaced data with file audio
1978 //sf_write_raw(filehandle[tracknum],&whattowrite[tracknum*subblocksize+((mustdeinterlace+1)*skipsams*bytespersam)],subblockbytes);
1979
1980
1981
1982 // cout << "replace audio block on track " << tracknum+1 << endl;
1983
1984 //filehandle[tracknum];
1985
1986 // libsndfile converts all files to 32-bit samples, but we only use 24 bit,
1987 // so we divide by 256 to shift out the unused 8 bits.
1988
1989 __uint32 firstbyte=tracknum*samplesinblock*bytespersam;
1990 __uint32 whichbyte=firstbyte;
1991
1992 int samval;
1993 for (unsigned int sam=0;sam<samsread;sam+=trackchans)
1994 {
1995 int whichsam=sam;
1996 if (action>2) {
1997 // multi track
1998 // use only 24 out of 32 bit
1999 samval = (audiobuf[tracknum][whichsam+(action-3)])/256;
2000 } else {
2001 if (action<2)
2002 {
2003 samval=(audiobuf[tracknum][whichsam]);
2004 } else {
2005 // action=2 (mono track).
2006 if (trackchans==1)
2007 {
2008 // use the only track
2009 samval=(audiobuf[tracknum][whichsam])/256;
2010 }
2011 else {
2012 // convert multiple tracks to 1 mono track
2013 samval=0;
2014 for (unsigned int whichchan=0;whichchan<trackchans;whichchan++) {
2015 samval+=(audiobuf[tracknum][whichsam+whichchan])/256;
2016 }
2017 // TODO: clip handling
2018 samval/=trackchans;
2019 }
2020 }
2021 }
2022#if (HD24TRANSFERDEBUG==1)
2023 cout << "whichsam=" << whichsam << " " ;//
2024
2025
2026 cout << "buf[" << tracknum*samplesinblock+(whichsam*bytespersam) << "]=";
2027 cout << (samval & 0xff) << " " << ((samval>>8) & 0xff) << " " << ((samval>>16) & 0xff) <<"//";
2028 if (sam==0) {
2029 cout << "writing to byte " << whichbyte << " of audiodata " <<endl;
2030 }
2031#endif
2032 audiodata[whichbyte]=(unsigned char)samval & 0xff;
2033 audiodata[whichbyte+1]=(unsigned char)(samval>>8) & 0xff;
2034 audiodata[whichbyte+2]=(unsigned char)(samval>>16) & 0xff;
2035 whichbyte+=bytespersam;
2036 }
2037 // cout << endl;
2038
2039 if (transfer_cancel==1) {
2040 //ui_refresh("tohd24_cancel2");
2041 break;
2042 }
2043 }
2044
2045 // finally we write the audio. the hd24 library will make sure only the relevant
2046 // tracks will be overwritten and the rest are protected.
2047 #if (HD24TRANSFERDEBUG==1)
2048 cout << "1st 30 bytes of track: " << endl;
2049 for (unsigned int fbyte=0; fbyte<30; fbyte++) {
2050 cout << audiodata[samplesinblock+fbyte] << " ";
2051 }
2052 cout << endl;
2053 #endif
2054 //int writesams= (result was not used)
2055 job->targetsong()->putmtrackaudiodata(
2056 samplenum+startoffset,
2057 samplesinblock,
2058 &audiodata[0],
2059 hd24song::WRITEMODE_COPY
2060 );
2061
2062 totbytestransferred+=(samplesinblock*bytespersam);
2063
2064 __uint32 pct; // to use for display percentage
2065 __uint32 oldpct=0; // to use for display percentage
2066 double dblpct; // to use for ETA calculation
2067 #if (HD24TRANSFERDEBUG==1)
2068 cout << "about to calc pct" << endl;
2069 cout << "totbytestransferred=" << totbytestransferred;
2070 cout << ", currbytestransferred=" << bytestransferred;
2071 cout << ", totbytestotransfer=" << totbytestotransfer;
2072 cout << endl;
2073 #endif
2074
2075 if (translen<100000) {
2076 pct=(__uint32)(((totbytestransferred+bytestransferred)*100)/(totbytestotransfer));
2077 } else {
2078 pct=(__uint32)((totbytestransferred+bytestransferred)/(totbytestotransfer/100));
2079 }
2080 #if (HD24TRANSFERDEBUG==1)
2081 cout << "about to calc pct2" << endl;
2082 #endif
2083 if (translen<100000) {
2084 dblpct=(((totbytestransferred+bytestransferred)*100)/(totbytestotransfer));
2085 } else {
2086 dblpct=((totbytestransferred+bytestransferred)/(totbytestotransfer/100));
2087 }
2088
2089 #if (HD24TRANSFERDEBUG==1)
2090 cout << "computed pct " << samplenum << endl;
2091 #endif
2092 time (&endtime);
2093 olddifseconds=difseconds;
2094 difseconds=(long long int)difftime(endtime,starttime);
2095
2096 if ((pct!=oldpct) || ((difseconds-olddifseconds)>=1))
2097 {
2098 /* update on percentage change, and also every
2099 so many samples (to allow frequent enough
2100 screen updates with large audio files) */
2101 oldpct=pct;
2102
2103 string* pctmsg=new string("Transferring audio to HD24... %d%%");
2104 // TODO: Estimated time remaining goes here
2105 setstatus(ui,pctmsg,pct);
2106 delete pctmsg;
2107 }
2108
2109 // fl_check(); covered by setstatus
2110 }
2111
2112 // fl_check(); covered by setstatus
2113 if (job->smptegen!=NULL)
2114 {
2115 // TODO: move to job destructor?
2116 delete job->smptegen;
2117 job->smptegen=NULL;
2118 }
2119 if (audiodata!=NULL)
2120 {
2121 free (audiodata);
2122 audiodata=NULL;
2123 }
2124 for (unsigned int bufnum=0;bufnum<MAXCHANNELS;bufnum++) {
2125 if (audiobuf[bufnum]!=NULL) {
2126 memutils::myfree("audiobuf transfer_to_hd24",audiobuf[bufnum]);
2127 audiobuf[bufnum]=NULL;
2128 }
2129 }
2130
2131 //end transfer_to_hd24
2132
2133
2134
2135 job->targetsong()->stoprecord();
2136
2137 for (unsigned int chnum=1;chnum<=job->targetsong()->logical_channels();chnum++) {
2138 job->targetsong()->trackarmed(chnum,false);
2139 }
2140 this->closeinputfiles((SNDFILE**)&(job->filehandle[0]),job->targetsong()->logical_channels());
2141 return totbytestransferred;
2142}
2143