| 143 | } |
| 144 | |
| 145 | static void |
| 146 | mpcdec_decode(DecoderClient &client, InputStream &is) |
| 147 | { |
| 148 | mpc_decoder_data data(is, &client); |
| 149 | |
| 150 | mpc_reader reader; |
| 151 | reader.read = mpc_read_cb; |
| 152 | reader.seek = mpc_seek_cb; |
| 153 | reader.tell = mpc_tell_cb; |
| 154 | reader.get_size = mpc_getsize_cb; |
| 155 | reader.canseek = mpc_canseek_cb; |
| 156 | reader.data = &data; |
| 157 | |
| 158 | mpc_demux *demux = mpc_demux_init(&reader); |
| 159 | if (demux == nullptr) { |
| 160 | if (client.GetCommand() != DecoderCommand::STOP) |
| 161 | LogWarning(mpcdec_domain, |
| 162 | "Not a valid musepack stream"); |
| 163 | return; |
| 164 | } |
| 165 | |
| 166 | AtScopeExit(demux) { mpc_demux_exit(demux); }; |
| 167 | |
| 168 | mpc_streaminfo info; |
| 169 | mpc_demux_get_info(demux, &info); |
| 170 | |
| 171 | auto audio_format = CheckAudioFormat(info.sample_freq, |
| 172 | mpcdec_sample_format, |
| 173 | info.channels); |
| 174 | |
| 175 | { |
| 176 | const auto rgi = ImportMpcdecReplayGain(info); |
| 177 | if (rgi.IsDefined()) |
| 178 | client.SubmitReplayGain(&rgi); |
| 179 | } |
| 180 | |
| 181 | client.Ready(audio_format, is.IsSeekable(), |
| 182 | SongTime::FromS(mpc_streaminfo_get_length(&info))); |
| 183 | |
| 184 | DecoderCommand cmd = DecoderCommand::NONE; |
| 185 | do { |
| 186 | if (cmd == DecoderCommand::SEEK) { |
| 187 | mpc_int64_t where = client.GetSeekFrame(); |
| 188 | bool success; |
| 189 | |
| 190 | success = mpc_demux_seek_sample(demux, where) |
| 191 | == MPC_STATUS_OK; |
| 192 | if (success) |
| 193 | client.CommandFinished(); |
| 194 | else |
| 195 | client.SeekError(); |
| 196 | } |
| 197 | |
| 198 | MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH]; |
| 199 | mpc_frame_info frame; |
| 200 | frame.buffer = (MPC_SAMPLE_FORMAT *)sample_buffer; |
| 201 | mpc_status status = mpc_demux_decode(demux, &frame); |
| 202 | if (status != MPC_STATUS_OK) { |
nothing calls this directly
no test coverage detected