music_smpeg.c
author Ozkan Sezer <sezeroz@gmail.com>
Wed, 03 Oct 2018 21:55:00 +0300
changeset 863 b81eb791d10d
parent 848 3907db698eb5
child 900 b56dbe75cac8
permissions -rw-r--r--
readmidi.c (groom_list): avoid integer overflow when recomputing time.

from libtimidity -- see:
https://sourceforge.net/p/libtimidity/libtimidity/ci/11be98a89eac229111420e6a3d521edbfddb0dbc/
slouken@777
     1
/*
slouken@777
     2
  SDL_mixer:  An audio mixer library based on the SDL library
slouken@848
     3
  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
slouken@777
     4
slouken@777
     5
  This software is provided 'as-is', without any express or implied
slouken@777
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@777
     7
  arising from the use of this software.
slouken@777
     8
slouken@777
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@777
    10
  including commercial applications, and to alter it and redistribute it
slouken@777
    11
  freely, subject to the following restrictions:
slouken@777
    12
slouken@777
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@777
    14
     claim that you wrote the original software. If you use this software
slouken@777
    15
     in a product, an acknowledgment in the product documentation would be
slouken@777
    16
     appreciated but is not required.
slouken@777
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@777
    18
     misrepresented as being the original software.
slouken@777
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@777
    20
*/
slouken@777
    21
slouken@777
    22
#ifdef MUSIC_MP3_SMPEG
slouken@777
    23
slouken@777
    24
#include "SDL_loadso.h"
slouken@777
    25
slouken@777
    26
#include "music_smpeg.h"
slouken@777
    27
slouken@777
    28
#if SDL_VERSION_ATLEAST(2, 0, 0)
slouken@777
    29
/* Forward declaration for SDL 2.0  because struct is not available there but
slouken@777
    30
   still used in a file included with smpeg.h. May not compile if missing. */
slouken@777
    31
typedef struct SDL_Overlay SDL_Overlay;
slouken@777
    32
#endif
slouken@777
    33
slouken@777
    34
#include "smpeg.h"
slouken@777
    35
slouken@777
    36
typedef struct {
slouken@777
    37
    int loaded;
slouken@777
    38
    void *handle;
slouken@777
    39
    void (*SMPEG_actualSpec)(SMPEG *mpeg, SDL_AudioSpec *spec);
slouken@777
    40
    void (*SMPEG_delete)(SMPEG* mpeg);
slouken@777
    41
    void (*SMPEG_enableaudio)(SMPEG* mpeg, int enable);
slouken@777
    42
    void (*SMPEG_enablevideo)(SMPEG* mpeg, int enable);
slouken@777
    43
    SMPEG* (*SMPEG_new_rwops)(SDL_RWops *src, SMPEG_Info* info, int freesrc, int sdl_audio);
slouken@777
    44
    void (*SMPEG_play)(SMPEG* mpeg);
slouken@777
    45
    int (*SMPEG_playAudio)(SMPEG *mpeg, Uint8 *stream, int len);
slouken@777
    46
    void (*SMPEG_rewind)(SMPEG* mpeg);
slouken@777
    47
    void (*SMPEG_setvolume)(SMPEG* mpeg, int volume);
slouken@777
    48
    void (*SMPEG_skip)(SMPEG* mpeg, float seconds);
slouken@777
    49
    SMPEGstatus (*SMPEG_status)(SMPEG* mpeg);
slouken@777
    50
    void (*SMPEG_stop)(SMPEG* mpeg);
slouken@777
    51
} smpeg_loader;
slouken@777
    52
slouken@777
    53
static smpeg_loader smpeg = {
slouken@777
    54
    0, NULL
slouken@777
    55
};
slouken@777
    56
slouken@777
    57
#ifdef SMPEG_DYNAMIC
slouken@798
    58
