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 static mpdclient_t *mpd = NULL;
38 static gboolean connected = FALSE;
39 static GTimer *timer = NULL;
41 static gchar *
42 error_msg(gchar *msg)
43 {
44 gchar *p;
46 if( (p=strchr(msg, '}' )) == NULL )
47 return msg;
48 while( p && *p && (*p=='}' || *p==' ') )
49 p++;
51 return p;
52 }
54 static void
55 error_callback(mpdclient_t *c, gint error, gchar *msg)
56 {
57 gint code = GET_ACK_ERROR_CODE(error);
59 error = error & 0xFF;
60 D("Error [%d:%d]> \"%s\"\n", error, c->connection->errorCode, msg);
61 switch(error)
62 {
63 case MPD_ERROR_CONNPORT:
64 case MPD_ERROR_NORESPONSE:
65 break;
66 case MPD_ERROR_ACK:
67 screen_status_printf("%s", error_msg(msg));
68 beep();
69 break;
70 default:
71 screen_status_printf("%s", msg);
72 doupdate();
73 beep();
74 connected = FALSE;
75 }
76 }
78 void
79 exit_and_cleanup(void)
80 {
81 screen_exit();
82 printf("\n");
83 if( mpd )
84 {
85 mpdclient_disconnect(mpd);
86 mpd = mpdclient_free(mpd);
87 }
88 g_free(options.host);
89 g_free(options.password);
90 if( timer )
91 g_timer_destroy(timer);
92 }
94 void
95 catch_sigint( int sig )
96 {
97 printf("\n%s\n", _("Exiting..."));
98 exit(EXIT_SUCCESS);
99 }
101 int
102 main(int argc, const char *argv[])
103 {
104 options_t *options;
105 struct sigaction act;
106 const char *charset = NULL;
108 #ifdef HAVE_LOCALE_H
109 /* time and date formatting */
110 setlocale(LC_TIME,"");
111 /* charset */
112 setlocale(LC_CTYPE,"");
113 /* initialize charset conversions */
114 charset_init(g_get_charset(&charset));
115 D("charset: %s\n", charset);
116 #endif
118 /* initialize i18n support */
119 #ifdef ENABLE_NLS
120 setlocale(LC_MESSAGES, "");
121 bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
122 bind_textdomain_codeset(GETTEXT_PACKAGE, charset);
123 textdomain(GETTEXT_PACKAGE);
124 #endif
126 /* initialize options */
127 options = options_init();
129 /* parse command line options - 1 pass get configuration files */
130 options_parse(argc, argv);
132 /* read configuration */
133 read_configuration(options);
135 /* check key bindings */
136 if( check_key_bindings() )
137 {
138 fprintf(stderr, _("Confusing key bindings - exiting!\n"));
139 exit(EXIT_FAILURE);
140 }
142 /* parse command line options - 2 pass */
143 options_parse(argc, argv);
145 /* setup signal behavior - SIGINT */
146 sigemptyset( &act.sa_mask );
147 act.sa_flags = 0;
148 act.sa_handler = catch_sigint;
149 if( sigaction( SIGINT, &act, NULL )<0 )
150 {
151 perror("signal");
152 exit(EXIT_FAILURE);
153 }
154 /* setup signal behavior - SIGTERM */
155 sigemptyset( &act.sa_mask );
156 act.sa_flags = 0;
157 act.sa_handler = catch_sigint;
158 if( sigaction( SIGTERM, &act, NULL )<0 )
159 {
160 perror("sigaction()");
161 exit(EXIT_FAILURE);
162 }
164 /* set xterm title */
165 if( g_getenv("DISPLAY") )
166 printf("%c]0;%s%c", '\033', PACKAGE " version " VERSION, '\007');
168 /* install exit function */
169 atexit(exit_and_cleanup);
171 /* connect to our music player daemon */
172 mpd = mpdclient_new();
173 if( mpdclient_connect(mpd,
174 options->host,
175 options->port,
176 10.0,
177 options->password) )
178 {
179 exit(EXIT_FAILURE);
180 }
181 connected = TRUE;
182 D("Connected to MPD version %d.%d.%d\n",
183 mpd->connection->version[0],
184 mpd->connection->version[1],
185 mpd->connection->version[2]);
187 /* initialize curses */
188 screen_init(mpd);
190 /* install error callback function */
191 mpdclient_install_error_callback(mpd, error_callback);
193 /* initialize timer */
194 timer = g_timer_new();
196 connected = TRUE;
197 while( connected || options->reconnect )
198 {
199 static gdouble t = G_MAXDOUBLE;
201 if( connected && (t>=MPD_UPDATE_TIME || mpd->need_update) )
202 {
203 mpdclient_update(mpd);
204 g_timer_start(timer);
205 }
207 if( connected )
208 {
209 command_t cmd;
211 screen_update(mpd);
212 if( (cmd=get_keyboard_command()) != CMD_NONE )
213 {
214 screen_cmd(mpd, cmd);
215 if( cmd==CMD_VOLUME_UP || cmd==CMD_VOLUME_DOWN)
216 /* make shure we dont update the volume yet */
217 g_timer_start(timer);
218 }
219 else
220 screen_idle(mpd);
221 }
222 else if( options->reconnect )
223 {
224 screen_status_printf(_("Connecting to %s... [Press %s to abort]"),
225 options->host, get_key_names(CMD_QUIT,0) );
227 if( get_keyboard_command_with_timeout(MPD_RECONNECT_TIME)==CMD_QUIT)
228 exit(EXIT_SUCCESS);
230 if( mpdclient_connect(mpd,
231 options->host,
232 options->port,
233 1.5,
234 options->password) == 0 )
235 {
236 screen_status_printf(_("Connected to %s!"), options->host);
237 connected = TRUE;
238 }
239 doupdate();
240 }
242 t = g_timer_elapsed(timer, NULL);
243 }
244 exit(EXIT_FAILURE);
245 }