Upstream tarball 9756
[amule.git] / cocoa-mule / amuleData.mm
blob1b356ead23c28538807ef3b5b0f36aca120e5fec
2 #import "amuleData.h"
4 @implementation amuleFile
6 @synthesize name = m_name;
7 @synthesize size = m_size;
9 - (unsigned)hash {
10         return m_hash.lo ^ m_hash.hi;
13 - (NSString *)key {
14         NSString *s = [NSString stringWithFormat:@"%qx%qx", m_hash.hi, m_hash.lo];
15         return s;
18 - (BOOL)isEqual: (id) object {
19         if ([object isKindOfClass:[amuleFile class]]) {
20                 amuleFile *myobj = (amuleFile *)object;
21                 return ((myobj->m_hash.lo == m_hash.lo) && (myobj->m_hash.hi == m_hash.hi));
22         } else {
23                 return false;
24         }
27 - (NSString *)convertWithPrefix:(uint64_t)number {
28         NSString *res = nil;
29         double dnum = number;
30         if ( number < 1024 ) { // bytes
31                 res = [NSString stringWithFormat:@"%llu bytes", number]; 
32         } else if ( number < 1024*1024 ) { // K
33                 res = [NSString stringWithFormat:@"%0.2f Kb", dnum / 1024.0]; 
34         } else if ( number < 1024*1024*1024 ) { // M
35                 res = [NSString stringWithFormat:@"%.2f Mb", dnum / 1048576.0]; 
36         } else {
37                 res = [NSString stringWithFormat:@"%.2f Gb", dnum / 1073741824.0]; 
38         }
39         return res;
43 @end
45 @implementation DownloadingFile
47 @synthesize src_count = m_src_count;
48 @synthesize non_current_src_count = m_non_current_src_count;
49 @synthesize xfer_src_count = m_xfer_src_count;
50 @synthesize a4af_src_count = m_a4af_src_count;
52 @synthesize speed = m_speed;
54 @synthesize size_done = m_size_done;
55 @synthesize size_xfer = m_size_xfer;
57 @synthesize prio = m_prio;
59 @dynamic sprio;
61 - (NSString *)sprio {
62         return [self prioToString: m_prio];
66 + (id)createFromEC: (ECTagMD5 *) tag {
67         DownloadingFile *obj = [[DownloadingFile alloc] init];
68         
69         obj->m_hash = [tag getMD5Data];
70         
71         ECTag *nametag = [tag tagByName: EC_TAG_PARTFILE_NAME];
72         ECTagString *stag = (ECTagString *)nametag;
73         obj->m_name = stag.stringValue;;
74         
75         obj->m_size = [tag tagInt64ByName: EC_TAG_PARTFILE_SIZE_FULL];
76         NSLog(@"[EC]: added partfile [%@]\n", obj->m_name);
77         [obj updateFromEC:tag];
78         
79         return obj;
82 - (void)updateFromEC:(ECTagMD5 *) tag {
83         NSLog(@"[EC]: updating partfile [%@]\n", m_name);
84         
85         m_size_done = [tag tagInt64ByName: EC_TAG_PARTFILE_SIZE_DONE];
86         m_size_xfer = [tag tagInt64ByName:EC_TAG_PARTFILE_SIZE_XFER];
87         
88         m_speed = [tag tagInt64ByName:EC_TAG_PARTFILE_SPEED];
89         
90         m_src_count = [tag tagInt64ByName: EC_TAG_PARTFILE_SOURCE_COUNT];
91         m_non_current_src_count = [tag tagInt64ByName: EC_TAG_PARTFILE_SOURCE_COUNT_NOT_CURRENT];
92         m_xfer_src_count = [tag tagInt64ByName: EC_TAG_PARTFILE_SOURCE_COUNT_XFER];
93         m_a4af_src_count = [tag tagInt64ByName: EC_TAG_PARTFILE_SOURCE_COUNT_A4AF];
95         m_prio = [tag tagInt64ByName:EC_TAG_PARTFILE_PRIO];
96         if ( m_prio > 10 ) {
97                 m_auto_prio = true;
98                 m_prio -= 10;
99         } else {
100                 m_auto_prio = false;
101         }
104 - (NSString *)prioToString:(int)prio {
105         NSString *s = nil;
106         switch (prio) {
107                 case 0:
108                         s = @"Low";
109                         break;
110                 case 1:
111                         s = @"Normal";
112                         break;
113                 case 2:
114                         s = @"High";
115                         break;
116                 case 3:
117                         s = @"Very High";
118                         break;
119                 case 4:
120                         s = @"Very Low";
121                         break;
122                 case 5:
123                         s = @"Auto";
124                         break;
125                 case 6:
126                         s = @"PowerShare";
127                         break;
128                 default:
129                         break;
130         }
131         if ( m_auto_prio ) {
132                 s = [s stringByAppendingString:@" (auto)"];
133         }
134         return s;
138 @end
140 @implementation SearchFile
142 @synthesize src_count = m_src_count;
143 @synthesize complete_src_count = m_complete_src_count;
145 + (id)createFromEC: (ECTagMD5 *) tag {
146         SearchFile *obj = [[SearchFile alloc] init];
147         
148         obj->m_hash = [tag getMD5Data];
150         ECTag *nametag = [tag tagByName: EC_TAG_PARTFILE_NAME];
151         ECTagString *stag = (ECTagString *)nametag;
152         obj->m_name = stag.stringValue;;
154         obj->m_size = [tag tagInt64ByName: EC_TAG_PARTFILE_SIZE_FULL];
156         obj->m_known = ([tag tagByName: EC_TAG_KNOWNFILE] == nil) ? false : true;
157         
158         [obj updateFromEC:tag];
159         
160         return obj;
163 - (void)updateFromEC:(ECTagMD5 *) tag {
164         m_src_count = [tag tagInt64ByName: EC_TAG_PARTFILE_SOURCE_COUNT];
165         m_complete_src_count = [tag tagInt64ByName: EC_TAG_PARTFILE_SOURCE_COUNT_XFER];
168 @end
170 @implementation SharedFile
172 @synthesize size_xfer = m_size_xfer;
173 @synthesize size_xfer_all = m_size_xfer_all;
175 @synthesize req_count = m_req_count;
176 @synthesize req_count_all = m_req_count_all;
178 @synthesize accept_count = m_accept_count;
179 @synthesize accept_count_all = m_accept_count_all;
181 @synthesize prio = m_prio;
183 @dynamic sprio;
185 - (NSString *)sprio {
186         return [self prioToString: m_prio];
189 + (id)createFromEC: (ECTagMD5 *) tag {
190         SharedFile *obj = [[SharedFile alloc] init];
192         obj->m_hash = [tag getMD5Data];
193         
194         ECTag *nametag = [tag tagByName: EC_TAG_PARTFILE_NAME];
195         ECTagString *stag = (ECTagString *)nametag;
196         obj->m_name = stag.stringValue;;
197         
198         obj->m_size = [tag tagInt64ByName: EC_TAG_PARTFILE_SIZE_FULL];
199                 
200         [obj updateFromEC:tag];
201         
202         return obj;
205 - (NSString *)prioToString:(int)prio {
206         NSString *s = nil;
207         switch (prio) {
208                 case 0:
209                         s = @"Low";
210                         break;
211                 case 1:
212                         s = @"Normal";
213                         break;
214                 case 2:
215                         s = @"High";
216                         break;
217                 case 3:
218                         s = @"Very High";
219                         break;
220                 case 4:
221                         s = @"Very Low";
222                         break;
223                 case 5:
224                         s = @"Auto";
225                         break;
226                 case 6:
227                         s = @"PowerShare";
228                         break;
229                 default:
230                         break;
231         }
232         if ( m_auto_prio ) {
233                 s = [s stringByAppendingString:@" (auto)"];
234         }
235         return s;
239 - (void)updateFromEC:(ECTagMD5 *) tag {
240         m_req_count = [tag tagInt64ByName: EC_TAG_KNOWNFILE_REQ_COUNT];
241         m_req_count_all = [tag tagInt64ByName: EC_TAG_KNOWNFILE_REQ_COUNT_ALL];
242         m_accept_count = [tag tagInt64ByName: EC_TAG_KNOWNFILE_ACCEPT_COUNT];
243         m_accept_count_all = [tag tagInt64ByName: EC_TAG_KNOWNFILE_ACCEPT_COUNT_ALL];
244         
245         m_size_xfer = [tag tagInt64ByName: EC_TAG_KNOWNFILE_XFERRED];
246         m_size_xfer_all = [tag tagInt64ByName: EC_TAG_KNOWNFILE_XFERRED_ALL];
247         
248         m_prio = [tag tagInt64ByName:EC_TAG_PARTFILE_PRIO];
249         if ( m_prio > 10 ) {
250                 m_auto_prio = true;
251                 m_prio -= 10;
252         } else {
253                 m_auto_prio = false;
254         }
255         
258 @end
260 @implementation amuleFileSet
262 - (id)init {
263     if ((self = [super init])) {
264                 m_file_dict = [NSMutableDictionary dictionaryWithCapacity:256];
265                 m_file_array = [[NSMutableArray alloc] init];
266         }
267         return self;
270 - (int)count {
271         return [m_file_dict count];
274 - (void)insertObject:(id)object {
275         id objKey = [object key];
276         [m_file_dict setObject:object forKey:objKey];
277         [m_file_array addObject:object];
278         
279         [self reloadGui];
282 - (void)reloadGui {
283         if ([m_gui_controller respondsToSelector:@selector(reload:)]) {
284                 [m_gui_controller performSelector:@selector(reload:)];
285         } else {
286                 NSLog(@"Internal error: gui controller doesnt respond to 'reload'\n");
287         }
288 //      if ([m_gui_controller respondsToSelector:[m_gui_controller reload]) {
289 //              [m_gui_controller performSelector:@selector(reload)];
290 //      } else {
291 //              NSLog(@"Internal error: gui controller doesnt respond to 'reload'\n");
292 //      }
295 - (id)objectAtIndex:(int)index {
296         return [m_file_array objectAtIndex:index];
299 - (id)objectForKey:(id)key {
300         return [m_file_dict objectForKey:key];
303 - (void)removeAtIndex:(int)index {
304         id curr_obj = [m_file_array objectAtIndex:index];
305         id key = [curr_obj key];
306         [m_file_dict removeObjectForKey:key];
307         [m_file_array removeObjectAtIndex:index];
309         [self reloadGui];
312 - (void)removeAtKey:(id)key {
313         [m_file_dict removeObjectForKey:key];
314         int index = -1;
315         for (int i = 0; i < [m_file_array count]; i++) {
316                 id curr_obj = [m_file_array objectAtIndex:i];
317                 if ([curr_obj key] == key) {
318                         index = i;
319                         break;
320                 }
321         }
322         if ( index != -1 ) {
323                 [m_file_array removeObjectAtIndex:index];
324         } else {
325                 NSLog(@"Internal error: object not found in array\n");
326         }
328         [self reloadGui];
331 - (void)setGuiController:(id)controller {
332         m_gui_controller = controller;
335 @end
337 @implementation amuleData
339 @synthesize downloads = m_downloads;
340 @synthesize shared = m_shared;
341 @synthesize search_resuls = m_search_results;
343 + (id)initWithConnection:(ECRemoteConnection *) connection {
344         amuleData *obj = [[amuleData alloc] init];
345         connection.delegate = obj;
346         
347         obj->m_connection = connection;
348         
349         obj->m_downloads = [[amuleFileSet alloc] init];
350         obj->m_shared = [[amuleFileSet alloc] init];
351         obj->m_search_results = [[amuleFileSet alloc] init];
352          
353         return obj;
356 - (void)handlePacket:(ECPacket *) packet {
357         switch(packet.opcode) {
358                 case EC_OP_STATS : {
359                         break;
360                 }
361                 case EC_OP_DLOAD_QUEUE: {
362                         [self handleDownloadQueueUpdate: packet];
363                         break;
364                 }
365                 case EC_OP_SHARED_FILES: {
366                         [self handleSharedFilesUpdate: packet];
367                         break;
368                 }
369                 case EC_OP_SEARCH_RESULTS: {
370                         [self handleSearchUpdate: packet];
371                         break;
372                 }
373                 default: {
374                         NSLog(@"[EC] packet with opcode %d not handled\n", packet.opcode);
375                 }
376         }
379 - (void)handleError {
380                 NSRunCriticalAlertPanel(@"Daemon communication error", 
381                                                 @"Connection with core daemon (amuled) failed",
382                                                 @"Quit", nil,nil);
383                 exit(-1);
386 - (void)handleDownloadQueueUpdate:(ECPacket *) packet {
387         for (ECTag *t in packet.subtags) {
388                 if ( [t isKindOfClass:[ECTagMD5 class]] ) {
389                         ECTagMD5 *tag = (ECTagMD5 *)t;
390                         if ( [tag tagCount] == 0 ) {
391                                 //
392                                 // Only hash here - indication to remove the object
393                                 //
394                                 [m_downloads removeAtKey:[tag stringKey]];
395                         } else {
396                                 NSLog(@"[EC] filehash=[%@]\n", [tag stringKey]);
397                                 DownloadingFile *file = [m_downloads objectForKey:[tag stringKey]];
398                                 if ( file == nil ) {
399                                         file = [DownloadingFile createFromEC:tag];
400                                         [m_downloads insertObject:file];
401                                 } else {
402                                         DownloadingFile *file = [m_downloads objectForKey:[tag stringKey]];
403                                         [file updateFromEC:tag];
404                                 }
405                         }
406                 } else {
407                         NSLog(@"[EC] bad tag type '%s'\n", [t class]);
408                 }
409         }
412 - (void)handleSharedFilesUpdate:(ECPacket *) packet {
413         for (ECTag *t in packet.subtags) {
414                 if ( [t isKindOfClass:[ECTagMD5 class]] ) {
415                         ECTagMD5 *tag = (ECTagMD5 *)t;
416                         if ( [tag tagCount] == 0 ) {
417                                 //
418                                 // Only hash here - indication to remove the object
419                                 //
420                                 [m_shared removeAtKey:[tag stringKey]];
421                         } else {
422                                 NSLog(@"[EC] filehash=[%@]\n", [tag stringKey]);
423                                 SharedFile *file = [m_shared objectForKey:[tag stringKey]];
424                                 if ( file == nil ) {
425                                         file = [SharedFile createFromEC:tag];
426                                         [m_shared insertObject:file];
427                                 } else {
428                                         SharedFile *file = [m_shared objectForKey:[tag stringKey]];
429                                         [file updateFromEC:tag];
430                                 }
431                         }
432                 } else {
433                         NSLog(@"[EC] bad tag type '%s'\n", [t class]);
434                 }
435         }
438 - (void)handleSearchUpdate:(ECPacket *) packet {
439         for (ECTag *t in packet.subtags) {
440                 if ( [t isKindOfClass:[ECTagMD5 class]] ) {
441                         ECTagMD5 *tag = (ECTagMD5 *)t;
442                         SearchFile *file = [m_search_results objectForKey:[tag stringKey]];
443                         if ( file == nil ) {
444                                 file = [SearchFile createFromEC:tag];
445                                 [m_search_results insertObject:file];
446                         } else {
447                                 SearchFile *file = [m_search_results objectForKey:[tag stringKey]];
448                                 [file updateFromEC:tag];
449                         }
450                 }
451         }
454 - (void)handleStatusUpdate:(ECPacket *) packet {
457 - (void)startSearch:(NSString *)text searchType:(EC_SEARCH_TYPE)searchType
458         minSize:(uint64_t)minSize maxSize:(uint64_t)maxSize avail:(uint32_t)avail {
460         ECPacket *packet = [ECPacket packetWithOpcode:EC_OP_SEARCH_START];
462         ECTagInt8 *searchtag = [ECTagInt8 tagFromInt8:searchType withName:EC_TAG_SEARCH_TYPE];
464         [searchtag.subtags addObject:[ECTagString tagFromString:text withName:EC_TAG_SEARCH_NAME]];
465         if ( minSize ) {
466                 [searchtag.subtags addObject:[ECTagInt64 tagFromInt64:minSize withName:EC_TAG_SEARCH_MIN_SIZE]];
467         }
468         if ( maxSize ) {
469                 [searchtag.subtags addObject:[ECTagInt64 tagFromInt64:maxSize withName:EC_TAG_SEARCH_MAX_SIZE]];
470         }
471         if ( avail ) {
472                 [searchtag.subtags addObject:[ECTagInt32 tagFromInt32:avail withName:EC_TAG_SEARCH_AVAILABILITY]];
473         }
474         
475         [packet.subtags addObject:searchtag];
476         
477         [m_connection sendPacket:packet];
478         
479         m_search_running = true;
482 - (void)stopSearch {
483         ECPacket *packet = [ECPacket packetWithOpcode:EC_OP_SEARCH_STOP];
485         [m_connection sendPacket:packet];
486         
487         m_search_running = false;
490 @end