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
|
#define AL_LOG_SECTION "cdio"
#include <al/log.h>
#include "../../cache/entry.h"
#include "../../cache/handlers/cdio.h"
#include "cdio.h"
#define SECTORS_PER_PACKET 8
static bool cdio_server_init(struct lia_server_handler *handler, struct cch_handle *handle)
{
struct lia_cdio_server *cdio = (struct lia_cdio_server *)handler;
cdio->handle = handle;
cdio->fmt.format = CAMU_SAMPLE_FORMAT_S16;
cdio->fmt.sample_rate = 44100;
cdio->fmt.channel_count = 2;
nn_buffer_init(&cdio->buffer);
cdio->pts = 0.0;
if (handle->entry->chapter) {
cch_handle_seek(handle, handle->entry->chapter->start * CDIO_CD_FRAMESIZE_RAW, SEEK_SET);
}
return true;
}
static void cdio_server_write_info(struct lia_server_handler *handler, struct nn_packet *packet)
{
struct lia_cdio_server *cdio = (struct lia_cdio_server *)handler;
u64 duration = cdio->handler.get_duration(&cdio->handler);
nn_packet_write_u64(packet, duration);
nn_packet_write_u32(packet, 1); // 1 stream.
nn_packet_write_str(packet, &al_str_c("pcm_s16le"));
nn_packet_write_u8(packet, CAMU_NORMAL);
nn_packet_write_u8(packet, CAMU_STREAM_AUDIO);
nn_packet_write_u64(packet, duration);
nn_packet_write_s32(packet, 0); // index.
nn_packet_write_s32(packet, cdio->fmt.format);
nn_packet_write_s32(packet, cdio->fmt.sample_rate);
nn_packet_write_s32(packet, cdio->fmt.channel_count);
}
static void cdio_server_subscribe(struct lia_server_handler *handler, u64 mask)
{
(void)handler;
(void)mask;
}
static u64 cdio_server_get_duration(struct lia_server_handler *handler)
{
struct lia_cdio_server *cdio = (struct lia_cdio_server *)handler;
struct cch_chapter *first = &al_array_at(cdio->handle->entry->chapters, 0);
struct cch_chapter *last = &al_array_last(cdio->handle->entry->chapters);
u64 length = camu_audio_format_bytes_to_usec(&cdio->fmt, (last->end - first->start) * CDIO_CD_FRAMESIZE_RAW);
log_info("Length: %.2fs.", length / 1000000.0);
return length;
}
static bool cdio_server_seek(struct lia_server_handler *handler, u64 pos)
{
struct lia_cdio_server *cdio = (struct lia_cdio_server *)handler;
(void)cdio;
(void)pos;
return false;
}
static void cdio_server_step(struct lia_server_handler *handler)
{
struct lia_cdio_server *cdio = (struct lia_cdio_server *)handler;
(void)cdio;
}
static void cdio_server_write_packet(struct lia_server_handler *handler, struct nn_packet *packet)
{
struct lia_cdio_server *cdio = (struct lia_cdio_server *)handler;
off_t size = CDIO_CD_FRAMESIZE_RAW * SECTORS_PER_PACKET;
nn_buffer_ensure_space(&cdio->buffer, size);
s32 ret = cch_handle_read(cdio->handle, nn_buffer_get_ptr(&cdio->buffer, 0), size);
if (ret == CAMU_ERR_EOF) {
cdio->handler.status = CAMU_ERR_EOF;
nn_packet_write_u8(packet, LIANA_PACKET_EOF);
return;
}
cdio->handler.status = CAMU_OK;
nn_packet_write_u8(packet, LIANA_PACKET_DATA);
nn_packet_write_s32(packet, 0);
nn_packet_write_f64(packet, cdio->pts);
s32 sample_count = ret / (camu_audio_format_bytes_per_sample(&cdio->fmt) * cdio->fmt.channel_count);
nn_packet_write_s32(packet, sample_count);
cdio->buffer.size = ret;
nn_packet_write_buffer(packet, &cdio->buffer);
cdio->pts += camu_audio_format_samples_to_sec(&cdio->fmt, sample_count);
}
static void cdio_server_free(struct lia_server_handler **handler)
{
struct lia_cdio_server *cdio = (struct lia_cdio_server *)*handler;
al_free(cdio);
*handler = NULL;
}
struct lia_server_handler *lia_cdio_server_create()
{
struct lia_cdio_server *cdio = al_alloc_object(struct lia_cdio_server);
cdio->handler.init = cdio_server_init;
cdio->handler.write_info = cdio_server_write_info;
cdio->handler.subscribe = cdio_server_subscribe;
cdio->handler.get_duration = cdio_server_get_duration;
cdio->handler.seek = cdio_server_seek;
cdio->handler.step = cdio_server_step;
cdio->handler.write_packet = cdio_server_write_packet;
cdio->handler.free = cdio_server_free;
return (struct lia_server_handler *)cdio;
}
|