Push and pop modes
[kaka/cakelight.git] / src / kaka / cakelight / Console.java
1 package kaka.cakelight;
2
3 import kaka.cakelight.mode.Mode;
4
5 import java.io.BufferedReader;
6 import java.io.IOException;
7 import java.io.InputStreamReader;
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12
13 public class Console extends Thread {
14     private boolean running;
15     private CakeLight cakelight;
16     private Configuration config;
17     private Map<String, Command> commands = new HashMap<>();
18     private List<Command> commandList = new ArrayList<>();
19
20     public static Console start(CakeLight cakelight, Configuration config) {
21         Console console = new Console(cakelight, config);
22         console.start();
23         return console;
24     }
25
26     private Console(CakeLight cakelight, Configuration config) {
27         this.cakelight = cakelight;
28         this.config = config;
29         register(Commands.help());
30         register(Commands.quit());
31         register(Commands.push());
32         register(Commands.pop());
33         register(Commands.video());
34         register(Commands.color());
35         register(Commands.brightness());
36         register(Commands.gamma());
37         register(Commands.saturation());
38         register(Commands.ambientMode());
39         register(Commands.twoColorNoiseMode());
40         register(Commands.sunriseMode());
41     }
42
43     public CakeLight getCakelight() {
44         return cakelight;
45     }
46
47     public Configuration getConfig() {
48         return config;
49     }
50
51     List<Command> getCommands() {
52         return commandList;
53     }
54
55     void quit() {
56         cakelight.turnOff();
57         running = false;
58     }
59
60     private void register(Command cmd) {
61         for (String name : cmd.getNames()){
62             if (commands.containsKey(name)) {
63                 System.out.println("Command name '" + name + "' is already registered by '" + commands.get(name).getClass() + "'!");
64                 System.exit(1);
65             }
66             commands.put(name, cmd);
67         }
68         commandList.add(cmd);
69     }
70
71     @Override
72     public void run() {
73         running = true;
74         try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
75             while (running) {
76                 System.out.print("> ");
77                 String input = reader.readLine();
78                 internalHandleInput(input);
79             }
80         } catch (IOException e) {
81             System.out.println("Error reading from command line");
82         }
83     }
84
85     private void internalHandleInput(String input) {
86         Object obj = handleInput(input);
87         if (obj instanceof Mode) {
88             cakelight.setMode((Mode) obj);
89         }
90     }
91
92     Object handleInput(String input) {
93         String[] splitInput = input.split("\\s+", 2);
94         String name = splitInput[0];
95         String[] args = splitInput.length == 2
96                 ? splitInput[1].split("\\s+")
97                 : new String[]{};
98
99         Command cmd = commands.get(name);
100         if (cmd != null) {
101             return cmd.activate(this, args);
102         } else {
103             out("no command named '" + name + "'");
104         }
105         return null;
106     }
107
108     void out(String text) {
109         System.out.println("(" + text + ")");
110     }
111
112     Color parseColor(String s) {
113         switch (s.toLowerCase()) {
114             case "r": return Color.rgb(255, 0, 0);
115             case "g": return Color.rgb(0, 255, 0);
116             case "b": return Color.rgb(0, 0, 255);
117             default: // assume hexadecimal
118                 if (s.startsWith("#")) {
119                     s = s.substring(1);
120                 }
121                 if (s.length() == 3) {
122                     return Color.rgb(
123                             Integer.parseInt(s.substring(0, 1), 16) * 16 + Integer.parseInt(s.substring(0, 1), 16),
124                             Integer.parseInt(s.substring(1, 2), 16) * 16 + Integer.parseInt(s.substring(1, 2), 16),
125                             Integer.parseInt(s.substring(2, 3), 16) * 16 + Integer.parseInt(s.substring(2, 3), 16)
126                     );
127                 } else if (s.length() == 6) {
128                     return Color.rgb(
129                             Integer.parseInt(s.substring(0, 2), 16),
130                             Integer.parseInt(s.substring(2, 4), 16),
131                             Integer.parseInt(s.substring(4, 6), 16)
132                     );
133                 }
134         }
135         System.out.println("Failed to parse color '" + s + "'. Using black instead.");
136         return Color.BLACK;
137     }
138
139     public interface Command {
140         String[] getNames();
141         Object activate(Console console, String[] args);
142     }
143 }