Subversion Repositories freemyipod

Rev

Rev 509 | Rev 820 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
504 theseven 1
//
2
//
3
//    Copyright 2011 TheSeven
4
//
5
//
6
//    This file is part of emCORE.
7
//
8
//    emCORE is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
13
//    emCORE is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "emcorelib.h"
25
#include "libui.h"
26
#include "chooser.h"
27
 
28
 
29
void chooser_button_handler(void* user, enum button_event event, int which, int value)
30
{
31
    struct chooser_data* data = (struct chooser_data*)user;
32
    switch (data->info->actionhandler->handleevent(data, event, which, value))
33
    {
34
    case CHOOSER_RESULT_REDRAW:
35
        mutex_lock(&data->statemutex, TIMEOUT_BLOCK);
36
        data->redrawneeded = true;
37
        wakeup_signal(&data->eventwakeup);
38
        mutex_unlock(&data->statemutex);
39
        break;
40
    case CHOOSER_RESULT_CANCEL:
41
        mutex_lock(&data->statemutex, TIMEOUT_BLOCK);
42
        data->canceled = true;
43
        wakeup_signal(&data->eventwakeup);
44
        mutex_unlock(&data->statemutex);
45
        break;
46
    case CHOOSER_RESULT_FINISHED:
47
        mutex_lock(&data->statemutex, TIMEOUT_BLOCK);
48
        data->finished = true;
49
        wakeup_signal(&data->eventwakeup);
50
        mutex_unlock(&data->statemutex);
51
        break;
52
    }
53
}
54
 
55
const struct chooser_item* chooser_run(const struct chooser_info* info)
56
{
57
    struct chooser_data data;
58
    const struct chooser_item* rc = NULL;
59
    if (info->version != CHOOSER_INFO_VERSION) goto done;
60
    if (!info->actionhandler) goto done;
61
    if (info->actionhandler->version != CHOOSER_ACTION_HANDLER_VERSION) goto done;
62
    if (!info->renderer) goto done;
63
    if (info->renderer->version != CHOOSER_RENDERER_VERSION) goto done;
64
    if (info->defaultitem >= info->itemcount) data.selected = &info->items[info->itemcount - 1];
65
    else data.selected = &info->items[info->defaultitem];
66
    data.info = info;
67
    data.redrawneeded = false;
68
    data.canceled = false;
69
    data.finished = false;
70
    data.position = 0;
71
    data.actionhandlerdata = NULL;
72
    data.rendererdata = NULL;
73
    mutex_init(&data.statemutex);
74
    wakeup_init(&data.eventwakeup);
75
    if (info->actionhandler->init)
76
        if (info->actionhandler->init(&data) < 0)
77
            goto done;
78
    data.selected = &info->items[info->defaultitem];
509 theseven 79
    int spi = info->actionhandler->stepsperitem(&data);
80
    data.position = info->defaultitem * spi + spi / 2;
504 theseven 81
    if (info->renderer->init)
82
        if (info->renderer->init(&data) < 0)
83
            goto destroy_actionhandler;
84
    struct button_hook_entry* hook = button_register_handler(chooser_button_handler, &data);
85
    if (!hook) goto destroy_renderer;
86
    long lasttick = USEC_TIMER;
87
    bool redrawneeded = true;
88
    while (true)
89
    {
90
        long sleeptime = lasttick + info->tickinterval - USEC_TIMER;
91
        if (sleeptime > 0 && !redrawneeded) wakeup_wait(&data.eventwakeup, sleeptime);
92
        mutex_lock(&data.statemutex, TIMEOUT_BLOCK);
93
        if (data.canceled) goto cancel;
94
        if (data.finished) goto finished;
95
        redrawneeded |= data.redrawneeded;
96
        data.redrawneeded = false;
97
        if ((long)(lasttick + info->tickinterval - USEC_TIMER) < 0)
98
        {
99
            if (info->actionhandler->handletick)
100
                switch (info->actionhandler->handletick(&data))
101
                {
102
                case CHOOSER_RESULT_REDRAW:
103
                    redrawneeded = true;
104
                    break;
105
                case CHOOSER_RESULT_CANCEL:
106
                    goto cancel;
107
                case CHOOSER_RESULT_FINISHED:
108
                    goto finished;
109
                }
110
            lasttick = USEC_TIMER;
111
        }
686 theseven 112
        mutex_unlock(&data.statemutex);
509 theseven 113
        if (redrawneeded) redrawneeded = info->renderer->render(&data) == CHOOSER_RESULT_REDRAW;
504 theseven 114
    }
115
cancel:
116
    data.selected = NULL;
117
finished:
118
    rc = data.selected;
686 theseven 119
    mutex_unlock(&data.statemutex);
504 theseven 120
destroy_buttonhook:
121
    button_unregister_handler(hook);
122
destroy_renderer:
123
    if (info->renderer->destroy)
124
        info->renderer->destroy(&data);
125
destroy_actionhandler:
126
    if (info->actionhandler->destroy)
127
        info->actionhandler->destroy(&data);
128
done:
129
    return rc;
130
}