~ubuntu-branches/ubuntu/jaunty/imms/jaunty

« back to all changes in this revision

Viewing changes to plugin.cc

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Veber
  • Date: 2005-04-13 23:43:11 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050413234311-kzr68z9l7z5mv551
Tags: 2.0.3-2
Build depend on xmms-dev (>= 1.2.10+cvs20050209)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *      The XMMS plugin portion of IMMS
3
 
 */
4
 
 
5
 
#include <string>
6
 
#include <iostream>
7
 
#include <time.h>
8
 
 
9
 
#include <xmms/plugin.h>
10
 
#include <xmms/xmmsctrl.h> 
11
 
 
12
 
#include "immsconf.h"
13
 
#include "plugin.h"
14
 
#include "player.h"
15
 
#include "imms.h"
16
 
 
17
 
using std::string;
18
 
 
19
 
#define SPECTRUM_SKIP       0.15
20
 
#define POLL_DELAY          5
21
 
 
22
 
// Local vars
23
 
static Imms *imms = NULL;
24
 
unsigned int time_left = 1000, sloppy_skips = 0;
25
 
int last_plpos = -2, cur_plpos, pl_length = -1;
26
 
int good_length = 0, song_length = 0, delay = 0;
27
 
string cur_path = "", last_path = "";
28
 
bool spectrum_ok = false;
29
 
 
30
 
// Extern from interface.c
31
 
extern VisPlugin imms_vp;
32
 
int &session = imms_vp.xmms_session;
33
 
 
34
 
static enum
35
 
{
36
 
    IDLE        = 0,
37
 
    BUSY        = 1,
38
 
    FIND_NEXT   = 2
39
 
} state;
40
 
 
41
 
void Player::reset_selection() {}
42
 
 
43
 
// Wrapper that frees memory
44
 
string imms_get_playlist_item(int at)
45
 
{
46
 
    if (at > pl_length - 1)
47
 
        return "";
48
 
    char *tmp = 0;
49
 
    while (!tmp)
50
 
       tmp = xmms_remote_get_playlist_file(session, at);
51
 
    string result = tmp;
52
 
    free(tmp);
53
 
    return result;
54
 
}
55
 
 
56
 
void imms_setup(int use_xidle)
57
 
{
58
 
    if (imms)
59
 
        imms->setup(use_xidle);
60
 
}
61
 
 
62
 
void imms_init()
63
 
{
64
 
    if (!imms)
65
 
        imms = new Imms();
66
 
 
67
 
    state = IDLE;
68
 
}
69
 
 
70
 
void imms_cleanup(void)
71
 
{
72
 
    delete imms;
73
 
    imms = 0;
74
 
}
75
 
 
76
 
void imms_spectrum(uint16_t spectrum[256])
77
 
{
78
 
    if (imms && spectrum_ok)
79
 
        imms->integrate_spectrum(spectrum);
80
 
}
81
 
 
82
 
void do_more_checks()
83
 
{
84
 
    delay = 0;
85
 
 
86
 
    // make sure shuffle is disabled
87
 
    if (imms && xmms_remote_is_shuffle(session))
88
 
        xmms_remote_toggle_shuffle(session);
89
 
 
90
 
    // update playlist length
91
 
    int new_pl_length = xmms_remote_get_playlist_length(session);
92
 
    if (new_pl_length != pl_length)
93
 
    {
94
 
        pl_length = new_pl_length;
95
 
        imms->playlist_changed();
96
 
    }
97
 
 
98
 
    // check if xmms is reporting the song length correctly
99
 
    song_length = xmms_remote_get_playlist_time(session, cur_plpos);
100
 
    if (song_length > 1000)
101
 
        good_length++;
102
 
 
103
 
    // have imms do it's internal processing
104
 
    imms->do_events();
105
 
}
106
 
 
107
 
void do_checks()
108
 
{
109
 
    if (last_plpos == -2)
110
 
        last_plpos = xmms_remote_get_playlist_pos(session) - 1;
111
 
 
112
 
    // if not playing make sure we stopped collecting spectrum statistics
113
 
    if (!xmms_remote_is_playing(session))
114
 
    {
115
 
        imms->do_idle_events();
116
 
        return;
117
 
    }
118
 
 
119
 
    // run these checks less frequently so as not to waste cpu time
120
 
    if (++delay > POLL_DELAY || pl_length < 0 || good_length < 3)
121
 
        do_more_checks();
122
 
 
123
 
    // do not preemptively end the song if imms is disabled 
124
 
    // to allow the built in shuffle/sequential to take effect
125
 
    bool ending = good_length > 2 && time_left == 0;
126
 
    cur_plpos = xmms_remote_get_playlist_pos(session);
127
 
 
128
 
    if (ending || cur_plpos != last_plpos)
129
 
    {
130
 
        cur_path = imms_get_playlist_item(cur_plpos);
131
 
 
132
 
        if (ending || last_path != cur_path)
133
 
        {
134
 
            xmms_remote_stop(session);
135
 
            state = FIND_NEXT;
136
 
            return;
137
 
        }
138
 
 
139
 
        last_plpos = cur_plpos;
140
 
    }
141
 
 
142
 
    // check the time to catch the end of the song
143
 
    int cur_time = xmms_remote_get_output_time(session);
144
 
    if (cur_time > 1000 || good_length < 3)
145
 
        time_left = (song_length - cur_time) / 500;
146
 
 
147
 
    spectrum_ok = (cur_time > song_length * SPECTRUM_SKIP
148
 
            && cur_time < song_length * (1 - SPECTRUM_SKIP));
149
 
}
150
 
 
151
 
void do_find_next()
152
 
{
153
 
    if (time_left < 20)
154
 
        time_left = 0;
155
 
 
156
 
    cur_plpos = xmms_remote_get_playlist_pos(session);
157
 
    bool forced = (cur_plpos != last_plpos) && 
158
 
        ((last_plpos + 1) % pl_length) != cur_plpos;
159
 
    bool back = ((last_plpos + pl_length - 1) % pl_length) == cur_plpos;
160
 
    bool bad = good_length < 3 || song_length <= 30*1000;
161
 
 
162
 
    // notify imms that the previous song has ended
163
 
    if (last_path != "")
164
 
        imms->end_song(!time_left, forced, bad);
165
 
 
166
 
    if (!forced && pl_length > 2)
167
 
    {
168
 
        // have imms select the next song for us
169
 
        cur_plpos = imms->select_next();
170
 
    }
171
 
    else if (back)
172
 
    {
173
 
        int previous = imms->get_previous();
174
 
        if (previous != -1)
175
 
            cur_plpos = previous;
176
 
    }
177
 
 
178
 
    cur_path = imms_get_playlist_item(cur_plpos);
179
 
    xmms_remote_set_playlist_pos(session, cur_plpos);
180
 
 
181
 
    // notify imms of the next song
182
 
    imms->start_song(cur_plpos, cur_path);
183
 
 
184
 
    last_path = cur_path;
185
 
    good_length = 0;
186
 
 
187
 
    xmms_remote_play(session);
188
 
}
189
 
 
190
 
void imms_poll()
191
 
{
192
 
    switch (state)
193
 
    {
194
 
    case BUSY:
195
 
        return;
196
 
 
197
 
    case IDLE:
198
 
        state = BUSY;
199
 
        do_checks();
200
 
        if (state == BUSY)
201
 
            state = IDLE;
202
 
        return;
203
 
 
204
 
    case FIND_NEXT:
205
 
        state = BUSY;
206
 
        do_find_next();
207
 
        state = IDLE;
208
 
        return;
209
 
    }
210
 
}