Semi working version
This commit is contained in:
parent
333ab8f82d
commit
a80bd0c480
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,5 @@
|
|||||||
/build/sdlamp2
|
/build/sdlamp2
|
||||||
/build/sdlamp2.dSYM
|
/build/sdlamp2.dSYM
|
||||||
|
*.mp3
|
||||||
|
*.m4a
|
||||||
|
|
||||||
|
|||||||
10
build.sh
10
build.sh
@ -1,11 +1,15 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
pushd build
|
pushd build 2>&1 >/dev/null
|
||||||
|
|
||||||
gcc -Wall -O0 -ggdb3 \
|
gcc -Wall -Wno-unused -O0 -ggdb3 \
|
||||||
-o sdlamp2 \
|
-o sdlamp2 \
|
||||||
`sdl2-config --cflags --libs` \
|
`sdl2-config --cflags --libs` \
|
||||||
|
`pkgconf --cflags --libs libavformat` \
|
||||||
|
`pkgconf --cflags --libs libavcodec` \
|
||||||
|
`pkgconf --cflags --libs libavutil` \
|
||||||
|
`pkgconf --cflags --libs libswresample` \
|
||||||
-lSDL2_image \
|
-lSDL2_image \
|
||||||
../src/sdlamp2.c
|
../src/sdlamp2.c
|
||||||
|
|
||||||
popd
|
popd 2>&1 >/dev/null
|
||||||
|
|||||||
165
src/sdlamp2.c
165
src/sdlamp2.c
@ -1,25 +1,29 @@
|
|||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavutil/avutil.h>
|
||||||
|
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
#include "SDL_image.h"
|
#include "SDL_image.h"
|
||||||
|
|
||||||
static SDL_Window *window = NULL;
|
static SDL_Window* window = NULL;
|
||||||
static SDL_Renderer *renderer = NULL;
|
static SDL_Renderer* renderer = NULL;
|
||||||
|
|
||||||
static SDL_AudioDeviceID audio_device = 0;
|
static SDL_AudioDeviceID audio_device = 0;
|
||||||
static Uint8 *wavbuf = NULL;
|
static Uint8* wavbuf = NULL;
|
||||||
static Uint32 wavlen = 0;
|
static Uint32 wavlen = 0;
|
||||||
static SDL_AudioSpec wavspec;
|
static SDL_AudioSpec wavspec;
|
||||||
static SDL_AudioStream *stream = NULL;
|
static SDL_AudioStream* stream = NULL;
|
||||||
// static SDL_bool paused = SDL_TRUE;
|
// static SDL_bool paused = SDL_TRUE;
|
||||||
static SDL_bool paused = SDL_FALSE;
|
static SDL_bool paused = SDL_FALSE;
|
||||||
|
|
||||||
static void panic_and_abort(const char *title, const char *text) {
|
static void panic_and_abort(const char* title, const char* text) {
|
||||||
fprintf(stderr, "PANIC: %s ... %s\n", title, text);
|
fprintf(stderr, "PANIC: %s ... %s\n", title, text);
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, text, window);
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, text, window);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool load_audio_file(const char *fname) {
|
static SDL_bool load_audio_file(const char* fname) {
|
||||||
SDL_FreeAudioStream(stream);
|
SDL_FreeAudioStream(stream);
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
SDL_FreeWAV(wavbuf);
|
SDL_FreeWAV(wavbuf);
|
||||||
@ -27,33 +31,99 @@ static SDL_bool load_audio_file(const char *fname) {
|
|||||||
wavlen = 0;
|
wavlen = 0;
|
||||||
|
|
||||||
if (SDL_LoadWAV(fname, &wavspec, &wavbuf, &wavlen) == NULL) {
|
if (SDL_LoadWAV(fname, &wavspec, &wavbuf, &wavlen) == NULL) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't load wav file!",
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't load wav file!", SDL_GetError(),
|
||||||
SDL_GetError(), window);
|
window);
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream = SDL_NewAudioStream(wavspec.format, wavspec.channels, wavspec.freq,
|
stream = SDL_NewAudioStream(wavspec.format, wavspec.channels, wavspec.freq, AUDIO_F32, 2, 48000);
|
||||||
AUDIO_F32, 2, 48000);
|
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create audio stream!", SDL_GetError(),
|
||||||
"Couldn't create audio stream!", SDL_GetError(),
|
|
||||||
window);
|
window);
|
||||||
SDL_FreeWAV(wavbuf);
|
SDL_FreeWAV(wavbuf);
|
||||||
wavbuf = NULL;
|
wavbuf = NULL;
|
||||||
wavlen = 0;
|
wavlen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_AudioStreamPut(stream, wavbuf, wavlen) ==
|
if (SDL_AudioStreamPut(stream, wavbuf, wavlen) == -1) { // FIXME(m): graceful handling.
|
||||||
-1) { // FIXME(m): graceful handling.
|
|
||||||
panic_and_abort("Audio stream put failed!", SDL_GetError());
|
panic_and_abort("Audio stream put failed!", SDL_GetError());
|
||||||
}
|
}
|
||||||
SDL_AudioStreamFlush(stream); // FIXME(m): error handling.
|
SDL_AudioStreamFlush(stream); // FIXME(m): error handling.
|
||||||
SDL_PauseAudioDevice(audio_device, paused);
|
SDL_PauseAudioDevice(audio_device, paused);
|
||||||
|
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
static SDL_bool decode_audio() {
|
||||||
|
printf("libavutil version: %s\n", av_version_info());
|
||||||
|
|
||||||
|
// Trying to open and decode AAC / ALAC (.m4a file) with ffmpeg libraries
|
||||||
|
AVFormatContext* pFormatContext = avformat_alloc_context();
|
||||||
|
if (avformat_open_input(&pFormatContext, "./build/music.m4a", NULL, NULL) != 0) {
|
||||||
|
printf("ERROR: could not open the file!\n");
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
printf("Format: %s\n", pFormatContext->iformat->long_name);
|
||||||
|
|
||||||
|
avformat_find_stream_info(pFormatContext, NULL);
|
||||||
|
if (pFormatContext->nb_streams < 1) {
|
||||||
|
printf("ERROR: no valid streams found in file!\n");
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVCodecParameters* pLocalCodecParameters = pFormatContext->streams[0]->codecpar;
|
||||||
|
if (pLocalCodecParameters->codec_type != AVMEDIA_TYPE_AUDIO) {
|
||||||
|
printf("ERROR: no audio stream found in file!\n");
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Audio stream: %d channels, sample rate %d\n",
|
||||||
|
pLocalCodecParameters->ch_layout.nb_channels, pLocalCodecParameters->sample_rate);
|
||||||
|
|
||||||
|
const AVCodec* pLocalCodec = avcodec_find_decoder(pLocalCodecParameters->codec_id);
|
||||||
|
printf("Codec: %s ID %d bit_rate %lld\n", pLocalCodec->long_name, pLocalCodec->id,
|
||||||
|
pLocalCodecParameters->bit_rate);
|
||||||
|
|
||||||
|
AVCodecContext* pCodecContext = avcodec_alloc_context3(pLocalCodec);
|
||||||
|
avcodec_parameters_to_context(pCodecContext, pLocalCodecParameters);
|
||||||
|
avcodec_open2(pCodecContext, pLocalCodec, NULL);
|
||||||
|
|
||||||
|
AVPacket* pPacket = av_packet_alloc();
|
||||||
|
AVFrame* pFrame = av_frame_alloc();
|
||||||
|
|
||||||
|
SDL_FreeAudioStream(stream);
|
||||||
|
stream = NULL;
|
||||||
|
wavlen = 0;
|
||||||
|
|
||||||
|
stream = SDL_NewAudioStream(AUDIO_F32, pLocalCodecParameters->ch_layout.nb_channels,
|
||||||
|
pLocalCodecParameters->sample_rate, AUDIO_F32, 2, 48000);
|
||||||
|
if (!stream) {
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create audio stream!", SDL_GetError(),
|
||||||
|
window);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (av_read_frame(pFormatContext, pPacket) >= 0) {
|
||||||
|
if (!avcodec_send_packet(pCodecContext, pPacket)) {
|
||||||
|
avcodec_receive_frame(pCodecContext, pFrame);
|
||||||
|
if (pFrame->linesize[0] > 0) {
|
||||||
|
if (SDL_AudioStreamPut(stream, pFrame->data[0], pFrame->linesize[0]) ==
|
||||||
|
-1) { // FIXME(m): graceful handling.
|
||||||
|
panic_and_abort("Audio stream put failed!", SDL_GetError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("Frame %c (%lld) pts %lld dts %lld\n", av_get_picture_type_char(pFrame->pict_type),
|
||||||
|
// pCodecContext->frame_num, pFrame->pts, pFrame->pkt_dts);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_AudioStreamFlush(stream); // FIXME(m): error handling.
|
||||||
|
SDL_PauseAudioDevice(audio_device, paused);
|
||||||
|
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
SDL_AudioSpec desired;
|
SDL_AudioSpec desired;
|
||||||
SDL_bool running = SDL_TRUE;
|
SDL_bool running = SDL_TRUE;
|
||||||
const SDL_Rect rewind_rect = {10, 10, 100, 100};
|
const SDL_Rect rewind_rect = {10, 10, 100, 100};
|
||||||
@ -71,8 +141,8 @@ int main(int argc, char **argv) {
|
|||||||
panic_and_abort("SDL_Init failed!", SDL_GetError());
|
panic_and_abort("SDL_Init failed!", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
window = SDL_CreateWindow("SDLamp2", SDL_WINDOWPOS_UNDEFINED,
|
window =
|
||||||
SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
|
SDL_CreateWindow("SDLamp2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
|
||||||
if (!window) {
|
if (!window) {
|
||||||
panic_and_abort("SDL_CreateWindow failed!", SDL_GetError());
|
panic_and_abort("SDL_CreateWindow failed!", SDL_GetError());
|
||||||
}
|
}
|
||||||
@ -94,15 +164,15 @@ int main(int argc, char **argv) {
|
|||||||
panic_and_abort("Could not open audio device!", SDL_GetError());
|
panic_and_abort("Could not open audio device!", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
load_audio_file("music.wav");
|
// load_audio_file("music.wav");
|
||||||
|
decode_audio();
|
||||||
|
|
||||||
SDL_Surface *controls_surface = IMG_Load("controls.png");
|
SDL_Surface* controls_surface = IMG_Load("controls.png");
|
||||||
if (controls_surface == NULL) {
|
if (controls_surface == NULL) {
|
||||||
panic_and_abort("Could not load controls asset!", SDL_GetError());
|
panic_and_abort("Could not load controls asset!", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Texture *controls_texture =
|
SDL_Texture* controls_texture = SDL_CreateTextureFromSurface(renderer, controls_surface);
|
||||||
SDL_CreateTextureFromSurface(renderer, controls_surface);
|
|
||||||
SDL_FreeSurface(controls_surface);
|
SDL_FreeSurface(controls_surface);
|
||||||
if (controls_texture == NULL) {
|
if (controls_texture == NULL) {
|
||||||
panic_and_abort("Could not load controls asset!", SDL_GetError());
|
panic_and_abort("Could not load controls asset!", SDL_GetError());
|
||||||
@ -113,28 +183,27 @@ int main(int argc, char **argv) {
|
|||||||
// Event loop
|
// Event loop
|
||||||
while (SDL_PollEvent(&e)) {
|
while (SDL_PollEvent(&e)) {
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
running = SDL_FALSE;
|
running = SDL_FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_MOUSEBUTTONDOWN: {
|
case SDL_MOUSEBUTTONDOWN: {
|
||||||
const SDL_Point pt = {e.button.x, e.button.y};
|
const SDL_Point pt = {e.button.x, e.button.y};
|
||||||
if (SDL_PointInRect(&pt, &rewind_rect)) { // Pressed the "rewind" button
|
if (SDL_PointInRect(&pt,
|
||||||
SDL_ClearQueuedAudio(audio_device);
|
&rewind_rect)) { // Pressed the "rewind" button
|
||||||
SDL_AudioStreamClear(stream);
|
SDL_ClearQueuedAudio(audio_device);
|
||||||
if (SDL_AudioStreamPut(stream, wavbuf, wavlen) ==
|
SDL_AudioStreamClear(stream);
|
||||||
-1) { // FIXME(m): graceful handling.
|
if (SDL_AudioStreamPut(stream, wavbuf, wavlen) == -1) { // FIXME(m): graceful handling.
|
||||||
panic_and_abort("Audio stream put failed!", SDL_GetError());
|
panic_and_abort("Audio stream put failed!", SDL_GetError());
|
||||||
|
}
|
||||||
|
SDL_AudioStreamFlush(stream); // FIXME(m): error handling.
|
||||||
|
} else if (SDL_PointInRect(&pt,
|
||||||
|
&play_pause_rect)) { // Pressed the "pause" button
|
||||||
|
paused = paused ? SDL_FALSE : SDL_TRUE;
|
||||||
|
SDL_PauseAudioDevice(audio_device, paused);
|
||||||
}
|
}
|
||||||
SDL_AudioStreamFlush(stream); // FIXME(m): error handling.
|
break;
|
||||||
} else if (SDL_PointInRect(
|
|
||||||
&pt,
|
|
||||||
&play_pause_rect)) { // Pressed the "pause" button
|
|
||||||
paused = paused ? SDL_FALSE : SDL_TRUE;
|
|
||||||
SDL_PauseAudioDevice(audio_device, paused);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +214,7 @@ int main(int argc, char **argv) {
|
|||||||
const int new_bytes = SDL_min(bytes_remaining, 32 * 1024);
|
const int new_bytes = SDL_min(bytes_remaining, 32 * 1024);
|
||||||
static Uint8 converted_buffer[32 * 1024];
|
static Uint8 converted_buffer[32 * 1024];
|
||||||
SDL_AudioStreamGet(stream, converted_buffer,
|
SDL_AudioStreamGet(stream, converted_buffer,
|
||||||
new_bytes); // FIXME(m): error handling.
|
new_bytes); // FIXME(m): error handling.
|
||||||
SDL_QueueAudio(audio_device, converted_buffer, new_bytes);
|
SDL_QueueAudio(audio_device, converted_buffer, new_bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,18 +229,14 @@ int main(int argc, char **argv) {
|
|||||||
SDL_RenderFillRect(renderer, &play_pause_rect);
|
SDL_RenderFillRect(renderer, &play_pause_rect);
|
||||||
SDL_RenderFillRect(renderer, &fast_forward_rect);
|
SDL_RenderFillRect(renderer, &fast_forward_rect);
|
||||||
|
|
||||||
SDL_RenderCopy(renderer, controls_texture, &rewind_symbol_rect,
|
SDL_RenderCopy(renderer, controls_texture, &rewind_symbol_rect, &rewind_rect);
|
||||||
&rewind_rect);
|
|
||||||
SDL_RenderCopy(renderer, controls_texture, &stop_symbol_rect, &stop_rect);
|
SDL_RenderCopy(renderer, controls_texture, &stop_symbol_rect, &stop_rect);
|
||||||
if (paused) {
|
if (paused) {
|
||||||
SDL_RenderCopy(renderer, controls_texture, &play_symbol_rect,
|
SDL_RenderCopy(renderer, controls_texture, &play_symbol_rect, &play_pause_rect);
|
||||||
&play_pause_rect);
|
|
||||||
} else {
|
} else {
|
||||||
SDL_RenderCopy(renderer, controls_texture, &pause_symbol_rect,
|
SDL_RenderCopy(renderer, controls_texture, &pause_symbol_rect, &play_pause_rect);
|
||||||
&play_pause_rect);
|
|
||||||
}
|
}
|
||||||
SDL_RenderCopy(renderer, controls_texture, &fast_forward_symbol_rect,
|
SDL_RenderCopy(renderer, controls_texture, &fast_forward_symbol_rect, &fast_forward_rect);
|
||||||
&fast_forward_rect);
|
|
||||||
|
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user