aboutsummaryrefslogtreecommitdiff
path: root/src/lib/hd24utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/hd24utils.cpp')
-rwxr-xr-xsrc/lib/hd24utils.cpp637
1 files changed, 637 insertions, 0 deletions
diff --git a/src/lib/hd24utils.cpp b/src/lib/hd24utils.cpp
new file mode 100755
index 0000000..6efb3a7
--- /dev/null
+++ b/src/lib/hd24utils.cpp
@@ -0,0 +1,637 @@
1#define UTILDEBUG 0
2#ifdef DARWIN
3# define creat64 creat
4# define open64 open
5# define lseek64 lseek
6# define pread64 pread
7# define pwrite64 pwrite
8#endif
9
10#if defined(LINUX) || defined(DARWIN)
11# define PRINTAPP "lp"
12#endif
13
14#ifdef WINDOWS
15# include <windows.h>
16# include <shellapi.h>
17# define PRINTAPP "print"
18# define popen _popen
19# define pclose _pclose
20#else
21# include <unistd.h>
22#endif
23
24#include <string>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <fcntl.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <iostream>
31#include <fstream>
32#include <math.h>
33#include <hd24devicenamegenerator.h>
34#include <FL/FLTKstuff.H>
35#include <FL/Fl_Preferences.H>
36#include <FL/filename.H>
37#include "convertlib.h"
38#include "hd24utils.h"
39#include "memutils.h"
40#define _LARGE_FILES
41#define LARGE_FILES
42#define LARGEFILE64_SOURCE
43#define _FILE_OFFSET_BITS 64
44#define FILE_OFFSET_BITS 64
45#define SECTORSIZE 512
46#define FSINFO_VERSION_MAJOR 0x8
47#define FSINFO_VERSION_MINOR 0x9
48#define FSINFO_BLOCKSIZE_IN_SECTORS 0x10
49#define FSINFO_AUDIOBLOCKS_PER_CLUSTER 0x14
50#define FSINFO_STARTSECTOR_FAT 0x38
51#define FSINFO_NUMSECTORS_FAT 0x3c
52#define FSINFO_CLUSTERS_ON_DISK 0x44
53#define FSINFO_MAXPROJECTS 0x50
54#define FSINFO_MAXSONGSPERPROJECT 0x54
55#define FSINFO_DATAAREA 0x7c
56#define DRIVEINFO_VOLUME 0x1b8
57#define DRIVEINFO_PROJECTCOUNT 0x0c
58#define DRIVEINFO_LASTPROJ 0x10
59#define DRIVEINFO_PROJECTLIST 0x20
60
61void hd24utils::gencatalog_showsongs(hd24project* currentproj,string* strcatalog)
62{
63 if (currentproj==NULL) {
64 return;
65 }
66 if (strcatalog==NULL) {
67 return;
68 }
69 int numsongs=currentproj->songcount();
70 *strcatalog+=" ======================================================================\n";
71 if (numsongs==0) {
72 *strcatalog+=" There are no songs in this project.\n";
73 return;
74 }
75 hd24song* currsong=NULL;
76 for (int i=1; i<=numsongs; i++) {
77 currsong=currentproj->getsong(i);
78 if (currsong==NULL) continue;
79
80 *strcatalog+=" ";
81 *strcatalog+=" ";
82 if (i<10) {
83 *strcatalog+=" ";
84 }
85 string* songnum=Convert::int2str(i);
86 *strcatalog+=*songnum;
87 *strcatalog+=": ";
88 delete songnum;
89
90 string* currsname=currsong->songname();
91 string* pad=Convert::padright(*currsname,35," ");
92 delete(currsname);
93 *strcatalog+=*pad;
94 delete pad;
95 string* dur=currsong->display_duration();
96 *strcatalog+=*dur;
97 delete dur;
98 *strcatalog+= ", " ;
99
100 string* chans=Convert::int2str(currsong->logical_channels());
101 string* chans2=Convert::padleft(*chans,2," ");
102 *strcatalog+=*chans;
103 delete chans;
104 delete chans2;
105 *strcatalog+="ch. ";
106
107 string* samrate=Convert::int2str(currsong->samplerate());
108 *strcatalog+=*samrate;
109 delete samrate;
110 *strcatalog+=" Hz";
111
112
113 if (currsong->iswriteprotected())
114 {
115 *strcatalog+="*";
116 }
117
118 *strcatalog+="\n";
119
120 delete currsong;
121 currsong=NULL;
122 }
123 return;
124}
125
126void hd24utils::gencatalog_showprojects(hd24fs* currenthd24,string* strcatalog)
127{
128 int numprojs=currenthd24->projectcount();
129 hd24project* currproj=NULL;
130 for (int i=1; i<=numprojs; i++)
131 {
132 currproj=currenthd24->getproject(i);
133
134 *strcatalog+=" ======================================================================\n";
135 *strcatalog+=" Project ";
136 string* projnum=Convert::int2str(i);
137 *strcatalog+=*projnum;
138 delete projnum;
139 *strcatalog+=": ";
140
141 string* currpname=currproj->projectname();
142 *strcatalog+= *currpname;
143 delete(currpname);
144
145 *strcatalog+="\n"; // << endl;
146 gencatalog_showsongs (currproj,strcatalog); //to_out);
147 delete(currproj);
148 }
149
150}
151
152int hd24utils::gencatalog(hd24fs* currenthd24,string* strcatalog)
153{
154
155 time_t currenttime;
156 struct tm timestamp;
157 char timebuf[80];
158 time(&currenttime);
159 timestamp = *localtime(&currenttime);
160 strftime(timebuf,sizeof(timebuf),"%a %Y-%m-%d %H:%M:%S %Z", &timestamp);
161 *strcatalog+= " Catalog timestamp : ";
162 *strcatalog+= timebuf ;
163 *strcatalog+="\n";
164
165 *strcatalog+=" Volume name : ";
166 string* volname=currenthd24->volumename();
167 *strcatalog+=*volname;
168 delete volname;
169 *strcatalog+="\n";
170
171 *strcatalog+=" Number of projects : ";
172 string* pcount=Convert::int2str(currenthd24->projectcount());
173 *strcatalog+=*pcount;
174 delete pcount;
175
176 *strcatalog+="\n";
177 gencatalog_showprojects(currenthd24,strcatalog);
178 return 0;
179}
180
181string* hd24utils::savecatalog(hd24fs* currenthd24,string* filename)
182{
183 string* error=new string("");
184
185 // gencatalog
186 string* catalog=new string("");
187
188 if (hd24utils::gencatalog(currenthd24,catalog)!=0)
189 {
190 *error+="Error generating catalog.";
191 return error;
192 }
193 fstream to_out(filename->c_str(),ios::out);
194 if (to_out==NULL)
195 {
196 *error+="Cannot write catalog.";
197 return error;
198 }
199 to_out << *catalog ;
200
201 to_out.flush();
202 to_out.close();
203 return NULL;
204}
205
206string* hd24utils::printcatalog(hd24fs* currenthd24)
207{
208
209 string* error=new string("");
210 string catname="_hd24cat.txt";
211
212
213 // gencatalog
214 string* catalog=new string("");
215
216 if (hd24utils::gencatalog(currenthd24,catalog)!=0)
217 {
218 *error+="Error generating catalog.";
219 return error;
220 }
221 fstream to_out(catname.c_str(),ios::out);
222 if (to_out==NULL)
223 {
224 *error+="Cannot write catalog.";
225 return error;
226 }
227 *catalog += "\f\n"; // form feed
228 to_out << *catalog ;
229
230 to_out.flush();
231 to_out.close();
232
233#ifdef WINDOWS
234 SHELLEXECUTEINFO ShExecInfo = {0};
235 ShExecInfo.cbSize = sizeof (SHELLEXECUTEINFO);
236 ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; //SEE_MASK_INVOKEIDLIST;
237 ShExecInfo.hwnd = NULL;
238 ShExecInfo.lpVerb="print";
239 ShExecInfo.lpFile=catname.c_str();
240 ShExecInfo.lpParameters = "";
241 ShExecInfo.lpDirectory=NULL;
242 ShExecInfo.nShow = SW_HIDE;
243 ShExecInfo.hInstApp = NULL;
244 ShellExecuteEx(&ShExecInfo);
245 WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
246 unlink (catname.c_str());
247#else
248 char s[1024];
249 string* catcmd = new string (PRINTAPP);
250 *catcmd += " ";
251 *catcmd += catname;
252 *catcmd += " 2>&1";
253 FILE *fp = popen(catcmd->c_str() , "r");
254 while (fgets(s, sizeof(s)-1, fp))
255 {
256 *error += s;
257 }
258 pclose(fp);
259 unlink (catname.c_str());
260#endif
261 return error;
262}
263
264
265void hd24utils::interlacetobuffer(unsigned char* sourcebuf,unsigned char* targetbuf,
266 __uint32 totbytes,__uint32 bytespersam,__uint32 trackwithingroup,__uint32 trackspergroup)
267{
268 __uint32 samplenum;
269 __uint32 totsams=totbytes/bytespersam;
270 __uint32 trackoff=(trackwithingroup*bytespersam);
271 __uint32 q=0;
272 // unroll loop for bytespersam=1,2,3
273 switch (bytespersam)
274 {
275 case 3:
276 for (samplenum=0;samplenum<totsams;samplenum++)
277 {
278 __uint32 samoff=(samplenum*bytespersam);
279 q=trackspergroup*samoff+trackoff;
280 targetbuf[q++]=sourcebuf[samoff];
281 targetbuf[q++]=sourcebuf[samoff+1];
282 targetbuf[q++]=sourcebuf[samoff+2];
283 }
284 break;
285 case 1:
286 for (samplenum=0;samplenum<totsams;samplenum++)
287 {
288 __uint32 samoff=(samplenum*bytespersam);
289 q=trackspergroup*samoff+trackoff;
290 targetbuf[q]=sourcebuf[samoff];
291 }
292 break;
293 case 2:
294 for (samplenum=0;samplenum<totsams;samplenum++)
295 {
296 __uint32 samoff=(samplenum*bytespersam);
297 q=trackspergroup*samoff+trackoff;
298 targetbuf[q++]=sourcebuf[samoff];
299 targetbuf[q++]=sourcebuf[samoff+1];
300 }
301 break;
302 default:
303 for (samplenum=0;samplenum<totsams;samplenum++)
304 {
305 __uint32 samoff=(samplenum*bytespersam);
306 q=trackspergroup*samoff;
307 for (__uint32 j=0; j<bytespersam; j++) {
308 targetbuf[q+j+trackoff]=sourcebuf[samoff+j];
309 }
310 }
311 break;
312 }
313}
314
315bool hd24utils::dirExists(const char * pszDirName)
316{
317#ifdef WIN32
318 unsigned int dwAttrs;
319 if (!(pszDirName))
320 {
321 //setupLog(NULL, "DirExists failed: passed in NULL parameter for directory");
322 return (1==0);
323 }
324 dwAttrs = GetFileAttributes(pszDirName);
325 if ((dwAttrs != 0xFFFFFFFF) && (dwAttrs & FILE_ATTRIBUTE_DIRECTORY))
326 {
327 return (1==1);
328 }
329 return (1==0);
330#else
331 struct stat fi;
332
333 if (stat (pszDirName, &fi) == -1 || !S_ISDIR(fi.st_mode))
334 {
335 return (1==0);
336 }
337 else
338 {
339 return (1==1);
340 }
341#endif
342}
343int hd24utils::savedrivesectors(hd24fs* currenthd24,string* outputfilename,unsigned long firstsector,unsigned long endsector,char* message,int* cancel) {
344 unsigned long i;
345#define MULTISECTOR 100
346 unsigned char bootblock[(MULTISECTOR+1)*512]; // 1 sector spare
347 memset(bootblock,0,MULTISECTOR*512);
348#if defined(LINUX) || defined(DARWIN)
349#if (UTILDEBUG==1)
350 cout << "creat64" << endl;
351#endif
352 FSHANDLE handle=creat64(outputfilename->c_str(),O_WRONLY);
353#endif
354#ifdef WINDOWS
355 FSHANDLE handle=CreateFile(outputfilename->c_str(),GENERIC_WRITE|GENERIC_READ,
356 FILE_SHARE_READ|FILE_SHARE_WRITE,
357 NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
358 if (hd24fs::isinvalidhandle(handle)) {
359 handle=CreateFile(outputfilename->c_str(),GENERIC_WRITE|GENERIC_READ,
360 FILE_SHARE_READ|FILE_SHARE_WRITE,
361 NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
362 }
363
364 #endif
365 if (hd24fs::isinvalidhandle(handle)) {
366 // cout << "Cannot open file "<<filename <<" for writing. Access denied?" << endl;
367 return 1;
368 }
369 int q=0;
370 for (i=firstsector;i<=endsector;i++) {
371 q++;
372 int numsectors=1;
373 if ((endsector-i) >=MULTISECTOR) {
374 numsectors=MULTISECTOR;
375 }
376 if (currenthd24!=NULL) {
377 currenthd24->readsector_noheader(currenthd24,i,bootblock); // raw reading
378 }
379#if defined(LINUX) || defined(DARWIN)
380 __uint64 targetoff=i;
381 targetoff-=firstsector;
382 targetoff*=512;
383 ssize_t byteswritten=0;
384 if (currenthd24!=NULL) {
385 byteswritten=pwrite64(handle,bootblock,512,targetoff);
386 } else {
387 byteswritten=pwrite64(handle,bootblock,512*numsectors,targetoff);
388 i+=(numsectors-1);
389 }
390#endif
391#ifdef WINDOWS
392 //DWORD dummy;
393 //long bytes=0;
394 __uint64 targetoff=i;
395 targetoff-=firstsector;
396 __uint64 byteswritten=0;
397 if (currenthd24!=NULL) {
398 byteswritten=currenthd24->writesectors(handle,targetoff,bootblock,1);
399 } else {
400 byteswritten=currenthd24->writesectors(handle,targetoff,bootblock,numsectors);
401 i+=(numsectors-1);
402 }
403#endif
404 if (byteswritten==0) {
405#if defined(LINUX) || defined(DARWIN)
406 close (handle);
407#endif
408#ifdef WINDOWS
409 CloseHandle(handle);
410#endif
411 return 1;
412 }
413 if (message!=NULL) {
414 if (q%1000==0) {
415 sprintf(message,"Saving sector %ld of %ld",i,(endsector+1));
416
417 // cout << i << endl;
418 Fl::wait(0);
419 }
420 }
421 }
422#if defined(LINUX) || defined(DARWIN)
423 close (handle);
424 chmod(outputfilename->c_str(),0664);
425#endif
426#ifdef WINDOWS
427 CloseHandle(handle);
428#endif
429
430 return 0;
431}
432
433int hd24utils::savedriveimage(hd24fs* currenthd24,string* imagefilename,char* message,int* cancel) {
434 unsigned long firstsector=0;
435 unsigned long endsector=currenthd24->getlastsectornum();
436 return savedrivesectors(currenthd24,imagefilename,firstsector,endsector,message,cancel);
437}
438
439int hd24utils::newdriveimage(string* imagefilename,__uint32 endsector,char* message,int* cancel) {
440 if (endsector<1353964)
441 {
442 // requested drive size is less than possible minimum size
443 return -1;
444 }
445
446 unsigned long firstsector=0;
447#if (UTILDEBUG==1)
448cout << "about to save drive sectors" <<endl;
449#endif
450 int result=savedrivesectors(NULL,imagefilename,firstsector,endsector,message,cancel);
451 if (result!=0)
452 {
453 return result;
454 }
455#if (UTILDEBUG==1)
456cout << "saved drive sectors, creating new fs object to format" <<endl;
457#endif
458 hd24fs* newfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,imagefilename,true);
459#if (UTILDEBUG==1)
460cout << "write enabling fs" <<endl;
461#endif
462 newfs->write_enable();
463#if (UTILDEBUG==1)
464cout << "quickformatting fs" <<endl;
465#endif
466 newfs->quickformat(message);
467#if (UTILDEBUG==1)
468 cout << "format result=" << *message << endl;
469cout << "deleting format fs object" <<endl;
470#endif
471 delete newfs;
472#if (UTILDEBUG==1)
473cout << "destructed fs object" <<endl;
474#endif
475 return 0;
476}
477
478void hd24utils::dumpsector(const char* buffer)
479{
480 for (int i=0;i<512;i+=16) {
481 string* dummy=Convert::int32tohex(i);
482 cout << *dummy << " ";
483 delete dummy; dummy=NULL;
484 for (int j=0;j<16;j++) {
485 string* dummy= Convert::byte2hex(buffer[i+j]);
486 cout << *dummy;
487 if (j==7) {
488 cout << "-" ;
489 } else {
490 cout << " " ;
491 }
492 delete dummy; dummy=NULL;
493 }
494 cout << " ";
495 for (int j=0;j<16;j++) {
496 cout << Convert::safebyte(buffer[i+j]);
497 }
498 cout << "" << endl;
499 }
500}
501int hd24utils::saveheader(hd24fs* currenthd24,string* headerfilename) {
502 return savedrivesectors(currenthd24,headerfilename,0,0x700,NULL,NULL);
503 // TODO: 0x700 sectors is arbitrary. First song entry is at 0x77,
504 // total of 99*99 songs of 7 sectors each puts actual required length
505 // at 0x10c76. However, this has served fine so far.
506
507}
508
509void hd24utils::findfile(const char* rawname,const char* path,char* result)
510{
511 string* strpath=new string(path);
512#ifdef WINDOWS
513 string* pathsep=new string(";");
514#else
515 string* pathsep=new string(":");
516#endif
517 int last=0;
518 string* exename;
519 string* exepath;
520#if (UTILDEBUG==1)
521 cout << "search path for exe " << endl;
522#endif
523 while (last==0)
524 {
525 unsigned int idx=strpath->find(pathsep->c_str());
526 if (idx==string::npos) {
527 last=1;
528 exepath=new string(strpath->c_str());
529 exename=new string(strpath->c_str());
530 *strpath="";
531 } else {
532 exepath=new string(strpath->substr(0,idx));
533 exename=new string(strpath->substr(0,idx));
534 *strpath=strpath->substr(idx+1);
535 }
536#if (UTILDEBUG==1)
537 cout << "exepath= " << *exepath << endl;
538#endif
539 if (exepath->substr(exepath->length()-1,1)!=PATHSLASH) {
540 *exepath+=PATHSLASH;
541 }
542 if (exename->substr(exename->length()-1,1)!=PATHSLASH) {
543 *exename+=PATHSLASH;
544 }
545
546 *exename+=rawname;
547#if (UTILDEBUG==1)
548 cout << "test if file " << exename->c_str() << " exists" << endl;
549#endif
550 if (hd24utils::fileExists(exename->c_str())) {
551 strncpy(result,exepath->c_str(),2048);
552 if (exename!=NULL) {
553 delete exename;
554 exename=NULL;
555 }
556 if (exepath!=NULL) {
557 delete exepath;
558 exepath=NULL;
559 }
560 if (strpath!=NULL) {
561 delete strpath;
562 strpath=NULL;
563 }
564 if (pathsep!=NULL) {
565 delete pathsep;
566 pathsep=NULL;
567 }
568 return ;
569 }
570 if (exename!=NULL) {
571 delete exename;
572 exename=NULL;
573 }
574 if (exepath!=NULL) {
575 delete exepath;
576 exepath=NULL;
577 }
578 }
579
580 if (strpath!=NULL) {
581 delete strpath;
582 strpath=NULL;
583 }
584 if (pathsep!=NULL) {
585 delete pathsep;
586 pathsep=NULL;
587 }
588
589 result[0]=(char)0;
590 return;
591}
592
593bool hd24utils::fileExists(const char* strFilename) {
594 struct stat stFileInfo;
595 int intStat;
596
597 // Attempt to get the file attributes
598 intStat = stat(strFilename,&stFileInfo);
599 if(intStat == 0)
600 {
601 // We were able to get the file attributes
602 // so the file obviously exists.
603 return true;
604 }
605 // We were not able to get the file attributes.
606 // This may mean that we don't have permission to
607 // access the folder which contains this file. If you
608 // need to do that level of checking, lookup the
609 // return values of stat which will give you
610 // more details on why stat failed.
611 return false;
612}
613
614string* hd24utils::getlastdir(string which)
615{
616 string* whichdir;
617 char buffer[FL_PATH_MAX];
618
619 Fl_Preferences* userprefs=new Fl_Preferences(Fl_Preferences::USER, "HD24","HD24connect" );
620 /* Attempt to find last used project dir */
621 if (userprefs->entryExists(which.c_str())) {
622 userprefs->get(which.c_str(),buffer,".",FL_PATH_MAX);
623 whichdir=new string(buffer);
624 } else {
625 whichdir=new string(".");
626 }
627 delete userprefs;
628 return whichdir;
629}
630
631void hd24utils::setlastdir(string which,const char* newdir)
632{
633 Fl_Preferences* userprefs=new Fl_Preferences(Fl_Preferences::USER, "HD24","HD24connect" );
634 userprefs->set(which.c_str(),newdir);
635 // cout << "just set " << which << " to " << newdir << endl;
636 delete userprefs;
637}