~ubuntu-dev/ubuntu/lucid/mpd/lucid-201002101854

« back to all changes in this revision

Viewing changes to src/state_file.c

  • Committer: Bazaar Package Importer
  • Author(s): Alessio Treglia
  • Date: 2009-10-23 12:38:20 UTC
  • mfrom: (1.1.12 upstream) (2.2.6 sid)
  • Revision ID: james.westby@ubuntu.com-20091023123820-rxt21lmekscxbkbt
Tags: 0.15.4-1ubuntu1
* Merge from debian unstable, Ubuntu remaining changes:
  - debian/control:
    + Don't build-depends on libmikmod2-dev (Debian bug #510675).
    + Move avahi-daemon from Suggests field to Recommends field.
  - debian/mpd.init.d:
    + Read mpd user from mpd.conf.
* Also fixes LP: #332332.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* the Music Player Daemon (MPD)
2
 
 * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
3
 
 * This project's homepage is: http://www.musicpd.org
 
1
/*
 
2
 * Copyright (C) 2003-2009 The Music Player Daemon Project
 
3
 * http://www.musicpd.org
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify
6
6
 * it under the terms of the GNU General Public License as published by
11
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
13
 * GNU General Public License for more details.
14
 
 * You should have received a copy of the GNU General Public License
15
 
 * along with this program; if not, write to the Free Software
16
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License along
 
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18
 */
18
19
 
19
 
#include "../config.h"
20
20
#include "state_file.h"
21
 
#include "conf.h"
22
 
#include "log.h"
23
 
#include "audio.h"
 
21
#include "output_state.h"
24
22
#include "playlist.h"
25
 
#include "utils.h"
26
23
#include "volume.h"
27
24
 
28
25
#include <glib.h>
 
26
#include <assert.h>
29
27
#include <string.h>
30
 
#include <sys/stat.h>
 
28
#include <errno.h>
 
29
 
 
30
#undef G_LOG_DOMAIN
 
31
#define G_LOG_DOMAIN "state_file"
31
32
 
32
33
static struct _sf_cb {
33
34
        void (*reader)(FILE *);
38
39
        { readPlaylistState, savePlaylistState },
39
40
};
40
41
 
41
 
static const char *sfpath;
42
 
 
43
 
static void get_state_file_path(void)
44
 
{
45
 
        ConfigParam *param;
46
 
        if (sfpath)
47
 
                return;
48
 
        param = parseConfigFilePath(CONF_STATE_FILE, 0);
49
 
        if (param)
50
 
                sfpath = (const char *)param->value;
51
 
}
52
 
 
53
 
void write_state_file(void)
 
42
static char *state_file_path;
 
43
 
 
44
/** the GLib source id for the save timer */
 
45
static guint save_state_source_id;
 
46
 
 
47
static void
 
48
state_file_write(void)
54
49
{
55
50
        unsigned int i;
56
51
        FILE *fp;
57
52
 
58
 
        if (!sfpath)
 
53
        if (state_file_path == NULL)
59
54
                return;
60
 
        fp = fopen(sfpath, "w");
 
55
 
 
56
        fp = fopen(state_file_path, "w");
61
57
        if (G_UNLIKELY(!fp)) {
62
 
                ERROR("problems opening state file \"%s\" for writing: %s\n",
63
 
                      sfpath, strerror(errno));
 
58
                g_warning("failed to create %s: %s",
 
59
                          state_file_path, strerror(errno));
64
60
                return;
65
61
        }
66
62
 
67
 
        for (i = 0; i < ARRAY_SIZE(sf_callbacks); i++)
 
63
        for (i = 0; i < G_N_ELEMENTS(sf_callbacks); i++)
68
64
                sf_callbacks[i].writer(fp);
69
65
 
70
66
        while(fclose(fp) && errno == EINTR) /* nothing */;
71
67
}
72
68
 
73
 
void read_state_file(void)
 
69
static void
 
70
state_file_read(void)
74
71
{
75
 
        struct stat st;
76
72
        unsigned int i;
77
73
        FILE *fp;
78
74
 
79
 
        get_state_file_path();
80
 
        if (!sfpath)
81
 
                return;
82
 
        if (stat(sfpath, &st) < 0) {
83
 
                DEBUG("failed to stat state file: %s\n", sfpath);
84
 
                return;
85
 
        }
86
 
        if (!S_ISREG(st.st_mode))
87
 
                FATAL("state file \"%s\" is not a regular file\n", sfpath);
88
 
 
89
 
        while (!(fp = fopen(sfpath, "r")) && errno == EINTR);
 
75
        assert(state_file_path != NULL);
 
76
 
 
77
        g_debug("Saving state file");
 
78
 
 
79
        fp = fopen(state_file_path, "r");
90
80
        if (G_UNLIKELY(!fp)) {
91
 
                FATAL("problems opening state file \"%s\" for reading: %s\n",
92
 
                      sfpath, strerror(errno));
 
81
                g_warning("failed to open %s: %s",
 
82
                          state_file_path, strerror(errno));
 
83
                return;
93
84
        }
94
 
        for (i = 0; i < ARRAY_SIZE(sf_callbacks); i++) {
 
85
        for (i = 0; i < G_N_ELEMENTS(sf_callbacks); i++) {
95
86
                sf_callbacks[i].reader(fp);
96
87
                rewind(fp);
97
88
        }
99
90
        while(fclose(fp) && errno == EINTR) /* nothing */;
100
91
}
101
92
 
102
 
void G_GNUC_NORETURN state_file_fatal(void)
103
 
{
104
 
        FATAL("error parsing state file \"%s\"\n", sfpath);
105
 
}
106
 
 
 
93
/**
 
94
 * This function is called every 5 minutes by the GLib main loop, and
 
95
 * saves the state file.
 
96
 */
 
97
static gboolean
 
98
timer_save_state_file(G_GNUC_UNUSED gpointer data)
 
99
{
 
100
        state_file_write();
 
101
        return true;
 
102
}
 
103
 
 
104
void
 
105
state_file_init(const char *path)
 
106
{
 
107
        assert(state_file_path == NULL);
 
108
 
 
109
        if (path == NULL)
 
110
                return;
 
111
 
 
112
        state_file_path = g_strdup(path);
 
113
        state_file_read();
 
114
 
 
115
        save_state_source_id = g_timeout_add(5 * 60 * 1000,
 
116
                                             timer_save_state_file, NULL);
 
117
}
 
118
 
 
119
void
 
120
state_file_finish(void)
 
121
{
 
122
        if (save_state_source_id != 0)
 
123
                g_source_remove(save_state_source_id);
 
124
 
 
125
        if (state_file_path != NULL)
 
126
                state_file_write();
 
127
 
 
128
        g_free(state_file_path);
 
129
}