~ubuntu-branches/ubuntu/maverick/newsbeuter/maverick

« back to all changes in this revision

Viewing changes to src/pb_controller.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Nico Golde
  • Date: 2007-04-21 19:44:35 UTC
  • Revision ID: james.westby@ubuntu.com-20070421194435-21g6134ws2yvarlt
Tags: upstream-0.3
ImportĀ upstreamĀ versionĀ 0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <pb_controller.h>
 
2
#include <pb_view.h>
 
3
#include <poddlthread.h>
 
4
#include <config.h>
 
5
#include <utils.h>
 
6
#include <iostream>
 
7
#include <sstream>
 
8
#include <cstdio>
 
9
 
 
10
#include <sys/types.h>
 
11
#include <pwd.h>
 
12
#include <signal.h>
 
13
 
 
14
#include <keymap.h>
 
15
#include <configcontainer.h>
 
16
#include <colormanager.h>
 
17
#include <exceptions.h>
 
18
#include <queueloader.h>
 
19
#include <logger.h>
 
20
 
 
21
using namespace newsbeuter;
 
22
 
 
23
static std::string lock_file = "pb-lock.pid";
 
24
 
 
25
void ctrl_c_action(int sig) {
 
26
        GetLogger().log(LOG_DEBUG,"caugh signal %d",sig);
 
27
        stfl::reset();
 
28
        utils::remove_fs_lock(lock_file);
 
29
        if (SIGSEGV == sig) {
 
30
                fprintf(stderr,"%s\n", _("Segmentation fault."));
 
31
        }
 
32
        ::exit(EXIT_FAILURE);
 
33
}
 
