Code

1e9edcd0d5096e65088968c10beed11b105a6081
[ncmpc.git] / src / command.c
1 /* 
2  * (c) 2004 by Kalle Wallin (kaw@linux.se)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  *
17  */
19 #include <ctype.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include <glib.h>
25 #include <ncurses.h>
27 #include "config.h"
28 #include "command.h"
30 #undef DEBUG_KEYS
32 #ifdef DEBUG_KEYS
33 #define DK(x) x
34 #else
35 #define DK(x)
36 #endif
38 extern void screen_resize(void);
40 #define BS   KEY_BACKSPACE
41 #define DEL  KEY_DC
42 #define UP   KEY_UP
43 #define DWN  KEY_DOWN
44 #define LEFT KEY_LEFT
45 #define RGHT KEY_RIGHT
46 #define HOME KEY_HOME
47 #define END  KEY_END
48 #define PGDN KEY_NPAGE
49 #define PGUP KEY_PPAGE
50 #define TAB  0x09
51 #define STAB 0x161
52 #define ESC  0x1B
53 #define F1   KEY_F(1)
54 #define F2   KEY_F(2)
55 #define F3   KEY_F(3)
56 #define F4   KEY_F(4)
57 #define F5   KEY_F(5)
58 #define F6   KEY_F(6)
61 static command_definition_t cmds[] =
62 {
63   { {  13,   0,   0 }, CMD_PLAY, "play",  
64     "Play/Enter directory" },
65   { { 'P',   0,   0 }, CMD_PAUSE,"pause", 
66     "Pause" },
67   { { 's',  BS,   0 }, CMD_STOP, "stop",   
68     "Stop" },
69   { { '>',   0,   0 }, CMD_TRACK_NEXT, "next", 
70     "Next track" },
71   { { '<',   0,   0 }, CMD_TRACK_PREVIOUS, "prev", 
72     "Previous track" },
73   { { 'f',   0,   0 }, CMD_SEEK_FORWARD, "seek-forward", 
74     "Seek forward" },
75   { { 'b',   0,   0 }, CMD_SEEK_BACKWARD, "seek-backward", 
76     "Seek backward" },
78   { { '+', RGHT,  0 }, CMD_VOLUME_UP, "volume-up", 
79     "Increase volume" },
80   { { '-', LEFT,  0 }, CMD_VOLUME_DOWN, "volume-down", 
81     "Decrease volume" },
83   { { 'w',   0,   0 }, CMD_TOGGLE_FIND_WRAP,  "wrap-mode", 
84     "Toggle find mode" },
85   { { 'U',   0,   0 }, CMD_TOGGLE_AUTOCENTER, "autocenter-mode", 
86     "Toggle auto center mode" },
88   { { ' ',  'a',   0 }, CMD_SELECT, "select", 
89     "Select/deselect song in playlist" },
90   { { DEL,  'd',  0 }, CMD_DELETE, "delete",
91     "Delete song from playlist" },
92   { { 'Z',   0,   0 }, CMD_SHUFFLE, "shuffle",
93     "Shuffle playlist" },
94   { { 'c',   0,   0 }, CMD_CLEAR, "clear",
95     "Clear playlist" },
96   { { 'r',   0,   0 }, CMD_REPEAT, "repeat",
97     "Toggle repeat mode" },
98   { { 'z',   0,   0 }, CMD_RANDOM, "random",
99     "Toggle random mode" },
100   { { 'x',   0,   0 }, CMD_CROSSFADE, "crossfade",
101     "Toggle crossfade mode" },
102   { { 'S',   0,   0 }, CMD_SAVE_PLAYLIST, "save",
103     "Save playlist" },
105   { { 0,  0,   0 }, CMD_LIST_MOVE_UP,     "move-up", 
106     "Move item up" },
107   { { 0,  0,   0 }, CMD_LIST_MOVE_DOWN,   "move-down", 
108     "Move item down" },
110   { {  UP,  ',',   0 }, CMD_LIST_PREVIOUS,      "up",
111     "Move cursor up" },
112   { { DWN,  '.',   0 }, CMD_LIST_NEXT,          "down",
113     "Move cursor down" },
114   { { HOME, 0x01, 0 }, CMD_LIST_FIRST,          "home",
115     "Home " },
116   { { END,  0x05, 0 }, CMD_LIST_LAST,           "end",
117     "End " },
118   { { PGUP, 'A',   0 }, CMD_LIST_PREVIOUS_PAGE, "pgup",
119     "Page up" },
120   { { PGDN, 'B',   0 }, CMD_LIST_NEXT_PAGE,     "pgdn", 
121     "Page down" },
122   { { '/',   0,   0 }, CMD_LIST_FIND,           "find",
123     "Forward find" },
124   { { 'n',   0,   0 }, CMD_LIST_FIND_NEXT,      "find-next",
125     "Forward find next" },
126   { { '?',   0,   0 }, CMD_LIST_RFIND,          "rfind",
127     "Backward find" },
128   { { 'p',   0,   0 }, CMD_LIST_RFIND_NEXT,     "rfind-next",
129     "Backward find previous" },
132   { { TAB,   0,   0 }, CMD_SCREEN_NEXT,     "screen-next",
133     "Next screen" },
135   { { STAB,  0,   0 }, CMD_SCREEN_PREVIOUS, "screen-prev",
136     "Previous screen" },
138   { { '1', F1, 'h' }, CMD_SCREEN_HELP,      "screen-help",
139     "Help screen" },
140   { { '2', F2,  0 }, CMD_SCREEN_PLAY,      "screen-playlist",
141     "Playlist screen" },
142   { { '3', F3,  0 }, CMD_SCREEN_FILE,      "screen-browse",
143     "Browse screen" },
144   { {'u',   0,   0 }, CMD_SCREEN_UPDATE,    "update",
145     "Update screen" },
146 #ifdef ENABLE_KEYDEF_SCREEN
147   { {'K',   0,   0 }, CMD_SCREEN_KEYDEF,    "screen-keyedit",
148     "Key configuration screen" },
149 #endif
151   { { 'q',  0,   0 }, CMD_QUIT,   "quit",
152     "Quit " PACKAGE },  
154   { { -1,  -1,  -1 }, CMD_NONE, NULL, NULL }
155 };
157 command_definition_t *
158 get_command_definitions(void)
160   return cmds;
163 char *
164 key2str(int key)
166   static char buf[32];
167   int i;
169   buf[0] = 0;
170   switch(key)
171     {
172     case 0:
173       return "Undefined";
174     case ' ':
175       return "Space";
176     case 13:
177       return "Enter";
178     case BS:
179       return "Backspace";
180     case DEL:
181       return "Delete";
182     case UP: 
183       return "Up";
184     case DWN:
185       return "Down";
186     case LEFT:
187       return "Left";
188     case RGHT:
189       return "Right";
190     case HOME:
191       return "Home";
192     case END:
193       return "End";
194     case PGDN:
195       return "PageDown";
196     case PGUP:
197       return "PageUp";
198     case TAB: 
199       return "Tab";
200     case STAB:
201       return "Shift+Tab";
202     case ESC:
203       return "Esc";
204     case KEY_IC:
205       return "Insert";
206     default:
207       for(i=0; i<=63; i++)
208         if( key==KEY_F(i) )
209           {
210             snprintf(buf, 32, "F%d", i );
211             return buf;
212           }
213       if( !(key & ~037) )
214         snprintf(buf, 32, "Ctrl-%c", 'A'+(key & 037)-1 );
215       else if( (key & ~037) == 224 )
216         snprintf(buf, 32, "Alt-%c", 'A'+(key & 037)-1 );
217       else if( key>32 &&  key<256 )
218         snprintf(buf, 32, "%c", key);
219       else
220         snprintf(buf, 32, "0x%03X", key);
221     }
222   return buf;
225 void
226 command_dump_keys(void)
228   int i;
230   i=0;
231   while( cmds[i].description )
232     {
233       if( cmds[i].command != CMD_NONE )
234         printf(" %20s : %s\n", get_key_names(cmds[i].command,1),cmds[i].name); 
235       i++;
236     }
239 char *
240 get_key_names(command_t command, int all)
242   int i;
243   
244   i=0;
245   while( cmds[i].description )
246     {
247       if( cmds[i].command == command )
248         {
249           int j;
250           static char keystr[80];
252           strncpy(keystr, key2str(cmds[i].keys[0]), 80);
253           if( !all )
254             return keystr;
255           j=1;
256           while( j<MAX_COMMAND_KEYS && cmds[i].keys[j]>0 )
257             {
258               strcat(keystr, " ");
259               strcat(keystr, key2str(cmds[i].keys[j]));
260               j++;
261             }
262           return keystr;
263         }
264       i++;
265     }
266   return NULL;
269 char *
270 get_key_description(command_t command)
272   int i;
274   i=0;
275   while( cmds[i].description )
276     {
277       if( cmds[i].command == command )
278         return cmds[i].description;
279       i++;
280     }
281   return NULL;
284 char *
285 get_key_command_name(command_t command)
287   int i;
289   i=0;
290   while( cmds[i].name )
291     {
292       if( cmds[i].command == command )
293         return cmds[i].name;
294       i++;
295     }
296   return NULL;
299 command_t 
300 get_key_command_from_name(char *name)
302   int i;
304   i=0;
305   while( cmds[i].name )
306     {
307       if( strcmp(name, cmds[i].name) == 0 )
308         return cmds[i].command;
309       i++;
310     }
311   return CMD_NONE;
315 command_t 
316 find_key_command(int key, command_definition_t *cmds)
318   int i;
320   i=0;
321   while( cmds && cmds[i].name )
322     {
323       if( cmds[i].keys[0] == key || 
324           cmds[i].keys[1] == key ||
325           cmds[i].keys[2] == key )
326         return cmds[i].command;
327       i++;
328     }
329   return CMD_NONE;
332 command_t 
333 get_key_command(int key)
335   return find_key_command(key, cmds);
339 command_t
340 get_keyboard_command(void)
342   int key;
344   key = wgetch(stdscr);
346   if( key==KEY_RESIZE )
347     screen_resize();
349   if( key==ERR )
350     return CMD_NONE;
352   DK(fprintf(stderr, "key = 0x%02X\t", key));
354   return get_key_command(key);
357 int
358 assign_keys(command_t command, int keys[MAX_COMMAND_KEYS])
360  int i;
362   i=0;
363   while( cmds[i].name )
364     {
365       if( cmds[i].command == command )
366         {
367           memcpy(cmds[i].keys, keys, sizeof(int)*MAX_COMMAND_KEYS);
368           return 0;
369         }
370       i++;
371     }
372   return -1;
375 int 
376 check_key_bindings(void)
378   int i;
379   int retval = 0;
380   
381   i=0;
382   while( cmds[i].name )
383     {
384       int j;
385       command_t cmd;
387       for(j=0; j<MAX_COMMAND_KEYS; j++)
388         if( cmds[i].keys[j] && 
389             (cmd=get_key_command(cmds[i].keys[j])) != cmds[i].command )
390           {
391             fprintf(stderr, "Error: Key %s assigned to %s and %s !!!\n",
392                     key2str(cmds[i].keys[j]),
393                     get_key_command_name(cmds[i].command),
394                     get_key_command_name(cmd));
395             retval = -1;
396           }
397       i++;
398     }
399   return retval;
402 int
403 write_key_bindings(FILE *f)
405   int i,j;
407   i=0;
408   while( cmds[i].name && !ferror(f) )
409     {
410       fprintf(f, "# %s\n", cmds[i].description);
411       fprintf(f, "key %s = ", cmds[i].name);
412       for(j=0; j<MAX_COMMAND_KEYS; j++)
413         {
414           if( j && cmds[i].keys[j] )
415             fprintf(f, ",  ");
416           if( !j || cmds[i].keys[j] )
417             {
418               if( cmds[i].keys[j]<256 && (isalpha(cmds[i].keys[j]) || 
419                                           isdigit(cmds[i].keys[j])) )
420                 fprintf(f, "\'%c\'", cmds[i].keys[j]);
421               else
422                 fprintf(f, "%d", cmds[i].keys[j]);
423             }
424         }
425       fprintf(f,"\n\n");
426       i++;
427     }
428   return ferror(f);