summaryrefslogtreecommitdiff
path: root/apps/plugins/clock/clock_menu.c
blob: ed0027305b1ac80f932b4f34dc68769ba7d81617 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2003 Zakk Roberts
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/

#include "clock.h"
#include "clock_bitmaps.h"
#include "clock_settings.h"
#include "lib/playback_control.h"

/* Option structs (possible selections per each option) */
static const struct opt_items noyes_text[] = {
    { "No", -1 },
    { "Yes", -1 }
};

static const struct opt_items backlight_settings_text[] = {
    { "Always Off", -1 },
    { "Use Rockbox Setting", -1 },
    { "Always On", -1 }
};

static const struct opt_items idle_poweroff_text[] = {
    { "Disabled", -1 },
    { "Enabled", -1 }
};

static const struct opt_items date_format_text[] = {
    { "No date", -1 },
    { "US (M-D-Y)", -1 },
    { "European (D-M-Y)", -1 },
    { "Japanese (Y-M-D)", -1 },
};

static const struct opt_items hour_format_text[] = {
    { "24-Hour", -1 },
    { "12-Hour", -1 }
};

/***************
 * Select a mode, returs true when the mode has been selected
 * (we go back to clock display then)
 **************/
bool menu_mode_selector(void){
    MENUITEM_STRINGLIST(menu,"Mode Selector",NULL, "Analog",
                        "Digital", "Binary");
    if(rb->do_menu(&menu, &clock_settings.mode, NULL, false) >=0)
        return(true);
    return(false);
}

/**********************
 * Analog settings menu
 *********************/
void menu_analog_settings(void)
{
    int selection=0, result=0;

    MENUITEM_STRINGLIST(menu,"Analog Mode Settings",NULL,"Show Date",
                        "Show Second Hand","Show Border");

    while(result>=0){
        result=rb->do_menu(&menu, &selection, NULL, false);
        switch(result){
            case 0:
                rb->set_option("Show Date", &clock_settings.analog.show_date,
                               BOOL, noyes_text, 2, NULL);
                break;
            case 1:
                rb->set_option("Show Second Hand",
                               &clock_settings.analog.show_seconds,
                               BOOL, noyes_text, 2, NULL);
                break;
            case 2:
                rb->set_option("Show Border",
                               &clock_settings.analog.show_border,
                               BOOL, noyes_text, 2, NULL);
                break;
        }
    }
}

/***********************
 * Digital settings menu
 **********************/
void menu_digital_settings(void){
    int selection=0, result=0;

    MENUITEM_STRINGLIST(menu,"Digital Mode Settings",NULL,"Show Seconds",
                        "Blinking Colon");

    while(result>=0){
        result=rb->do_menu(&menu, &selection, NULL, false);
        switch(result){
            case 0:
                rb->set_option("Show Seconds",
                               &clock_settings.digital.show_seconds,
                               BOOL, noyes_text, 2, NULL);
                break;
            case 1:
                rb->set_option("Blinking Colon",
                               &clock_settings.digital.blinkcolon,
                               BOOL, noyes_text, 2, NULL);
                break;
        }
    }
}

/***********************************************************
 * Confirm resetting of settings, used in general_settings()
 **********************************************************/
void confirm_reset(void){
    int result=0;

    rb->set_option("Reset all settings?", &result, INT, noyes_text, 2, NULL);

    if(result == 1){ /* reset! */
        clock_settings_reset(&clock_settings);
        rb->splash(HZ, "Settings reset!");
    }
    else
        rb->splash(HZ, "Settings NOT reset.");
}

/************************************
 * General settings. Reset, save, etc
 ***********************************/
