Code

f2a0e3d29a729e2016a7a5b035dceaf51c558ce4
[ncmpc.git] / src / main.c
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 "conf.h"
34 #include "command.h"
35 #include "screen.h"
36 #include "screen_utils.h"
38 #define BUFSIZE 256
40 static mpdclient_t   *mpd = NULL;
41 static gboolean connected = FALSE;
42 static GTimer      *timer = NULL;
44 static gchar *
45 error_msg(gchar *msg)
46 {
47   gchar *p;
49   if( (p=strchr(msg, '}' )) == NULL )
50     return msg;
51   while( p && *p && (*p=='}' || *p==' ') )
52     p++;
54   return p;
55 }
57 static void
58 error_callback(mpdclient_t *c, gint error, gchar *msg)
59 {
60   gint code = GET_ACK_ERROR_CODE(error);
62   error = error & 0xFF;
63   D("Error [%d:%d]> \"%s\"\n", error, code, msg);
64   switch(error)
65     {
66     case MPD_ERROR_CONNPORT:
67     case MPD_ERROR_NORESPONSE:
68       break;
69     case MPD_ERROR_ACK:
70       screen_status_printf("%s", error_msg(msg));
71       screen_bell();
72       break;
73     default:
74       screen_status_printf("%s", msg);
75       screen_bell();
76       doupdate();
77       connected = FALSE;
78     }
79 }
81 void
82 exit_and_cleanup(void)
83 {
84   screen_exit();
85   printf("\n");
86   if( mpd )
87     {
88       mpdclient_disconnect(mpd);
89       mpd = mpdclient_free(mpd);
90     }
91   g_free(options.host);
92   g_free(options.password);
93   g_free(options.list_format);
94   g_free(options.status_format);
95   if( timer )
96     g_timer_destroy(timer);
97 }
99 void
100 catch_sigint( int sig )
102   printf("\n%s\n", _("Exiting..."));
103   exit(EXIT_SUCCESS);
106 int 
107 main(int argc, const char *argv[])
109   options_t *options;
110   struct sigaction act;
111   const char *charset = NULL;
112   gboolean key_error;
114 #ifdef HAVE_LOCALE_H
115   /* time and date formatting */
116   setlocale(LC_TIME,"");
117   /* charset */
118   setlocale(LC_CTYPE,"");
119   /* initialize charset conversions */
120   charset_init(g_get_charset(&charset));
121   D("charset: %s\n", charset);
122 #endif
124   /* initialize i18n support */
125 #ifdef ENABLE_NLS
126   setlocale(LC_MESSAGES, "");
127   bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
128   bind_textdomain_codeset(GETTEXT_PACKAGE, charset);
129   textdomain(GETTEXT_PACKAGE);
130 #endif
132   /* initialize options */
133   options = options_init();
135   /* parse command line options - 1 pass get configuration files */
136   options_parse(argc, argv);
137   
138   /* read configuration */
139   read_configuration(options);
141   /* check key bindings */
142   key_error = check_key_bindings(NULL, 0);
143   
144   /* parse command line options - 2 pass */
145   options_parse(argc, argv);
147   /* setup signal behavior - SIGINT */
148   sigemptyset( &act.sa_mask );
149   act.sa_flags    = 0;
150   act.sa_handler = catch_sigint;
151   if( sigaction( SIGINT, &act, NULL )<0 )
152     {
153       perror("signal");
154       exit(EXIT_FAILURE);
155     }
156   /* setup signal behavior - SIGTERM */
157   sigemptyset( &act.sa_mask );
158   act.sa_flags    = 0;
159   act.sa_handler = catch_sigint;
160   if( sigaction( SIGTERM, &act, NULL )<0 )
161     {
162       perror("sigaction()");
163       exit(EXIT_FAILURE);
164     }
166   /* set xterm title */
167 #ifdef DEBUG
168   options->enable_xterm_title = 1;
169   set_xterm_title(PACKAGE " version " VERSION);
170 #endif
172   /* install exit function */
173   atexit(exit_and_cleanup);
175   /* connect to our music player daemon */
176   mpd = mpdclient_new();
177   if( mpdclient_connect(mpd, 
178                         options->host, 
179                         options->port, 
180                         10.0, 
181                         options->password) )
182     {
183       exit(EXIT_FAILURE);
184     }
185   connected = TRUE;
186   D("Connected to MPD version %d.%d.%d\n",
187     mpd->connection->version[0],
188     mpd->connection->version[1],
189     mpd->connection->version[2]);
191   if( !MPD_VERSION(mpd, 0,11,0) )
192     {
193       fprintf(stderr, "MPD version %d.%d.%d is to old (0.11.0 needed).\n",
194               mpd->connection->version[0],
195               mpd->connection->version[1],
196               mpd->connection->version[2]);
197       exit(EXIT_FAILURE);
198     }
200   /* initialize curses */
201   screen_init(mpd);
203   /* install error callback function */
204   mpdclient_install_error_callback(mpd, error_callback);
206   /* initialize timer */
207   timer = g_timer_new();
209   connected = TRUE;
210   while( connected || options->reconnect )
211     {
212       static gdouble t = G_MAXDOUBLE;
214       if( key_error )
215         {
216           char buf[BUFSIZE];
218           key_error=check_key_bindings(buf, BUFSIZE);
219           screen_status_printf("%s", buf);
220         }
222       if( connected && (t>=MPD_UPDATE_TIME || mpd->need_update) )
223         {
224           mpdclient_update(mpd);
225           g_timer_start(timer);
226         }
228       if( connected )
229         {
230           command_t cmd;
232           screen_update(mpd);
233           if( (cmd=get_keyboard_command()) != CMD_NONE )
234             {
235               screen_cmd(mpd, cmd);
236               if( cmd==CMD_VOLUME_UP || cmd==CMD_VOLUME_DOWN)
237                 /* make shure we dont update the volume yet */
238                 g_timer_start(timer);
239             }
240           else
241             screen_idle(mpd);
242         }
243       else if( options->reconnect )
244         {
245           screen_status_printf(_("Connecting to %s...  [Press %s to abort]"), 
246                                options->host, get_key_names(CMD_QUIT,0) );
248           if( get_keyboard_command_with_timeout(MPD_RECONNECT_TIME)==CMD_QUIT)
249             exit(EXIT_SUCCESS);
250           
251           if( mpdclient_connect(mpd,
252                                 options->host,
253                                 options->port, 
254                                 1.5,
255                                 options->password) == 0 )
256             {
257               screen_status_printf(_("Connected to %s!"), options->host);
258               connected = TRUE;
259             }     
260           doupdate();
261         }
263       t = g_timer_elapsed(timer, NULL);
264     }
265   exit(EXIT_FAILURE);