34
 
 
35
namespace podbeuter {
 
36
 
 
37
pb_controller::pb_controller() : v(0), config_file("config"), queue_file("queue"), cfg(0), view_update_(true),  max_dls(1), ql(0) { 
 
38
        std::ostringstream cfgfile;
 
39
 
 
40
        char * cfgdir;
 
41
        if (!(cfgdir = ::getenv("HOME"))) {
 
42
                struct passwd * spw = ::getpwuid(::getuid());
 
43
                if (spw) {
 
44
                        cfgdir = spw->pw_dir;
 
45
                } else {
 
46
                        std::cout << _("Fatal error: couldn't determine home directory!") << std::endl;
 
47
                        char buf[1024];
 
48
                        snprintf(buf, sizeof(buf), _("Please set the HOME environment variable or add a valid user for UID %u!"), ::getuid());
 
49
                        std::cout << buf << std::endl;
 
50
                        ::exit(EXIT_FAILURE);
 
51
                }
 
52
        }
 
53
        config_dir = cfgdir;
 
54
 
 
55
 
 
56
        config_dir.append(NEWSBEUTER_PATH_SEP);
 
57
        config_dir.append(NEWSBEUTER_CONFIG_SUBDIR);
 
58
        mkdir(config_dir.c_str(),0700); // create configuration directory if it doesn't exist
 
59
 
 
60
        config_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + config_file;
 
61
        queue_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + queue_file;
 
62
        lock_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + lock_file;
 
63
}
 
64
 
 
65
pb_controller::~pb_controller() { 
 
66
        delete cfg;
 
67
}
 
68
 
 
69
void pb_controller::run(int argc, char * argv[]) {
 
70
        int c;
 
71
        char msgbuf[1024];
 
72
 
 
73
        ::signal(SIGINT, ctrl_c_action);
 
74
        ::signal(SIGSEGV, ctrl_c_action);
 
75
 
 
76
        do {
 
77
                if ((c = ::getopt(argc, argv, "C:q:d:l:h")) < 0)
 
78
                        continue;
 
79
 
 
80
                switch (c) {
 
81
                        case ':':
 
82
                        case '?':
 
83
                                usage(argv[0]);
 
84
                                break;
 
85
                        case 'C':
 
86
                                config_file = optarg;
 
87
                                break;
 
88
                        case 'q':
 
89
                                queue_file = optarg;
 
90
                                break;
 
91
                        case 'd': // this is an undocumented debug commandline option!
 
92
                                GetLogger().set_logfile(optarg);
 
93
                                break;
 
94
                        case 'l': // this is an undocumented debug commandline option!
 
95
                                {
 
96
                                        loglevel level = static_cast<loglevel>(atoi(optarg));
 
97
                                        if (level > LOG_NONE && level <= LOG_DEBUG)
 
98
                                                GetLogger().set_loglevel(level);
 
99
                                }
 
100
                                break;
 
101
                        case 'h':
 
102
                                usage(argv[0]);
 
103
                                break;
 
104
                        default:
 
105
                                snprintf(msgbuf, sizeof(msgbuf), _("%s: unknown option - %c"), argv[0], static_cast<char>(c));
 
106
                                std::cout << msgbuf << std::endl;
 
107
                                usage(argv[0]);
 
108
                                break;
 
109
                }
 
110
        } while (c != -1);
 
111
 
 
112
        snprintf(msgbuf, sizeof(msgbuf), _("Starting %s %s..."), "podbeuter", PROGRAM_VERSION);
 
113
        std::cout << msgbuf << std::endl;
 
114
 
 
115
        pid_t pid;
 
116
        if (!utils::try_fs_lock(lock_file, pid)) {
 
117
                snprintf(msgbuf, sizeof(msgbuf), _("Error: an instance of %s is already running (PID: %u)"), "podbeuter", pid);
 
118
                std::cout << msgbuf << std::endl;
 
119
                return;
 
120
        }
 
121
 
 
122
        std::cout << _("Loading configuration...");
 
123
        std::cout.flush();
 
124
 
 
125
        configparser cfgparser(config_file.c_str());
 
126
        cfg = new configcontainer();
 
127
        cfg->register_commands(cfgparser);
 
128
        colormanager * colorman = new colormanager();
 
129
        colorman->register_commands(cfgparser);
 
130
 
 
131
        keymap keys;
 
132
        cfgparser.register_handler("bind-key", &keys);
 
133
        cfgparser.register_handler("unbind-key", &keys);
 
134
 
 
135
        v->set_keymap(&keys);
 
136
 
 
137
        try {
 
138
                cfgparser.parse();
 
139
        } catch (const configexception& ex) {
 
140
                std::cout << ex.what() << std::endl;
 
141
                return; 
 
142
        }
 
143
 
 
144
        if (colorman->colors_loaded())
 
145
                colorman->set_pb_colors(v);
 
146
        delete colorman;
 
147
 
 
148
        max_dls = cfg->get_configvalue_as_int("max-downloads");
 
149
 
 
150
        std::cout << _("done.") << std::endl;
 
151
 
 
152
        ql = new queueloader(queue_file, this);
 
153
        ql->reload(downloads_);
 
154
        
 
155
        v->run();
 
156
 
 
157
        std::cout <<  _("Cleaning up queue...");
 
158
        std::cout.flush();
 
159
        
 
160
        ql->reload(downloads_);
 
161
        delete ql;
 
162
        
 
163
        std::cout << _("done.") << std::endl;
 
164
 
 
165
        utils::remove_fs_lock(lock_file);
 
166
}
 
167
 
 
168
void pb_controller::usage(const char * argv0) {
 
169
        char buf[2048];
 
170
        snprintf(buf, sizeof(buf),
 
171
                                _("%s %s\nusage %s [-C <file>] [-q <file>] [-h]\n"
 
172
                                "-C <configfile> read configuration from <configfile>\n"
 
173
                                "-q <queuefile>  use <queuefile> as queue file\n"
 
174
                                "-h              this help\n"), "podbeuter", PROGRAM_VERSION, argv0);
 
175
        std::cout << buf;
 
176
        ::exit(EXIT_FAILURE);
 
177
}
 
178
 
 
179
std::string pb_controller::get_dlpath() {
 
180
        return cfg->get_configvalue("download-path");
 
181
}
 
182
 
 
183
unsigned int pb_controller::downloads_in_progress() {
 
184
        unsigned int count = 0;
 
185
        if (downloads_.size() > 0) {
 
186
                for (std::vector<download>::iterator it=downloads_.begin();it!=downloads_.end();++it) {
 
187
                        if (it->status() == DL_DOWNLOADING)
 
188
                                ++count;
 
189
                }
 
190
        }
 
191
        return count;
 
192
}
 
193
 
 
194
unsigned int pb_controller::get_maxdownloads() {
 
195
        return max_dls;
 
196
}
 
197
 
 
198
void pb_controller::reload_queue() {
 
199
        if (ql) {
 
200
                ql->reload(downloads_);
 
201
        }
 
202
}
 
203
 
 
204
double pb_controller::get_total_kbps() {
 
205
        double result = 0.0;
 
206
        if (downloads_.size() > 0) {
 
207
                for (std::vector<download>::iterator it=downloads_.begin();it!=downloads_.end();++it) {
 
208
                        if (it->status() == DL_DOWNLOADING) {
 
209
                                result += it->kbps();
 
210
                        }
 
211
                }
 
212
        }
 
213
        return result;
 
214
}
 
215
 
 
216
void pb_controller::start_downloads() {
 
217
        int dl2start = get_maxdownloads() - downloads_in_progress();
 
218
        for (std::vector<download>::iterator it=downloads_.begin();dl2start > 0 && it!=downloads_.end();++it) {
 
219
                if (it->status() == DL_QUEUED) {
 
220
                        poddlthread * thread = new poddlthread(&(*it));
 
221
                        thread->start();
 
222
                        --dl2start;
 
223
                }
 
224
        }
 
225
}
 
226
 
 
227
void pb_controller::increase_parallel_downloads() {
 
228
        ++max_dls;
 
229
}
 
230
 
 
231
void pb_controller::decrease_parallel_downloads() {
 
232
        if (max_dls > 1)
 
233
                --max_dls;
 
234
}
 
235
 
 
236
void pb_controller::play_file(const std::string& str) {
 
237
        std::string cmdline;
 
238
        std::string player = cfg->get_configvalue("player");
 
239
        if (player == "")
 
240
                return;
 
241
        cmdline.append(player);
 
242
        cmdline.append(" '");
 
243
        cmdline.append(str);
 
244
        cmdline.append("'");
 
245
        stfl::reset();
 
246
        GetLogger().log(LOG_DEBUG, "pb_controller::play_file: running `%s'", cmdline.c_str());
 
247
        ::system(cmdline.c_str());
 
248
}
 
249
 
 
250
 
 
251
} // namespace