void menu_general_settings(void){
    int selection=0, result=0;

    MENUITEM_STRINGLIST(menu,"General Settings",NULL,
                        "Hour Format","Date Format","Show Counter",
                        "Reset Settings","Save Settings Now",
                        "Save On Exit","Backlight Settings",
                        "Idle Poweroff (temporary)");

    while(result>=0){
        result=rb->do_menu(&menu, &selection, NULL, false);
        switch(result){
            case 0:
                rb->set_option("Hour format",
                               &clock_settings.general.hour_format,
                               INT, hour_format_text, 2, NULL);
                break;
            case 1:
                rb->set_option("Date format",
                               &clock_settings.general.date_format,
                               INT, date_format_text, 4, NULL);
                break;
            case 2:
                rb->set_option("Show Counter", &clock_settings.general.show_counter,
                               BOOL, noyes_text, 2, NULL);
                break;
            case 3:
                confirm_reset();
                break;

            case 4:
                save_settings_wo_gui();
                rb->splash(HZ, "Settings saved");
                break;

            case 5:
                rb->set_option("Save On Exit",
                               &clock_settings.general.save_settings,
                               BOOL, noyes_text, 2, NULL);

                /* if we no longer save on exit,
                   we better save now to remember that */
                if(!clock_settings.general.save_settings)
                    save_settings_wo_gui();
                break;
            case 6:
                rb->set_option("Backlight Settings",
                               &clock_settings.general.backlight,
                               INT, backlight_settings_text, 3, NULL);
                apply_backlight_setting(clock_settings.general.backlight);
                break;

            case 7:
                rb->set_option("Idle Poweroff (temporary)",
                               &clock_settings.general.idle_poweroff,
                               BOOL, idle_poweroff_text, 2, NULL);
                break;
        }
    }
}

/***********
 * Main menu
 **********/
bool main_menu(void){
    int selection=0;
    bool done = false;
    bool exit_clock=false;

    MENUITEM_STRINGLIST(menu,"Clock Menu",NULL,"View Clock","Mode Selector",
                        "Mode Settings","General Settings","Playback Control",
                        "Quit");

    while(!done){
        switch(rb->do_menu(&menu, &selection, NULL, false)){
            case 0:
                done = true;
                break;

            case 1:
                done=menu_mode_selector();
                break;

            case 2:
                switch(clock_settings.mode){
                    case ANALOG: menu_analog_settings();break;
                    case DIGITAL: menu_digital_settings();break;
                    case BINARY: /* no settings */;break;
                }
                break;

            case 3:
                menu_general_settings();
                break;

            case 4:
                playback_control(NULL);
                break;

            case 5:
                exit_clock = true;
                done = true;
                break;

            default:
                done=true;
                break;
        }
    }
    return(exit_clock);
}
n1110' href='#n1110'>1110 1111 1112 1113 1114 1115 1116 1117 1118
/* libFLAC - Free Lossless Audio Codec library
 * Copyright (C) 2000,2001,2002,2003,2004,2005  Josh Coalson
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of the Xiph.org Foundation nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include "global.h" /* for calloc() */
#include <string.h> /* for memcpy()/memcmp() */
#include "FLAC/assert.h"
#include "protected/seekable_stream_decoder.h"
#include "protected/stream_decoder.h"
#include "private/float.h" /* for FLAC__double */
#include "private/md5.h"

/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */
#ifdef _MSC_VER
#define FLAC__U64L(x) x
#else
#define FLAC__U64L(x) x##LLU
#endif

/***********************************************************************
 *
 * Private class method prototypes
 *
 ***********************************************************************/

static void set_defaults_(FLAC__SeekableStreamDecoder *decoder);
static FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
static FLAC__bool seek_to_absolute_sample_(FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);

/***********************************************************************
 *
 * Private class data
 *
 ***********************************************************************/

typedef struct FLAC__SeekableStreamDecoderPrivate {
	FLAC__SeekableStreamDecoderReadCallback read_callback;
	FLAC__SeekableStreamDecoderSeekCallback seek_callback;
	FLAC__SeekableStreamDecoderTellCallback tell_callback;
	FLAC__SeekableStreamDecoderLengthCallback length_callback;
	FLAC__SeekableStreamDecoderEofCallback eof_callback;
	FLAC__SeekableStreamDecoderWriteCallback write_callback;
	FLAC__SeekableStreamDecoderMetadataCallback metadata_callback;
	FLAC__SeekableStreamDecoderErrorCallback error_callback;
	void *client_data;
	FLAC__StreamDecoder *stream_decoder;
	FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek */
	struct FLAC__MD5Context md5context;
	FLAC__byte stored_md5sum[16]; /* this is what is stored in the metadata */
	FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */
	/* the rest of these are only used for seeking: */
	FLAC__StreamMetadata_StreamInfo stream_info; /* we keep this around so we can figure out how to seek quickly */
	const FLAC__StreamMetadata_SeekTable *seek_table; /* we hold a pointer to the stream decoder's seek table for the same reason */
	/* Since we always want to see the STREAMINFO and SEEK_TABLE blocks at this level, we need some extra flags to keep track of whether they should be passed on up through the metadata_callback */
	FLAC__bool ignore_stream_info_block;
	FLAC__bool ignore_seek_table_block;
	FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */
	FLAC__uint64 target_sample;
} FLAC__SeekableStreamDecoderPrivate;

