1 // MacTF Copyright 2004 Nathan Oates
5 * This source code is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Public License as published
7 * by the Free Software Foundation; either version 2 of the License,
8 * or (at your option) any later version.
10 * This source code is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * Please refer to the GNU Public License for more details.
15 * You should have received a copy of the GNU Public License along with
16 * this source code; if not, write to:
17 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /* This file was modified by Kalle Olavi Niemitalo on 2007-10-18. */
23 #import "DataHandler.h"
25 @implementation DataHandler
28 #pragma mark Startup and Shutdown
32 if (self = [super init])
34 fileList = [[NSMutableArray alloc] init];
35 searchList = [[NSMutableArray alloc] init];
50 #pragma mark Simple Accessors
52 - (NSMutableArray *) fileList
57 - (NSMutableArray *) displayedList
59 if (searchIsActive) return searchList;
63 - (void) setFileList: (NSArray *)newFileList
65 if (fileList != newFileList)
67 [fileList autorelease];
68 fileList = [[NSMutableArray alloc] initWithArray: newFileList];
72 - (void) setSearchList: (NSArray *)newSearchList
74 if (searchList != newSearchList)
76 [searchList autorelease];
77 searchList = [[NSMutableArray alloc] initWithArray: newSearchList];
88 -(id)tableView:(NSTableView *)aTableView
89 objectValueForTableColumn:(NSTableColumn *)aTableColumn
92 id theRecord, theValue;
93 if (searchIsActive) theRecord = [searchList objectAtIndex:rowIndex];
94 else theRecord = [fileList objectAtIndex:rowIndex];
95 theValue = [theRecord objectForKey:[aTableColumn identifier]];
99 // just returns the number of items we have.
100 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
102 if (searchIsActive) return [searchList count];
103 else return [fileList count];
106 - (void) reloadTable {
107 [tableView reloadData];
110 - (IBAction) search:(id)sender {
111 NSString *searchString = [sender stringValue];
112 if ([searchString isEqualToString:@""]) {
116 NSArray *searchTerms = [searchString componentsSeparatedByString:@" "];
117 NSEnumerator *enumerator = [searchTerms objectEnumerator];
119 BOOL firstToken = YES;
120 NSArray *results = [[NSArray alloc] init];
121 while (anObject = [enumerator nextObject]) {
122 if (![anObject isEqualTo:@""]) {
123 NSPredicate *pred = [NSPredicate predicateWithFormat:@"(name contains[cd] %@)", anObject];
125 results = [fileList filteredArrayUsingPredicate:pred];
127 results = [results filteredArrayUsingPredicate:pred];
131 [self setSearchList:results];
132 searchIsActive = YES;
138 // Drag n Drop methods
139 /*- (BOOL)tableView:(NSTableView *)aTableView writeRows:(NSArray*)rows toPasteboard:(NSPasteboard*)pboard {
145 NSMutableArray *tempArray = [NSMutableArray array];
146 movedRows = [[NSMutableArray alloc] init];
149 NSEnumerator *enumerator = [rows objectEnumerator];
150 while ( (index = [enumerator nextObject]) ) {
151 tempObject = [list objectAtIndex:[index intValue]];
152 [tempArray addObject:tempObject];
154 movedRows = tempArray;
155 NSData *data = [NSArchiver archivedDataWithRootObject: tempArray];
156 [pboard declareTypes: [NSArray arrayWithObject: @"NSGeneralPboardType"] owner: nil];
157 [pboard setData: data forType: @"NSGeneralPboardType"];
161 - (BOOL)tableView:(NSTableView*)aTableView acceptDrop:(id <NSDraggingInfo>)info row:(int)row dropOperation:(NSTableViewDropOperation)operation {
162 NSPasteboard *pboard = [info draggingPasteboard];
163 NSArray *types = [NSArray arrayWithObjects:@"NSFilenamesPboardType", nil];
164 NSString *desiredType = [pboard availableTypeFromArray:types];
165 if (nil == [info draggingSource]) // From other application
167 NSData *carriedData = [pboard dataForType:desiredType];
168 if (nil == carriedData)
170 //the operation failed for some reason
171 NSRunAlertPanel(@"Paste Error", @"Sorry, but the paste operation failed", nil, nil, nil);
174 if ([desiredType isEqualToString:NSFilenamesPboardType]) {
175 //we have a list of file names in an NSData object
176 NSArray *fileArray = [pboard propertyListForType:@"NSFilenamesPboardType"]; //be caseful since this method returns id. We just happen to know that it will be an array.
177 NSEnumerator* selected = [fileArray objectEnumerator];
179 while (currentSelected = [selected nextObject]) {
180 NSLog(@"Upload:%@ to %@", currentSelected, [NSString stringWithString:[UIEl currentPath]]);
181 [UIEl uploadPath:currentSelected toPath:[NSString stringWithString:[UIEl currentPath]]];
185 NSAssert(NO, @"This can't happen");
190 } else if (aTableView == [info draggingSource]) { // From self
193 // From other documents
197 - (NSDragOperation) tableView: (NSTableView *) view
198 validateDrop: (id <NSDraggingInfo>) info
199 proposedRow: (int) row
200 proposedDropOperation: (NSTableViewDropOperation) operation
203 if (nil == [info draggingSource]) // From other application
205 [view setDropRow: row dropOperation: NSTableViewDropAbove];
206 return NSDragOperationCopy;
208 else if (tableView == [info draggingSource]) // From self
210 return NSDragOperationNone;
212 return NSDragOperationNone;
215 // Delegate methods for tableview
217 - (NSMutableDictionary*) getTFFileFromSwappedHexData:(NSData*) input {
219 NSData* mjdHex = [input subdataWithRange:(NSRange) {0,2}];
220 NSData* hrHex = [input subdataWithRange:(NSRange) {2,1}];
221 NSData* minHex = [input subdataWithRange:(NSRange) {3,1}];
222 NSData* secHex = [input subdataWithRange:(NSRange) {4,1}];
223 NSData* typeHex = [input subdataWithRange:(NSRange) {5,1}];
224 NSData* sizeMSBHex = [input subdataWithRange:(NSRange) {6,4}];
225 NSData* sizeLSBHex = [input subdataWithRange:(NSRange) {10,4}];
226 NSData* nameHex = [input subdataWithRange:(NSRange) {14,95}];
227 // windows attributes here?
230 unsigned short int s;
232 NSMutableDictionary* tfFile = [[NSMutableDictionary alloc] init];
233 [mjdHex getBytes:&s];
234 [tfFile setObject:[NSNumber numberWithInt:s] forKey:@"rawMJD"];
236 [tfFile setObject:[NSNumber numberWithChar:c] forKey:@"hour"];
237 [minHex getBytes:&c];
238 [tfFile setObject:[NSNumber numberWithChar:c] forKey:@"min"];
239 [secHex getBytes:&c];
240 [tfFile setObject:[NSNumber numberWithChar:c] forKey:@"sec"];
241 [typeHex getBytes:&c];
242 [tfFile setObject:[NSNumber numberWithChar:c] forKey:@"type"];
243 [sizeMSBHex getBytes:&d];
244 [tfFile setObject:[NSNumber numberWithLong:d] forKey:@"sizeMSB"];
245 [sizeLSBHex getBytes:&d];
246 [tfFile setObject:[NSNumber numberWithLong:d] forKey:@"sizeLSB"];
247 NSString* name = [[NSString alloc] initWithData:nameHex encoding:NSISOLatin1StringEncoding];
248 name = [name substringToIndex:[name rangeOfCharacterFromSet:[NSCharacterSet characterSetWithRange:(NSRange){0,1}]].location]; //trim anything past the 0x00
249 name = [name stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithRange:(NSRange){5,1}]]; //remove extraneous 0x05 on some peoples names.
250 [tfFile setObject:name forKey:@"name"];
251 // NSLog([tfFile description]);
255 - (NSDictionary*) extractAttributes:(NSDictionary*)fattrs {
256 NSMutableDictionary* tfFile = [[NSMutableDictionary alloc] init];
258 NSCalendarDate* date = [[NSCalendarDate alloc] initWithTimeInterval:0 sinceDate:[fattrs fileModificationDate]];
259 int min = [date minuteOfHour];
260 int sec = [date secondOfMinute];
261 int hour = [date hourOfDay];
263 NSCalendarDate *mjdref = [[[NSCalendarDate alloc] initWithYear:1858 month:11 day:17 hour:0 minute:0 second:0 timeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]] autorelease];
264 [date years:NULL months:NULL days:&MJDdate hours:NULL minutes:NULL seconds:NULL sinceDate:mjdref];
265 [tfFile setObject:[NSNumber numberWithInt:MJDdate] forKey:@"rawMJD"];
266 [tfFile setObject:[NSNumber numberWithInt:hour] forKey:@"hour"];
267 [tfFile setObject:[NSNumber numberWithInt:min] forKey:@"min"];
268 [tfFile setObject:[NSNumber numberWithInt:sec] forKey:@"sec"];
271 NSString* type = [fattrs fileType];
272 if ([type isEqualToString:@"NSFileTypeDirectory"])
273 [tfFile setObject:[NSNumber numberWithInt:1] forKey:@"type"];
275 [tfFile setObject:[NSNumber numberWithInt:2] forKey:@"type"];
278 long long size = [fattrs fileSize];
279 [tfFile setObject:[NSNumber numberWithLong:size/0xFFFFFFFF] forKey:@"sizeMSB"];
280 [tfFile setObject:[NSNumber numberWithLong:size%0xFFFFFFFF] forKey:@"sizeLSB"];
284 -(NSData*) getDataFromTFFile:(NSDictionary*) infile withName:(NSString*) inputName {
285 unsigned short int s = [[infile objectForKey:@"rawMJD"] shortValue] ;
286 NSMutableData* build = [NSMutableData dataWithBytes:&s length:2];
287 char c = [[infile objectForKey:@"hour"]charValue];
288 [build appendData:[NSData dataWithBytes:&c length:1]];
289 c = [[infile objectForKey:@"min"] charValue];
290 [build appendData:[NSData dataWithBytes:&c length:1]];
291 c = [[infile objectForKey:@"sec"] charValue];
292 [build appendData:[NSData dataWithBytes:&c length:1]];
293 c = [[infile objectForKey:@"type"] charValue];
294 [build appendData:[NSData dataWithBytes:&c length:1]];
295 long f = [[infile objectForKey:@"sizeMSB"] longValue];
296 [build appendData:[NSData dataWithBytes:&f length:4]];
297 f = [[infile objectForKey:@"sizeLSB"] longValue];
298 [build appendData:[NSData dataWithBytes:&f length:4]];
299 NSData * name = [inputName dataUsingEncoding:NSISOLatin1StringEncoding];
300 [build appendData:name];
301 // need to pad to 95 length
304 while (i < 95 -[name length]){
305 [build appendData:[NSData dataWithBytes:&f length:1]];
308 // other file stuff (5 bytes) - maybe add this later?
309 [build appendData:[NSData dataWithBytes:&f length:5]];
313 - (void) convertRawDataToUseful:(NSMutableDictionary*) input {
315 //turn MJD and time into a useful object
316 if ([[input objectForKey:@"type"] intValue] == 1) { //folder
317 [input setObject:@"" forKey:@"date"];
318 [input setObject:[NSDate distantPast] forKey:@"sortdate"];
319 [input setObject:[NSImage imageNamed:@"folder.tif"] forKey:@"icon"];
320 if ([[input objectForKey:@"name"] isEqualToString:@".."])
321 [input setObject:@".. (Parent folder)" forKey:@"name"];
322 [input setObject:@"0000" forKey:@"suffix"];
324 if ([[input objectForKey:@"name"] hasSuffix:@".tgd"]) [input setObject:[NSImage imageNamed:@"tgd.tif"] forKey:@"icon"];
325 else if ([[input objectForKey:@"name"] hasSuffix:@".tap"]) [input setObject:[NSImage imageNamed:@"package.tif"] forKey:@"icon"];
326 else if ([[input objectForKey:@"name"] hasSuffix:@".mp3"]) [input setObject:[NSImage imageNamed:@"mp3.tif"] forKey:@"icon"];
327 else if ([[input objectForKey:@"name"] hasSuffix:@".txt"] || [[input objectForKey:@"name"] hasSuffix:@".ini"]) [input setObject:[NSImage imageNamed:@"txt.tif"] forKey:@"icon"];
328 else [input setObject:[NSImage imageNamed:@"file.tif"] forKey:@"icon"];
329 [input setObject:[[input objectForKey:@"name"] pathExtension] forKey:@"suffix"];
331 int daysSinceRef = [[input objectForKey:@"rawMJD"] intValue] - 51910; // ref date is 1/1/2001 51911??
332 float secsSinceRef = (((daysSinceRef * 24 + [[input objectForKey:@"hour"] intValue])* 60 + [[input objectForKey:@"min"] intValue]) * 60);
333 NSCalendarDate* tempDate = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:secsSinceRef];
334 //now adjust for timezone
335 int offset = [[NSTimeZone defaultTimeZone] secondsFromGMTForDate:tempDate];
336 //NSLog(@"TZ offset:%i td:%@", offset, [tempDate description]);
337 NSCalendarDate* finalDate = [tempDate dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 seconds:-1*offset];
338 //NSLog(@"TZ td:%@", [finalDate description]);
339 [input setObject:finalDate forKey:@"date"];
340 [input setObject:finalDate forKey:@"sortdate"];
343 //turn size fields into a proper number
345 double big = pow( 256., 4. );
346 double lsb = [[input objectForKey:@"sizeLSB"] doubleValue];
347 double msb = [[input objectForKey:@"sizeMSB"] doubleValue];
349 lsb = lsb + pow( 256., 4. ); //rollover
351 msb = msb + pow( 256., 4. ); //rollover
352 size = msb * big + lsb;
353 [input setObject:[NSNumber numberWithDouble:size] forKey:@"fileSize"];
356 if( size == 0. ) ret = NSLocalizedString( @" - ", "no file size" );
357 else if( size > 0. && size < 1024. ) ret = [NSString stringWithFormat:NSLocalizedString( @"%.0f B", "file size measured in bytes" ), size];
358 else if( size >= 1024. && size < pow( 1024., 2. ) ) ret = [NSString stringWithFormat:NSLocalizedString( @"%.1f KB", "file size measured in kilobytes" ), ( size / 1024. )];
359 else if( size >= pow( 1024., 2. ) && size < pow( 1024., 3. ) ) ret = [NSString stringWithFormat:NSLocalizedString( @"%.2f MB", "file size measured in megabytes" ), ( size / pow( 1024., 2. ) )];
360 else if( size >= pow( 1024., 3. ) && size < pow( 1024., 4. ) ) ret = [NSString stringWithFormat:NSLocalizedString( @"%.2f GB", "file size measured in gigabytes" ), ( size / pow( 1024., 3. ) )];
361 else if( size >= pow( 1024., 4. ) ) ret = [NSString stringWithFormat:NSLocalizedString( @"%.4f TB", "file size measured in terabytes" ), ( size / pow( 1024., 4. ) )];
362 else ret = NSLocalizedString( @" ? ", "unknown file size" );
363 [input setObject:ret forKey:@"size"];
366 - (NSDictionary*) extractDataFromRecHeader:(NSString*)file forModel:(NSString*)model {
367 NSMutableDictionary* extracts = [NSMutableDictionary dictionaryWithCapacity:8];
368 NSData* fileData = [NSData dataWithContentsOfFile:file];
371 if ([model isEqualToString:@"TF5800"]) modelOffset = 4;
372 unsigned char c; //1byte
373 unsigned short int s; //2bytes
374 // unsigned int i; //4bytes
375 [[fileData subdataWithRange:(NSRange) {8,2}] getBytes:&s];
376 [extracts setObject:[NSNumber numberWithShort:s] forKey:@"duration"];
377 NSString* channel = [[NSString alloc] initWithData:[fileData subdataWithRange:(NSRange) {28,24}] encoding:NSISOLatin1StringEncoding];
378 NSRange r = [channel rangeOfCharacterFromSet:[NSCharacterSet characterSetWithRange:(NSRange){0,1}]]; //trim anything past the 0x00
379 if (r.location != NSNotFound)
380 channel = [channel substringToIndex:r.location];
381 channel = [channel stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithRange:(NSRange){5,1}]]; //remove extraneous 0x05 on some peoples names.
382 [extracts setObject:channel forKey:@"channel"];
383 [[fileData subdataWithRange:(NSRange) {76+modelOffset,2}] getBytes:&s];
384 [extracts setObject:[NSNumber numberWithInt:s] forKey:@"rawMJD"];
385 int daysSinceRef = [[extracts objectForKey:@"rawMJD"] intValue] - 51910; // ref date is 1/1/2001 51911??
386 [[fileData subdataWithRange:(NSRange) {78+modelOffset,1}] getBytes:&c];
387 NSNumber* hour = [NSNumber numberWithChar:c];
388 [[fileData subdataWithRange:(NSRange) {79+modelOffset,1}] getBytes:&c];
389 NSNumber* min = [NSNumber numberWithChar:c];
390 float secsSinceRef = (((daysSinceRef * 24 + [hour intValue])* 60 + [min intValue]) * 60);
391 NSCalendarDate* finalDate = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:secsSinceRef];
392 [extracts setObject:finalDate forKey:@"startTime"];
393 [[fileData subdataWithRange:(NSRange) {85+modelOffset,1}] getBytes:&c];
394 NSString* name = [[NSString alloc] initWithData:[fileData subdataWithRange:(NSRange) {87+modelOffset,c}] encoding:NSISOLatin1StringEncoding];
395 [extracts setObject:name forKey:@"name"];
396 NSString* desc = [[NSString alloc] initWithData:[fileData subdataWithRange:(NSRange) {87+c+modelOffset,255}] encoding:NSISOLatin1StringEncoding];
397 r = [desc rangeOfCharacterFromSet:[NSCharacterSet characterSetWithRange:(NSRange){0,1}]]; //trim anything past the 0x00
398 if (r.location != NSNotFound)
399 desc = [desc substringToIndex:r.location];
400 desc = [desc stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithRange:(NSRange){5,1}]]; //remove extraneous 0x05 on some peoples names.
401 [extracts setObject:desc forKey:@"description"];
402 [[fileData subdataWithRange:(NSRange) {362+modelOffset,2}] getBytes:&s];
403 NSString* extInfo = [[NSString alloc] initWithData:[fileData subdataWithRange:(NSRange) {369+modelOffset,s}] encoding:NSISOLatin1StringEncoding];
404 [extracts setObject:extInfo forKey:@"extInfo"];
405 //NSData* movieData = [fileData subdataWithRange:(NSRange) {1656,([fileData length]-1656)}];
406 //[movieData writeToFile:@"/Volumes/Tyr/cazlar/testMovie.ts" atomically:YES];
407 //NSLog([extracts description]);