1 /*
2 * $Id$
3 *
4 * (c) 2004 by Kalle Wallin <kaw@linux.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <signal.h>
25 #include <string.h>
26 #include <glib.h>
28 #include "config.h"
29 #include "ncmpc.h"
30 #include "mpdclient.h"
31 #include "support.h"
32 #include "options.h"
33 #include "command.h"
34 #include "screen.h"
35 #include "conf.h"
37 #define BUFSIZE 256
39 static mpdclient_t *mpd = NULL;
40 static gboolean connected = FALSE;
41 static GTimer *timer = NULL;
43 static gchar *
44 error_msg(gchar *msg)
45 {
46 gchar *p;
48 if( (p=strchr(msg, '}' )) == NULL )
49 return msg;
50 while( p && *p && (*p=='}' || *p==' ') )
51 p++;
53 return p;
54 }
56 static void
57 error_callback(mpdclient_t *c, gint error, gchar *msg)
58 {
59 gint code = GET_ACK_ERROR_CODE(error);
61 error = error & 0xFF;
62 D("Error [%d:%d]> \"%s\"\n", error, code, msg);
63 switch(error)
64 {
65 case MPD_ERROR_CONNPORT:
66 case MPD_ERROR_NORESPONSE:
67 break;
68 case MPD_ERROR_ACK:
69 screen_status_printf("%s", error_msg(msg));
70 beep();
71 break;
72 default:
73 screen_status_printf("%s", msg);
74 beep();
75 doupdate();
76 connected = FALSE;
77 }
78 }
80 void
81 exit_and_cleanup(void)
82 {
83 screen_exit();
84 printf("\n");
85 if( mpd )
86 {
87 mpdclient_disconnect(mpd);
88 mpd = mpdclient_free(mpd);
89 }
90 g_free(options.host);
91 g_free(options.password);
92 g_free(options.list_format);
93 g_free(options.status_format);
94 if( timer )
95 g_timer_destroy(timer);
96 }
98 void
99 catch_sigint( int sig )
100 {
101 printf("\n%s\n", _("Exiting..."));
102 exit(EXIT_SUCCESS);
103 }
105 int
106 main(int argc, const char *argv[])
107 {
108 options_t *options;
109 struct sigaction act;
110 const char *charset = NULL;
111 gboolean key_error;
113 #ifdef HAVE_LOCALE_H
114 /* time and date formatting */
115 setlocale(LC_TIME,"");
116 /* charset */
117 setlocale(LC_CTYPE,"");
118 /* initialize charset conversions */
119 charset_init(g_get_charset(&charset));
120 D("charset: %s\n", charset);
121 #endif
123 /* initialize i18n support */
124 #ifdef ENABLE_NLS
125 setlocale(LC_MESSAGES, "");
126 bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
127 bind_textdomain_codeset(GETTEXT_PACKAGE, charset);
128 textdomain(GETTEXT_PACKAGE);
129 #endif
131 /* initialize options */
132 options = options_init();
134 /* parse command line options - 1 pass get configuration files */
135 options_parse(argc, argv);
137 /* read configuration */
138 read_configuration(options);
140 /* check key bindings */
141 key_error = check_key_bindings(NULL, 0);
143 /* parse command line options - 2 pass */
144 options_parse(argc, argv);
146 /* setup signal behavior - SIGINT */
147 sigemptyset( &act.sa_mask );
148 act.sa_flags = 0;
149 act.sa_handler = catch_sigint;
150 if( sigaction( SIGINT, &act, NULL )<0 )
151 {
152 perror("signal");
153 exit(EXIT_FAILURE);
154 }
155 /* setup signal behavior - SIGTERM */
156 sigemptyset( &act.sa_mask );
157 act.sa_flags = 0;
158 act.sa_handler = catch_sigint;
159 if( sigaction( SIGTERM, &act, NULL )<0 )
160 {
161 perror("sigaction()");
162 exit(EXIT_FAILURE);
163 }
165 /* set xterm title */
166 /* if( g_getenv("DISPLAY") )
167 * printf("%c]0;%s%c", '\033', PACKAGE " version " VERSION, '\007');
168 */
170 /* install exit function */
171 atexit(exit_and_cleanup);
173 /* connect to our music player daemon */
174 mpd = mpdclient_new();
175 if( mpdclient_connect(mpd,
176 options->host,
177 options->port,
178 10.0,
179 options->password) )
180 {
181 exit(EXIT_FAILURE);
182 }
183 connected = TRUE;
184 D("Connected to MPD version %d.%d.%d\n",
185 mpd->connection->version[0],
186 mpd->connection->version[1],
187 mpd->connection->version[2]);
189 if( !MPD_VERSION(mpd, 0,11,0) )
190 {
191 fprintf(stderr, "MPD version %d.%d.%d is to old (0.11.0 needed).\n",
192 mpd->connection->version[0],
193 mpd->connection->version[1],
194 mpd->connection->version[2]);
195 exit(EXIT_FAILURE);
196 }
198 /* initialize curses */
199 screen_init(mpd);
201 /* install error callback function */
202 mpdclient_install_error_callback(mpd, error_callback);
204 /* initialize timer */
205 timer = g_timer_new();
207 connected = TRUE;
208 while( connected || options->reconnect )
209 {
210 static gdouble t = G_MAXDOUBLE;
212 if( key_error )
213 {
214 char buf[BUFSIZE];
216 key_error=check_key_bindings(buf, BUFSIZE);
217 screen_status_printf("%s", buf);
218 }
220 if( connected && (t>=MPD_UPDATE_TIME || mpd->need_update) )
221 {
222 mpdclient_update(mpd);
223 g_timer_start(timer);
224 }
226 if( connected )
227 {
228 command_t cmd;
230 screen_update(mpd);
231 if( (cmd=get_keyboard_command()) != CMD_NONE )
232 {
233 screen_cmd(mpd, cmd);
234 if( cmd==CMD_VOLUME_UP || cmd==CMD_VOLUME_DOWN)
235 /* make shure we dont update the volume yet */
236 g_timer_start(timer);
237 }
238 else
239 screen_idle(mpd);
240 }
241 else if( options->reconnect )
242 {
243 screen_status_printf(_("Connecting to %s... [Press %s to abort]"),
244 options->host, get_key_names(CMD_QUIT,0) );
246 if( get_keyboard_command_with_timeout(MPD_RECONNECT_TIME)==CMD_QUIT)
247 exit(EXIT_SUCCESS);
249 if( mpdclient_connect(mpd,
250 options->host,
251 options->port,
252 1.5,
253 options->password) == 0 )
254 {
255 screen_status_printf(_("Connected to %s!"), options->host);
256 connected = TRUE;
257 }
258 doupdate();
259 }
261 t = g_timer_elapsed(timer, NULL);
262 }
263 exit(EXIT_FAILURE);
264 }