/***********************************************************************
 *
 * Public static class data
 *
 ***********************************************************************/

FLAC_API const char * const FLAC__SeekableStreamDecoderStateString[] = {
	"FLAC__SEEKABLE_STREAM_DECODER_OK",
	"FLAC__SEEKABLE_STREAM_DECODER_SEEKING",
	"FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM",
	"FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR",
	"FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR",
	"FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR",
	"FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR",
	"FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED",
	"FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK",
	"FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED"
};

FLAC_API const char * const FLAC__SeekableStreamDecoderReadStatusString[] = {
	"FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK",
	"FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR"
};

FLAC_API const char * const FLAC__SeekableStreamDecoderSeekStatusString[] = {
	"FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK",
	"FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR"
};

FLAC_API const char * const FLAC__SeekableStreamDecoderTellStatusString[] = {
	"FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK",
	"FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR"
};

FLAC_API const char * const FLAC__SeekableStreamDecoderLengthStatusString[] = {
	"FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK",
	"FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR"
};


/***********************************************************************
 *
 * Class constructor/destructor
 *
 ***********************************************************************/

FLAC__SeekableStreamDecoder _ssd;
FLAC__SeekableStreamDecoderProtected _ssdprotected IDATA_ATTR;
FLAC__SeekableStreamDecoderPrivate _ssdprivate IDATA_ATTR;

FLAC_API FLAC__SeekableStreamDecoder *FLAC__seekable_stream_decoder_new(void)
{
	FLAC__SeekableStreamDecoder *decoder;

	FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */

    decoder = &_ssd;
    /*decoder = (FLAC__SeekableStreamDecoder*)calloc(1, sizeof(FLAC__SeekableStreamDecoder));
	if(decoder == 0) {
		return 0;
	}*/

	decoder->protected_ = &_ssdprotected;
    /*decoder->protected_ = (FLAC__SeekableStreamDecoderProtected*)calloc(1, sizeof(FLAC__SeekableStreamDecoderProtected));
	if(decoder->protected_ == 0) {
		free(decoder);
		return 0;
	}*/

	decoder->private_ = &_ssdprivate;
    /*decoder->private_ = (FLAC__SeekableStreamDecoderPrivate*)calloc(1, sizeof(FLAC__SeekableStreamDecoderPrivate));
	if(decoder->private_ == 0) {
		free(decoder->protected_);
		free(decoder);
		return 0;
	}*/

	decoder->private_->stream_decoder = FLAC__stream_decoder_new();
	if(0 == decoder->private_->stream_decoder) {
		/*free(decoder->private_);
		free(decoder->protected_);
		free(decoder);*/
		return 0;
	}

	set_defaults_(decoder);

	decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED;

	return decoder;
}

FLAC_API void FLAC__seekable_stream_decoder_delete(FLAC__SeekableStreamDecoder *decoder)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->protected_);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->private_->stream_decoder);

	(void)FLAC__seekable_stream_decoder_finish(decoder);

	FLAC__stream_decoder_delete(decoder->private_->stream_decoder);

	/*free(decoder->private_);
	free(decoder->protected_);
	free(decoder);*/
}

/***********************************************************************
 *
 * Public class methods
 *
 ***********************************************************************/