#define FUNCTION_LOADER(FUNC, SIG) \
slouken@798
    59
    smpeg.FUNC = (SIG) SDL_LoadFunction(smpeg.handle, #FUNC); \
slouken@798
    60
    if (smpeg.FUNC == NULL) { SDL_UnloadObject(smpeg.handle); return -1; }
slouken@798
    61
#else
slouken@798
    62
#define FUNCTION_LOADER(FUNC, SIG) \
slouken@798
    63
    smpeg.FUNC = FUNC;
slouken@798
    64
#endif
slouken@777
    65
slouken@777
    66
static int SMPEG_Load(void)
slouken@777
    67
{
slouken@777
    68
    if (smpeg.loaded == 0) {
slouken@798
    69
#ifdef SMPEG_DYNAMIC
slouken@777
    70
        smpeg.handle = SDL_LoadObject(SMPEG_DYNAMIC);
slouken@777
    71
        if (smpeg.handle == NULL) {
slouken@777
    72
            return -1;
slouken@777
    73
        }
slouken@798
    74
#elif defined(__MACOSX__)
slouken@798
    75
        extern SMPEG* SMPEG_new_rwops(SDL_RWops*, SMPEG_Info*, int, int) __attribute__((weak_import));
slouken@798
    76
        if (SMPEG_new_rwops == NULL)
slouken@798
    77
        {
slouken@798
    78
            /* Missing weakly linked framework */
slouken@798
    79
            Mix_SetError("Missing smpeg2.framework");
slouken@777
    80
            return -1;
slouken@777
    81
        }
slouken@798
    82
#endif
slouken@798
    83
        FUNCTION_LOADER(SMPEG_actualSpec, void (*)(SMPEG *, SDL_AudioSpec *))
slouken@798
    84
        FUNCTION_LOADER(SMPEG_delete, void (*)(SMPEG*))
slouken@798
    85
        FUNCTION_LOADER(SMPEG_enableaudio, void (*)(SMPEG*, int))
slouken@798
    86
        FUNCTION_LOADER(SMPEG_enablevideo, void (*)(SMPEG*, int))
slouken@798
    87
        FUNCTION_LOADER(SMPEG_new_rwops, SMPEG* (*)(SDL_RWops *, SMPEG_Info*, int, int))
slouken@798
    88
        FUNCTION_LOADER(SMPEG_play, void (*)(SMPEG*))
slouken@798
    89
        FUNCTION_LOADER(SMPEG_playAudio, int (*)(SMPEG *, Uint8 *, int))
slouken@798
    90
        FUNCTION_LOADER(SMPEG_rewind, void (*)(SMPEG*))
slouken@798
    91
        FUNCTION_LOADER(SMPEG_setvolume, void (*)(SMPEG*, int))
slouken@798
    92
        FUNCTION_LOADER(SMPEG_skip, void (*)(SMPEG*, float))
slouken@798
    93
        FUNCTION_LOADER(SMPEG_status, SMPEGstatus (*)(SMPEG*))
slouken@798
    94
        FUNCTION_LOADER(SMPEG_stop, void (*)(SMPEG*))
slouken@777
    95
    }
slouken@777
    96
    ++smpeg.loaded;
slouken@777
    97
slouken@777
    98
    return 0;
slouken@777
    99
}
slouken@777
   100
slouken@777
   101
static void SMPEG_Unload(void)
slouken@777
   102
{
slouken@777
   103
    if (smpeg.loaded == 0) {
slouken@777
   104
        return;
slouken@777
   105
    }
slouken@777
   106
    if (smpeg.loaded == 1) {
slouken@798
   107
#ifdef SMPEG_DYNAMIC
slouken@777
   108
        SDL_UnloadObject(smpeg.handle);
slouken@798
   109
#endif
slouken@777
   110
    }
slouken@777
   111
    --smpeg.loaded;
slouken@777
   112
}
slouken@777
   113
slouken@777
   114
slouken@797
   115
typedef struct
slouken@797
   116
{
slouken@797
   117
    SMPEG *mp3;
slouken@797
   118
    SDL_RWops *src;
slouken@797
   119
    int freesrc;
slouken@797
   120
} SMPEG_Music;
slouken@797
   121
slouken@777
   122
static void *SMPEG_CreateFromRW(SDL_RWops *src, int freesrc)
slouken@777
   123
{
slouken@797
   124
    SMPEG_Music *music;
slouken@777
   125
    SMPEG_Info info;
slouken@797
   126
slouken@797
   127
    music = (SMPEG_Music *)SDL_calloc(1, sizeof(*music));
slouken@797
   128
    if (!music) {
slouken@797
   129
        SDL_OutOfMemory();
slouken@797
   130
        return NULL;
slouken@797
   131
    }
slouken@797
   132
    music->src = src;
slouken@797
   133
slouken@797
   134
    music->mp3 = smpeg.SMPEG_new_rwops(src, &info, SDL_FALSE, 0);
slouken@777
   135
    if (!info.has_audio) {
slouken@777
   136
        Mix_SetError("MPEG file does not have any audio stream.");
slouken@797
   137
        smpeg.SMPEG_delete(music->mp3);
slouken@797
   138
        SDL_free(music);
slouken@777
   139
        return NULL;
slouken@777
   140
    }
slouken@777
   141
    smpeg.SMPEG_actualSpec(mp3, &music_spec);
slouken@797
   142
slouken@797
   143
    music->freesrc = freesrc;
slouken@797
   144
    return music;
slouken@777
   145
}
slouken@777
   146
slouken@777
   147
static void SMPEG_SetVolume(void *context, int volume)
slouken@777
   148
{
slouken@797
   149
    SMPEG_Music *music = (SMPEG_Music *)context;
slouken@797
   150
    smpeg.SMPEG_setvolume(music->mp3,(int)(((float)volume/(float)MIX_MAX_VOLUME)*100.0));
slouken@777
   151
}
slouken@777
   152
slouken@777
   153
static int SMPEG_Play(void *context)
slouken@777
   154
{
slouken@797
   155
    SMPEG_Music *music = (SMPEG_Music *)context;
slouken@797
   156
    smpeg.SMPEG_enableaudio(music->mp3, 1);
slouken@797
   157
    smpeg.SMPEG_enablevideo(music->mp3, 0);
slouken@797
   158
    smpeg.SMPEG_rewind(music->mp3);
slouken@797
   159
    smpeg.SMPEG_play(music->mp3);
slouken@777
   160
    return 0;
slouken@777
   161
}
slouken@777
   162
slouken@777
   163
static SDL_bool SMPEG_IsPlaying(void *context)
slouken@777
   164
{
slouken@797
   165
    SMPEG_Music *music = (SMPEG_Music *)context;
slouken@797
   166
    return smpeg.SMPEG_status(music->mp3) == SMPEG_PLAYING ? SDL_TRUE : SDL_FALSE;
slouken@777
   167
}
slouken@777
   168
slouken@777
   169
static int SMPEG_GetAudio(void *context, void *data, int bytes)
slouken@777
   170
{
slouken@797
   171
    SMPEG_Music *music = (SMPEG_Music *)context;
slouken@777
   172
    Uint8 *stream = (Uint8 *)data;
slouken@777
   173
    int len = bytes;
slouken@797
   174
    int left = (len - smpeg.SMPEG_playAudio(music->mp3, stream, len));
slouken@797
   175
    if (left > 0) {
slouken@797
   176
        stream += (len - left);
slouken@777
   177
    return left;
slouken@777
   178
}
slouken@777
   179
slouken@777
   180
static int SMPEG_Seek(void *context, double position)
slouken@777
   181
{
slouken@797
   182
    SMPEG_Music *music = (SMPEG_Music *)context;
slouken@797
   183
    smpeg.SMPEG_rewind(music->mp3);
slouken@797
   184
    smpeg.SMPEG_play(music->mp3);
slouken@777
   185
    if (position > 0.0) {
slouken@797
   186
        smpeg.SMPEG_skip(music->mp3, (float)position);
slouken@777
   187
    }
slouken@777
   188
    return 0;
slouken@777
   189
}
slouken@777
   190
slouken@777
   191
static void SMPEG_Stop(void *context)
slouken@777
   192
{
slouken@797
   193
    SMPEG_Music *music = (SMPEG_Music *)context;
slouken@797
   194
    smpeg.SMPEG_stop(music->mp3);
slouken@777
   195
}
slouken@777
   196
slouken@777
   197
static void SMPEG_Delete(void *context)
slouken@777
   198
{
slouken@797
   199
    SMPEG_Music *music = (SMPEG_Music *)context;
slouken@797
   200
slouken@797
   201
    smpeg.SMPEG_delete(music->mp3);
slouken@797
   202
slouken@797
   203
    if (music->freesrc) {
slouken@797
   204
        SDL_RWclose(music->src);
slouken@797
   205
    }
slouken@797
   206
    SDL_free(music);
slouken@777
   207
}
slouken@777
   208
slouken@777
   209
Mix_MusicInterface Mix_MusicInterface_SMPEG =
slouken@777
   210
{
slouken@777
   211
    "SMPEG",
slouken@777
   212
    MIX_MUSIC_SMPEG,
slouken@777
   213
    MUS_MP3,
slouken@777
   214
    SDL_FALSE,
slouken@777
   215
    SDL_FALSE,
slouken@777
   216
slouken@777
   217
    SMPEG_Load,
slouken@777
   218
    NULL,   /* Open */
slouken@777
   219
    SMPEG_CreateFromRW,
slouken@777
   220
    NULL,   /* CreateFromFile */
slouken@777
   221
    SMPEG_SetVolume,
slouken@777
   222
    SMPEG_Play,
slouken@777
   223
    SMPEG_IsPlaying,
slouken@777
   224
    SMPEG_GetAudio,
slouken@777
   225
    SMPEG_Seek,
slouken@777
   226
    NULL,   /* Pause */
slouken@777
   227
    NULL,   /* Resume */
slouken@777
   228
    SMPEG_Stop,
slouken@777
   229
    SMPEG_Delete,
slouken@777
   230
    NULL,   /* Close */
slouken@777
   231
    SMPEG_Unload,
slouken@777
   232
};
slouken@777
   233
slouken@777
   234
#endif /* MUSIC_MP3_SMPEG */
slouken@777
   235
slouken@777
   236
/* vi: set ts=4 sw=4 expandtab: */