Complete Makeover
[splitter-ng] / Splitter-ng-filesplitter / src / Filesplitter.java
1 import java.io.File;
2 import java.io.IOException;
3 import java.nio.file.DirectoryStream;
4 import java.nio.file.Files;
5 import java.nio.file.LinkOption;
6 import java.nio.file.Path;
7 import java.nio.file.Paths;
8 import java.util.Collection;
9 import java.util.HashMap;
10 import java.util.Iterator;
11 import java.util.LinkedList;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Map.Entry;
15 import java.util.Scanner;
16 import java.util.Set;
17 import java.util.TreeMap;
18
19 import org.ini4j.Ini;
20 import org.ini4j.Profile.Section;
21
22 import splitterng.CodingTask;
23 import splitterng.DecodingTask;
24 import splitterng.EncodingTask;
25 import splitterng.Splitter;
26 import splitterng.SplitterCallback;
27 import splitterng.plugin.CodecDescription;
28 import splitterng.plugin.PluginDescription;
29
30 public class Filesplitter implements SplitterCallback {
31         /*
32          * public static final String ANSI_RESET = ""; public static final String
33          * ANSI_BLACK = ""; public static final String ANSI_RED = ""; public static
34          * final String ANSI_GREEN = ""; public static final String ANSI_YELLOW =
35          * ""; public static final String ANSI_BLUE = ""; public static final String
36          * ANSI_PURPLE = ""; public static final String ANSI_CYAN = ""; public
37          * static final String ANSI_WHITE = ""; public static final String ANSI_BOLD
38          * = "";
39          */
40         public static final String ANSI_RESET = "\u001B[0m";
41         public static final String ANSI_BLACK = "\u001B[30m";
42         public static final String ANSI_RED = "\u001B[31m";
43         public static final String ANSI_GREEN = "\u001B[32m";
44         public static final String ANSI_YELLOW = "\u001B[33m";
45         public static final String ANSI_BLUE = "\u001B[34m";
46         public static final String ANSI_PURPLE = "\u001B[35m";
47         public static final String ANSI_CYAN = "\u001B[36m";
48         public static final String ANSI_WHITE = "\u001B[37m";
49         public static final String ANSI_BOLD = "\u001B[1m";
50
51         public Ini config;
52         public static String CONFIGFILE = "filesplitter.ini";
53
54         private List<CodingTask> finished_encoding_task = new LinkedList<CodingTask>();
55         private List<CodingTask> finished_decoding_task = new LinkedList<CodingTask>();
56         private List<CodingTask> running_tasks = new LinkedList<CodingTask>();
57         private List<String> codeclist = new LinkedList<String>();
58         private List<String> codeclist_configured = new LinkedList<String>();
59         private List<String> codeclist_failed = new LinkedList<String>();
60         // in der Map werden die Metadaten-vorlage für jeden Codec gespeichert
61         private List<Splitter> splitters = new LinkedList<Splitter>();
62         private Map<Splitter, Map<String, Object>> splitter_metadata_map = new HashMap<Splitter, Map<String, Object>>();
63
64         public static void main(String[] args) throws InterruptedException {
65                 Filesplitter filesplitter = new Filesplitter();
66                 filesplitter.run(args);
67
68                 // Thread.sleep(50000);
69                 // System.exit(0);
70         }
71
72         public String readCommandline() {
73                 return readCommandline("",false);
74         }
75         public String readCommandline(String string) {
76                 return readCommandline(string,false);
77         }
78         public String readCommandline(boolean allowblanklines) {
79                 return readCommandline("",allowblanklines);
80         }
81         public String readCommandline(String string ,boolean allowblanklines) {
82                 Scanner in;
83                 String line = null;
84                 in = new Scanner(System.in);
85                 while (line == null || (!allowblanklines && line.isEmpty())) {
86                         System.out.print(ANSI_BOLD +string+ ANSI_RESET);
87                         line = in.nextLine();
88                 }
89                 return line;
90
91         }
92
93         public void run(String[] args) {
94                 init_config();
95                 print_codecs();
96
97                 println_std("\nProcessing the following files:");
98                 Path srcDir = Paths.get("srcDir");
99                 List<Path> srcFileList = getFileList(srcDir);;
100                 for (String s:args){
101                         Path p = Paths.get(s);
102                         if (Files.exists(p, LinkOption.NOFOLLOW_LINKS)){
103                                 srcFileList.add(p);
104                         }
105                         else {
106                                 println_err("- " + p.toString() + " doesn't exists");
107                         }
108                         
109                 }
110                 for (Path entry : srcFileList) {
111                         println_std("- " + entry.toString());
112                 }
113
114                 // restoreDir anlegen bzw aufräumen
115                 Path splitDir = Paths.get("splitDir");
116                 checkDirectory(splitDir);
117                 for (Path entry : getFileList(splitDir)) {
118                         try {
119                                 Files.delete(entry);
120                         } catch (IOException e) {
121                                 // TODO Auto-generated catch block
122                                 e.printStackTrace();
123                         }
124                 }
125
126                 // restoreDir anlegen bzw aufräumen
127                 Path restoreDir = Paths.get("restoreDir");
128                 checkDirectory(restoreDir);
129                 for (Path entry : getFileList(restoreDir)) {
130                         try {
131                                 Files.delete(entry);
132                         } catch (IOException e) {
133                                 e.printStackTrace();
134                         }
135                 }
136                 // Jede Datei ...
137                 for (Path srcfile : srcFileList) {
138                         // ... mit jedem initialisierten Splitter bearbeiten
139                         for (Splitter splitter : splitters) {
140                                 encode(srcfile, splitter);
141
142                         }
143
144                 }
145
146                 println_info("-----");
147                 println_info("All CodingTasks submitted");
148
149                 println_info("Use 'h' or 'help' to display commands");
150                 // printUsage();
151
152                 // dateien zusammenbauen
153                 String commandline;
154                 while (true) {
155                         commandline = readCommandline(">>>");
156                         if (commandline == null) {
157                                 println_std("Exit");
158                                 System.exit(0);
159                         }
160                         Scanner in = new Scanner(commandline);
161                         switch (in.next()) {
162                         case "EOF":
163                         case "q":
164                         case "quit":
165                         case "exit":
166                                 System.exit(0);
167                         case "h":
168                         case "help":
169                                 printUsage();
170                                 break;
171                         case "ls":
172                                 if (in.hasNext()) {
173                                         switch (in.next()) {
174                                         case "enc":
175                                                 for (CodingTask t : finished_encoding_task) {
176                                                         println_ok(""
177                                                                         + finished_encoding_task.lastIndexOf(t)
178                                                                         + "\t" + t.getFilePath().getFileName());
179                                                 }
180                                                 break;
181                                         case "dec":
182                                                 for (CodingTask t : finished_decoding_task) {
183                                                         println_ok(""
184                                                                         + finished_decoding_task.lastIndexOf(t)
185                                                                         + "\t" + t.getFilePath().getFileName());
186                                                 }
187                                                 break;
188
189                                         case "frag":
190                                                 try {
191                                                         for (Entry<Integer, Path> e : finished_encoding_task
192                                                                         .get(Integer.parseInt(in.next()))
193                                                                         .getFragmentPaths().entrySet()) {
194                                                                 String color = Files.exists(e.getValue()) ? ANSI_GREEN
195                                                                                 : ANSI_RED;
196                                                                 System.out.format(color + "\t %-5s %s %s\n"
197                                                                                 + ANSI_RESET, e.getKey(), e.getValue()
198                                                                                 .toString(),
199                                                                                 (Files.exists(e.getValue()) ? "OK"
200                                                                                                 : "Fehlt"));
201                                                                 // println_std(++"\t"+e.getValue().toString());
202                                                         }
203                                                 } catch (Exception e) {
204                                                         println_err("Index not found. Use 'ls enc' to show valid indices");
205                                                 }
206                                                 break;
207
208                                         case "splitter":
209                                         case "splitters":
210                                                 print_splitter();
211                                                 break;
212
213                                         case "codec":
214                                         case "codecs":
215                                                         print_codecs();
216                                                 break;
217                                         }
218
219                                 }
220                                 break;
221
222                         case "meta":
223                                 if (in.hasNext()) {
224                                         switch (in.next()) {
225                                         case "enc":
226                                                 try {
227                                                         for (Entry<String, Object> e : finished_encoding_task
228                                                                         .get(Integer.parseInt(in.next()))
229                                                                         .getMetadata().entrySet()) {
230                                                                 println_ok(String.format("\t %-25s %-25s %s",
231                                                                                 e.getKey(), e.getValue().toString(), e
232                                                                                                 .getValue().getClass()
233                                                                                                 .toString()));
234                                                                 // println_std(++"\t"+e.getValue().toString());
235                                                         }
236                                                 } catch (Exception e) {
237                                                         println_err("Index not found. Use 'ls enc' to show valid indices");
238                                                 }
239                                                 break;
240
241                                         case "dec":
242                                                 try {
243                                                         for (Entry<String, Object> e : finished_decoding_task
244                                                                         .get(Integer.parseInt(in.next()))
245                                                                         .getMetadata().entrySet()) {
246                                                                 println_ok(String.format("\t %-25s %s",
247                                                                                 e.getKey(), e.getValue().toString()));
248                                                                 // println_std(++"\t"+e.getValue().toString());
249                                                         }
250                                                 } catch (Exception e) {
251                                                         println_err("Index not found. Use 'ls dec' to show valid indices");
252                                                 }
253                                                 break;
254                                         }
255                                 }
256                                 break;
257
258                         case "rm":
259                                 try {
260                                         int tasknr = Integer.parseInt(in.next());
261                                         int fragmentnr = Integer.parseInt(in.next());
262                                         Map<Integer, Path> fragmentPaths = finished_encoding_task
263                                                         .get(tasknr).getFragmentPaths();
264                                         Path path = fragmentPaths.get(fragmentnr);
265                                         try {
266                                                 Files.delete(path);
267                                         } catch (Exception e) {
268                                                 println_err("unable to delete fragment: "
269                                                                 + e.getMessage());
270
271                                         }
272
273                                 } catch (Exception e) {
274                                         println_err("Index not found. Use 'ls frag <index> ' to show valid indices");
275                                 }
276                                 break;
277
278                         case "dec":
279                                 try {
280                                         int tasknr = Integer.parseInt(in.next());
281                                         decode(restoreDir, tasknr);
282                                 } catch (Exception e) {
283                                         // e.printStackTrace();
284                                         println_err("Index not found. Use 'ls enc' to show valid indices");
285                                 }
286
287                                 break;
288                         case "enc":
289                                 int splitternr;
290                                 Splitter splitter;
291                                 try {
292                                         splitternr = in.nextInt();
293                                         splitter = splitters.get(splitternr);
294                                 } catch (Exception e1) {
295                                         // TODO Auto-generated catch block
296                                         println_err("no valid Splitter-Infex. Use 'ls splitter' to show valid indices");
297                                         break;
298                                 }
299                                 String filename;
300                                 Path srcfile = null;
301                                 try {
302                                         filename = in.next();
303                                         srcfile = Paths.get(filename);
304                                         if (Files.notExists(srcfile, LinkOption.NOFOLLOW_LINKS)) {
305                                                 in.close();
306                                                 throw new Exception();
307                                         }
308                                 } catch (Exception e1) {
309                                         println_err("no valid Filename. Use 'enc <splitternr> <Filename>'");
310                                         break;
311                                 }
312                                 try {
313                                         encode(srcfile, splitter);
314                                 } catch (Exception e1) {
315                                         // TODO Auto-generated catch block
316                                         println_err(e1.getMessage()
317                                                         + "\nEncoding failed. Use 'enc <splitternr> <Filename>'");
318                                 }
319                                 break;
320
321                         case "init":
322                                 try {
323                                         int codecnr = Integer.parseInt(in.next());
324                                         configure_codec(codecnr);
325                                 } catch (Exception e) {
326                                         println_err("Index not found. Use 'ls codec' to show valid indices");
327                                 }
328                                 break;
329                         case "reset":
330                                 try {
331                                         int codecnr = Integer.parseInt(in.next());
332                                         reset_codec(codecnr);
333                                 } catch (Exception e) {
334                                         println_err("Index not found. Use 'ls codec' to show valid indices");
335                                 }
336
337                                 break;
338                         default:
339                                 printUsage();
340                         }
341                         in.close();
342                 }
343
344         }
345
346         public void decode(Path restoreDir, int tasknr) {
347                 try {
348                         CodingTask enctask = (CodingTask) finished_encoding_task
349                                         .get(tasknr);
350                         Path restorefile = restoreDir.resolve(""
351                                         + System.currentTimeMillis()
352                                         + enctask.getFilePath().getFileName());
353
354                         Map<Integer, Path> fragmentPaths = enctask.getFragmentPaths();
355                         for (int i = 0; i < fragmentPaths.size(); i++) {
356                                 Path path = fragmentPaths.get(i);
357                                 if (path == null || !Files.exists(path)) {
358                                         fragmentPaths.put(i, null);
359                                 }
360
361                         }
362                         DecodingTask dectask = new DecodingTask(fragmentPaths, restorefile,
363                                         this, enctask.getMetadataAsDeepCopy());
364                         for (Splitter spl : splitters) {
365                                 if (spl.getCurrentPlugin().getPluginDescription().getPluginID() == (String) enctask
366                                                 .getMetadata("pluginid")
367                                                 && spl.getCurrentCodecDescription().getCodecID() == (String) enctask
368                                                                 .getMetadata("codecid")) {
369                                         println_ok("Auftrag angenommen..." + restorefile);
370                                         spl.decode(dectask);
371                                         running_tasks.add(dectask);
372                                 }
373                         }
374
375                 } catch (Exception e) {
376                         // e.printStackTrace();
377                         println_err("Index not found. Use 'ls enc' to show valid indices");
378                 }
379         }
380
381         public void print_splitter() {
382                 for (Splitter splitter : splitters) {
383                         String pid = splitter.getCurrentPlugin().getPluginDescription()
384                                         .getPluginID();
385                         String cid = splitter.getCurrentCodecDescription().getCodecID();
386                         println_ok(splitters.indexOf(splitter) + "\t" + pid + "/" + cid
387                                         + "  \t(" + splitter.getTaskQueueLength()
388                                         + " active Tasks)");
389                 }
390         }
391
392         public void encode(Path srcfile, Splitter splitter) {
393                 println_ok("Encoding: "
394                                 + srcfile
395                                 + "  with "
396                                 + splitter.getCurrentPlugin().getPluginDescription()
397                                                 .getPluginID() + "/"
398                                 + splitter.getCurrentCodecDescription().getCodecID());
399                 try {
400
401                         Map<String, Object> metadata = new TreeMap<String, Object>();
402
403                         for (Entry<String, Object> e : splitter_metadata_map.get(splitter)
404                                         .entrySet()) {
405                                 metadata.put(e.getKey(), e.getValue());
406                         }
407
408                         metadata.put("time_encoding_submitted", System.currentTimeMillis());
409
410                         // Hier wird codiert. Der Encodingtask
411                         EncodingTask task = new EncodingTask(srcfile,
412                                         Paths.get("splitDir"), this, metadata);
413                         splitter.encode(task);
414                         running_tasks.add(task);
415                 } catch (InterruptedException | IOException e) {
416                         e.printStackTrace();
417                 }
418         }
419
420         public void saveconfig() {
421                 try {
422                         config.store();
423                         println_ok("Configuration saved");
424                 } catch (IOException e1) {
425                         // TODO Auto-generated catch block
426                         e1.printStackTrace();
427                 }
428         }
429
430         public void init_config() {
431                 try {
432                         File configfile = new File(CONFIGFILE);
433                         if (!configfile.exists()) {
434                                 configfile.createNewFile();
435                         }
436                         config = new Ini(configfile);
437                 } catch (Exception e) {
438                         // TODO Auto-generated catch block
439                         e.printStackTrace();
440                 }
441                 for (PluginDescription p : Splitter.getPluginDescriptions()) {
442                         for (CodecDescription c : p.getCodecDescriptions()) {
443                                 String id = p.getPluginID() + "/" + c.getCodecID();
444                                 codeclist.add(id);
445                                 if (isInConfig(id)) {
446                                         init_codec(id);
447                                 }
448                         }
449                 }
450         }
451
452         private boolean isInConfig(String id) {
453                 Section s = config.get(id);
454                 if (s != null && s.containsKey("k") && s.containsKey("m")) {
455                         return true;
456                 }
457                 return false;
458         }
459
460         private void init_codec(String id) {
461                 Section section;
462                 section = config.get(id);
463
464                 // Build codecparameter map
465                 Map<String, Integer> codecparameter = new HashMap<>();
466                 for (Entry<String, String> e : section.entrySet()) {
467                         try {
468                                 codecparameter.put(e.getKey(), Integer.parseInt(e.getValue()));
469                         } catch (Exception ex) {
470                                 // nothing
471                         }
472                 }
473
474                 // build Metadata Template. Try tu use Integer, if it fails use String
475                 section = config.get(id + "_MetadataTemplate");
476                 Map<String, Object> metadatatemplate = new HashMap<>();
477                 if (section != null) {
478                         for (Entry<String, String> entry : section.entrySet()) {
479                                 try {
480                                         metadatatemplate.put(entry.getKey(),
481                                                         Integer.parseInt(entry.getValue()));
482                                 } catch (NumberFormatException ex) {
483                                         try {
484                                                 metadatatemplate.put(entry.getKey(), entry.getValue());
485                                         } catch (Exception e2) {
486                                                 // TODO: handle exception
487                                         }
488                                 }
489                         }
490                 }
491
492                 for (PluginDescription p : Splitter.getPluginDescriptions()) {
493                         for (CodecDescription c : p.getCodecDescriptions()) {
494                                 if (id.equals(p.getPluginID() + "/" + c.getCodecID())) {
495                                         try {
496                                                 Splitter splitter = new Splitter(p.getPluginID(),
497                                                                 c.getCodecID(), codecparameter);
498                                                 splitters.add(splitter);
499                                                 splitter_metadata_map.put(splitter, metadatatemplate);
500                                                 codeclist_configured.add(id);
501                                                 if (codeclist_failed.contains(id)){
502                                                         codeclist_failed.remove(id);
503                                                 }
504                                                 println_ok("Splitter created from config: " + id);
505                                         } catch (Exception e) {
506                                                 println_err("NO Splitter created for: " + id + "\n"
507                                                                 + e.getMessage());
508                                                 codeclist_failed.add(id);
509                                                 if (codeclist_configured.contains(id)){
510                                                         codeclist_configured.remove(id);
511                                                 }
512                                         }
513                                 }
514                         }
515                 }
516         }
517
518         private void reset_codec(int i) {
519                 String id = getCodecIDfromIndex(i);
520                 if (id == null) {
521                         println_err("Codec " + i + " existiert nicht");
522                         print_codecs();
523                         return;
524                 }
525                 config.remove(config.get(id));
526                 saveconfig();
527                 if (codeclist_configured.contains(id)){
528                         codeclist_configured.remove(id);
529                 }
530                 if (codeclist_failed.contains(id)){
531                         codeclist_failed.remove(id);
532                 }
533                 for (Splitter splitter : splitters) {
534                         String pid = splitter.getCurrentPlugin().getPluginDescription()
535                                         .getPluginID();
536                         String cid = splitter.getCurrentCodecDescription().getCodecID();
537                         if (id.equals(pid + "/" + cid)) {
538                                 splitters.remove(splitter);
539                                 splitter_metadata_map.remove(splitter);
540                                 splitter.stop();
541                         }
542                 }
543         }
544
545         public void configure_codec(int i) {
546                 String id = getCodecIDfromIndex(i);
547                 if (id == null) {
548                         println_err("Codec " + i + " existiert nicht");
549                         print_codecs();
550                         return;
551                 }
552
553                 for (PluginDescription p : Splitter.getPluginDescriptions()) {
554                         for (CodecDescription c : p.getCodecDescriptions()) {
555                                 if (id.equals(p.getPluginID() + "/" + c.getCodecID())) {
556                                         Section section = config.get(id);
557                                         if (section == null) {
558                                                 section = config.add(id);
559                                         }
560                                         print_codecdescription(p, c);
561                                         println_std(id + " Configuration:");
562                                         for (Entry<String, Integer[]> entry : c
563                                                         .getCodecParameterMinMax().entrySet()) {
564                                                 print_std(entry.getKey());
565                                                 print_std("\tmin="+ c.getCodecParameterMinMax().get(entry.getKey())[0]);
566                                                 print_std("\tmax="+ c.getCodecParameterMinMax().get(entry.getKey())[1]);
567                                                 if (c.getCodecParameterDefaults().get(entry.getKey()) != null) {
568                                                         print_std("\tdefault="
569                                                                         + c.getCodecParameterDefaults().get(
570                                                                                         entry.getKey()));
571                                                         section.put(entry.getKey(), readCommandline("\t"+entry.getKey()+"=",true));
572                                                 }
573                                                 else {
574                                                         section.put(entry.getKey(), readCommandline("\t"+entry.getKey()+"=",false));
575                                                 }
576                                         }
577                                         println_std("");
578
579                                         section = config.get(id + "_MetadataTemplate");
580                                         if (section == null) {
581                                                 section = config.add(id + "_MetadataTemplate");
582                                         }
583                                         section.put("fragmentsize", "4096");
584                                         saveconfig();
585                                         init_codec(id);
586                                 }
587                         }
588                 }
589
590         }
591
592         public String getCodecIDfromIndex(int i) {
593                 String id;
594                 try {
595                         id = codeclist.get(i);
596                 } catch (Exception e) {
597                         return null;
598                 }
599                 return id;
600         }
601
602         public void print_codecs() {
603                 println_info("----available codecs----");
604                 for (String c : codeclist) {
605                         if (codeclist_configured.contains(c)) {
606                                 println_ok(String.format("%-6s%-45s configured",
607                                                 codeclist.indexOf(c), c));
608                         } else if (codeclist_failed.contains(c)) {
609                                 println_err(String.format("%-6s%-45s invalid configuration",
610                                                 codeclist.indexOf(c), c));
611                         }
612                         else {
613                                 println_info(String.format("%-6s%-45s not configured",
614                                                 codeclist.indexOf(c), c));
615                         }
616                 }
617                 println_std("use 'init <nr>' to configure codecs and 'reset <n>' to delete configuration");
618         }
619
620         public void print_codecdescription(PluginDescription p, CodecDescription c) {
621                 println_info("\t|---------------------------------------------\n\t|"
622                                 + c.getCodecID() + "\t" + c.getCodecDescriptionText());
623                 Map<String, Integer[]> codecParameterMinMax = c
624                                 .getCodecParameterMinMax();
625                 for (Entry<String, Integer[]> e : codecParameterMinMax.entrySet()) {
626                         println_info(String.format(
627                                         "\t|\t%15s\tmin:%15s\tmax:%15s\tdefault:%15s", e.getKey(),
628                                         e.getValue()[0], e.getValue()[1], c
629                                                         .getCodecParameterDefaults().get(e.getKey())));
630                 }
631         }
632
633         private static List<Path> getFileList(Path path) {
634                 List<Path> files = new LinkedList<Path>();
635                 checkDirectory(path);
636                 try (DirectoryStream<Path> stream = Files.newDirectoryStream(path,
637                                 new DirectoryStream.Filter<Path>() {
638                                         @Override
639                                         public boolean accept(Path entry) throws IOException {
640                                                 return !Files.isDirectory(entry);
641                                         }
642                                 });) {
643                         for (Path entry : stream) {
644                                 files.add(entry);
645                         }
646                 } catch (IOException e) {
647                         e.printStackTrace();
648                 }
649                 return files;
650         }
651
652         private static void checkDirectory(Path path) {
653                 if (!Files.exists(path)) {
654                         try {
655                                 Files.createDirectory(path);
656                         } catch (IOException e) {
657                                 System.err.println("Verzeichnis kann nicht erstellt werden: "
658                                                 + path.toUri());
659                                 e.printStackTrace();
660                         }
661                 }
662         }
663
664         // private static void initSplitter(Splitter splitter) {
665         //
666         // println_std("Liste der Codecs:");
667         // Collection<String> codecids = splitter.getCodecIDs();
668         // Iterator<String> it = codecids.iterator();
669         // while (it.hasNext()){
670         // println_std("- " + it.next().toString());
671         // }
672         // if (codecids.contains("jerasureparity")){
673         // SplitterConfiguration config = new SplitterConfiguration();
674         // config.setCodecID("jerasureparity");
675         // splitter.setSplitterConfiguration(config);
676         // }
677         // println_std();
678         // }
679
680         @Override
681         public void codingFailed(CodingTask task, String reason) {
682                 synchronized (task) { // damit die Ausgabe nicht verwürfelt wird
683                         running_tasks.remove(task);
684                         println_err("Coding Failed: " + task.getFilePath().toString()
685                                         + "  Reason:" + reason);
686                 }
687
688         }
689
690         @Override
691         public synchronized void codingSuccessfull(CodingTask task) {
692                 synchronized (task) { // damit die Ausgabe nicht verwürfelt wird
693                         long duration = 0;
694                         running_tasks.remove(task);
695                         if (task instanceof EncodingTask) {
696                                 finished_encoding_task.add(task);
697                                 duration = (long) task.getMetadata("time_encode_end")
698                                                 - (long) task.getMetadata("time_encode_start");
699                         } else if (task instanceof DecodingTask) {
700                                 finished_decoding_task.add(task);
701                                 duration = (long) task.getMetadata("time_decode_end")
702                                                 - (long) task.getMetadata("time_decode_start");
703                         }
704
705                         println_ok("CodingTask " + finished_encoding_task.indexOf(task)
706                                         + " OK: " + task.getFilePath().toString() + "  Codec: "
707                                         + task.getMetadata("pluginid") + "/"
708                                         + task.getMetadata("codecid") + "  T(ms):" + duration);
709                 }
710         }
711
712         public void printUsage() {
713                 println_std("Bedienung:");
714                 println_std("init");
715                 println_std("reset");
716                 println_std( "ls splitter\tlistet alle initialisierten Splitter auf");
717                 println_std( "ls codec\t\tlistet alle codecs auf");
718                 println_std("ls enc\t\tlistet alle fertig encodierten Tasks auf");
719                 println_std("ls dec\t\tlistet alle fertig decodierten Tasks auf");
720                 println_std("ls frag <nr>\tlistet die Fragmentdateien zu Encoding-Task <nr> auf");
721                 println_std("rm <nr> <frac_nr>\tlöscht aus Encoding-Task <nr> die Fragmentdatei <frac_nr>");
722                 println_std("dec <nr>\twiederherstellen der Originaldatei aus Encoding-Task <nr> in das Verzeichnis restoreDir");
723                 println_std("enc <splitternr> <filename>\tencodieren files with a splitter");
724                 println_std("meta enc <nr>\tgibt metadaten zu encodingtask <nr> aus");
725                 println_std("meta dec <nr>\tgibt metadaten zu decodingtask <nr> aus");
726                 println_std("q, quit oder exit\tbeenden das Programm");
727                 // +" \nh oder help\tzeigt die Hilfe an"
728                 println_std("");
729         }
730
731         public void println_std(String str) {
732                 print_std(str + "\n");
733         }
734
735         public void print_std(String str) {
736                 System.out.print(ANSI_RESET + str + ANSI_RESET);
737         }
738
739         public void println_err(String str) {
740                 System.out.println(ANSI_RED + str + ANSI_RESET);
741         }
742
743         public void print_ok(String str) {
744                 System.out.print(ANSI_GREEN + str + ANSI_RESET);
745         }
746
747         public void println_ok(String str) {
748                 print_ok(str + "\n");
749         }
750
751         public void println_dbg(String str) {
752                 System.out.println(ANSI_RESET + str + ANSI_RESET);
753         }
754
755         public void println_info(String str) {
756                 System.out.println(ANSI_BOLD + ANSI_YELLOW + str + ANSI_RESET);
757         }
758 }