FLAC_API FLAC__SeekableStreamDecoderState FLAC__seekable_stream_decoder_init(FLAC__SeekableStreamDecoder *decoder)
{
	FLAC__ASSERT(0 != decoder);

	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED;

	if(0 == decoder->private_->read_callback || 0 == decoder->private_->seek_callback || 0 == decoder->private_->tell_callback || 0 == decoder->private_->length_callback || 0 == decoder->private_->eof_callback)
		return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;

	if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
		return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;

	decoder->private_->seek_table = 0;

	decoder->private_->do_md5_checking = decoder->protected_->md5_checking;

	/* We initialize the FLAC__MD5Context even though we may never use it.  This
	 * is because md5 checking may be turned on to start and then turned off if
	 * a seek occurs.  So we always init the context here and finalize it in
	 * FLAC__seekable_stream_decoder_finish() to make sure things are always
	 * cleaned up properly.
	 */
	FLAC__MD5Init(&decoder->private_->md5context);

	FLAC__stream_decoder_set_read_callback(decoder->private_->stream_decoder, read_callback_);
	FLAC__stream_decoder_set_write_callback(decoder->private_->stream_decoder, write_callback_);
	FLAC__stream_decoder_set_metadata_callback(decoder->private_->stream_decoder, metadata_callback_);
	FLAC__stream_decoder_set_error_callback(decoder->private_->stream_decoder, error_callback_);
	FLAC__stream_decoder_set_client_data(decoder->private_->stream_decoder, decoder);

	/* We always want to see these blocks.  Whether or not we pass them up
	 * through the metadata callback will be determined by flags set in our
	 * implementation of ..._set_metadata_respond/ignore...()
	 */
	FLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO);
	FLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);

	if(FLAC__stream_decoder_init(decoder->private_->stream_decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
		return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;

	return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_OK;
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_finish(FLAC__SeekableStreamDecoder *decoder)
{
	FLAC__bool md5_failed = false;

	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);

	if(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return true;

	FLAC__ASSERT(0 != decoder->private_->stream_decoder);

	/* see the comment in FLAC__seekable_stream_decoder_init() as to why we
	 * always call FLAC__MD5Final()
	 */
	FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context);

	FLAC__stream_decoder_finish(decoder->private_->stream_decoder);

	if(decoder->private_->do_md5_checking) {
		if(memcmp(decoder->private_->stored_md5sum, decoder->private_->computed_md5sum, 16))
			md5_failed = true;
	}

	set_defaults_(decoder);

	decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED;

	return !md5_failed;
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_md5_checking(FLAC__SeekableStreamDecoder *decoder, FLAC__bool value)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->protected_);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->protected_->md5_checking = value;
	return true;
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_read_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderReadCallback value)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private_->read_callback = value;
	return true;
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_seek_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderSeekCallback value)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private_->seek_callback = value;
	return true;
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_tell_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderTellCallback value)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private_->tell_callback = value;
	return true;
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_length_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderLengthCallback value)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private_->length_callback = value;
	return true;
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_eof_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderEofCallback value)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private_->eof_callback = value;
	return true;
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_write_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderWriteCallback value)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private_->write_callback = value;
	return true;
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderMetadataCallback value)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private_->metadata_callback = value;
	return true;
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_error_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderErrorCallback value)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private_->error_callback = value;
	return true;
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_client_data(FLAC__SeekableStreamDecoder *decoder, void *value)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private_->client_data = value;
	return true;
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_respond(FLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);
	FLAC__ASSERT(0 != decoder->private_->stream_decoder);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return false;
	if(type == FLAC__METADATA_TYPE_STREAMINFO)
		decoder->private_->ignore_stream_info_block = false;
	else if(type == FLAC__METADATA_TYPE_SEEKTABLE)
		decoder->private_->ignore_seek_table_block = false;
	return FLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, type);
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_respond_application(FLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4])
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);
	FLAC__ASSERT(0 != decoder->private_->stream_decoder);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return false;
	return FLAC__stream_decoder_set_metadata_respond_application(decoder->private_->stream_decoder, id);
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_respond_all(FLAC__SeekableStreamDecoder *decoder)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);
	FLAC__ASSERT(0 != decoder->private_->stream_decoder);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private_->ignore_stream_info_block = false;
	decoder->private_->ignore_seek_table_block = false;
	return FLAC__stream_decoder_set_metadata_respond_all(decoder->private_->stream_decoder);
}

FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_ignore(FLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type)
{
	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);
	FLAC__ASSERT(0 != decoder->protected_);
	FLAC__ASSERT(0 != decoder->private_->stream_decoder);
	if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)