cleaning stuff
parent
c382af789c
commit
7c1801a236
|
@ -72,7 +72,8 @@ set(srcs
|
|||
source/input.h
|
||||
source/keys.c
|
||||
source/keys.h
|
||||
source/lodepng.h
|
||||
source/lib/lodepng.h
|
||||
source/lib/stb_image_write.h
|
||||
source/mathlib.c
|
||||
source/mathlib.h
|
||||
source/menu.c
|
||||
|
@ -117,25 +118,14 @@ set(srcs
|
|||
source/snd_codeci.h
|
||||
source/snd_dma.c
|
||||
source/snd_flac.c
|
||||
source/snd_flac.h
|
||||
source/snd_mem.c
|
||||
source/snd_mikmod.c
|
||||
source/snd_mikmod.h
|
||||
source/snd_mix.c
|
||||
source/snd_mp3.c
|
||||
source/snd_mp3.h
|
||||
source/snd_mpg123.c
|
||||
source/snd_opus.c
|
||||
source/snd_opus.h
|
||||
source/snd_umx.c
|
||||
source/snd_umx.h
|
||||
source/snd_vorbis.c
|
||||
source/snd_vorbis.h
|
||||
source/spritegn.h
|
||||
source/stb_image_write.h
|
||||
source/strl_fn.h
|
||||
source/strlcat.c
|
||||
source/strlcpy.c
|
||||
source/strl_fn.c
|
||||
source/sv_main.c
|
||||
source/sv_move.c
|
||||
source/sv_phys.c
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#define MUSIC_DIRNAME "music"
|
||||
|
||||
bool bgmloop;
|
||||
bool bgm_loop;
|
||||
cvar_t bgm_extmusic = {"bgm_extmusic", "1", CVAR_ARCHIVE};
|
||||
|
||||
static bool no_extmusic = false;
|
||||
|
@ -104,15 +104,15 @@ static void BGM_Loop_f(void)
|
|||
{
|
||||
if(q_strcasecmp(Cmd_Argv(1), "0") == 0 ||
|
||||
q_strcasecmp(Cmd_Argv(1), "off") == 0)
|
||||
bgmloop = false;
|
||||
bgm_loop = false;
|
||||
else if(q_strcasecmp(Cmd_Argv(1), "1") == 0 ||
|
||||
q_strcasecmp(Cmd_Argv(1), "on") == 0)
|
||||
bgmloop = true;
|
||||
bgm_loop = true;
|
||||
else if(q_strcasecmp(Cmd_Argv(1), "toggle") == 0)
|
||||
bgmloop = !bgmloop;
|
||||
bgm_loop = !bgm_loop;
|
||||
}
|
||||
|
||||
if(bgmloop)
|
||||
if(bgm_loop)
|
||||
Con_Printf("Music will be looped\n");
|
||||
else
|
||||
Con_Printf("Music will not be looped\n");
|
||||
|
@ -138,7 +138,7 @@ bool BGM_Init(void)
|
|||
if(COM_CheckParm("-noextmusic") != 0)
|
||||
no_extmusic = true;
|
||||
|
||||
bgmloop = true;
|
||||
bgm_loop = true;
|
||||
|
||||
for(i = 0; wanted_handlers[i].type != CODECTYPE_NONE; i++)
|
||||
{
|
||||
|
@ -278,7 +278,7 @@ void BGM_Play(const char *filename)
|
|||
Con_Printf("Couldn't handle music file %s\n", filename);
|
||||
}
|
||||
|
||||
void BGM_PlayCDtrack(byte track, bool looping)
|
||||
void BGM_PlayCDTrack(byte track, bool looping)
|
||||
{
|
||||
/* instead of searching by the order of music_handlers, do so by
|
||||
* the order of searchpath priority: the file from the searchpath
|
||||
|
@ -309,20 +309,20 @@ void BGM_PlayCDtrack(byte track, bool looping)
|
|||
while(handler)
|
||||
{
|
||||
if(! handler->is_available)
|
||||
goto _next;
|
||||
goto next;
|
||||
if(! CDRIPTYPE(handler->type))
|
||||
goto _next;
|
||||
goto next;
|
||||
q_snprintf(tmp, sizeof(tmp), "%s/track%02" PRIi32 ".%s",
|
||||
MUSIC_DIRNAME, (int32_t)track, handler->ext);
|
||||
if(! COM_FileExists(tmp, &path_id))
|
||||
goto _next;
|
||||
goto next;
|
||||
if(path_id > prev_id)
|
||||
{
|
||||
prev_id = path_id;
|
||||
type = handler->type;
|
||||
ext = handler->ext;
|
||||
}
|
||||
_next:
|
||||
next:
|
||||
handler = handler->next;
|
||||
}
|
||||
if(ext == NULL)
|
||||
|
@ -425,7 +425,7 @@ static void BGM_UpdateStream(void)
|
|||
}
|
||||
else if(res == 0) /* EOF */
|
||||
{
|
||||
if(bgmloop)
|
||||
if(bgm_loop)
|
||||
{
|
||||
if(did_rewind)
|
||||
{
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#ifndef spingle__bgmusic_h
|
||||
#define spingle__bgmusic_h
|
||||
|
||||
extern bool bgmloop;
|
||||
extern bool bgm_loop;
|
||||
extern cvar_t bgm_extmusic;
|
||||
|
||||
bool BGM_Init(void);
|
||||
|
@ -37,6 +37,6 @@ void BGM_Update(void);
|
|||
void BGM_Pause(void);
|
||||
void BGM_Resume(void);
|
||||
|
||||
void BGM_PlayCDtrack(byte track, bool looping);
|
||||
void BGM_PlayCDTrack(byte track, bool looping);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1173,9 +1173,9 @@ void CL_ParseServerMessage(void)
|
|||
cl.cdtrack = MSG_ReadByte();
|
||||
cl.looptrack = MSG_ReadByte();
|
||||
if((cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1))
|
||||
BGM_PlayCDtrack((byte)cls.forcetrack, true);
|
||||
BGM_PlayCDTrack((byte)cls.forcetrack, true);
|
||||
else
|
||||
BGM_PlayCDtrack((byte)cl.cdtrack, true);
|
||||
BGM_PlayCDTrack((byte)cl.cdtrack, true);
|
||||
break;
|
||||
|
||||
case svc_intermission:
|
||||
|
|
|
@ -178,22 +178,24 @@ int32_t Q_strncmp(const char *s1, const char *s2, int32_t count);
|
|||
int32_t Q_atoi(const char *str);
|
||||
float Q_atof(const char *str);
|
||||
|
||||
#include "strl_fn.h"
|
||||
/* use our own copies of strlcpy and strlcat taken from OpenBSD */
|
||||
size_t q_strlcpy(char *dst, const char *src, size_t size);
|
||||
size_t q_strlcat(char *dst, const char *src, size_t size);
|
||||
|
||||
/* locale-insensitive strcasecmp replacement functions: */
|
||||
extern int32_t q_strcasecmp(const char * s1, const char * s2);
|
||||
extern int32_t q_strncasecmp(const char *s1, const char *s2, size_t n);
|
||||
int32_t q_strcasecmp(const char * s1, const char * s2);
|
||||
int32_t q_strncasecmp(const char *s1, const char *s2, size_t n);
|
||||
|
||||
/* locale-insensitive case-insensitive alternative to strstr */
|
||||
extern char *q_strcasestr(const char *haystack, const char *needle);
|
||||
char *q_strcasestr(const char *haystack, const char *needle);
|
||||
|
||||
/* locale-insensitive strlwr/upr replacement functions: */
|
||||
extern char *q_strlwr(char *str);
|
||||
extern char *q_strupr(char *str);
|
||||
char *q_strlwr(char *str);
|
||||
char *q_strupr(char *str);
|
||||
|
||||
/* snprintf, vsnprintf : always use our versions. */
|
||||
extern int32_t q_snprintf(char *str, size_t size, const char *format, ...) FUNC_PRINTF(3, 4);
|
||||
extern int32_t q_vsnprintf(char *str, size_t size, const char *format, va_list args) FUNC_PRINTF(3, 0);
|
||||
int32_t q_snprintf(char *str, size_t size, const char *format, ...) FUNC_PRINTF(3, 4);
|
||||
int32_t q_vsnprintf(char *str, size_t size, const char *format, va_list args) FUNC_PRINTF(3, 0);
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
|
|
@ -25,14 +25,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#define STB_IMAGE_WRITE_STATIC
|
||||
#include "stb_image_write.h"
|
||||
#include "lib/stb_image_write.h"
|
||||
|
||||
#define LODEPNG_NO_COMPILE_DECODER
|
||||
#define LODEPNG_NO_COMPILE_CPP
|
||||
#define LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS
|
||||
#define LODEPNG_NO_COMPILE_ERROR_TEXT
|
||||
#include "lodepng.h"
|
||||
#include "lodepng.c"
|
||||
#include "lib/lodepng.h"
|
||||
#include "lib/lodepng.c"
|
||||
|
||||
static char loadfilename[MAX_OSPATH]; //file scope so that error messages can use it
|
||||
|
||||
|
|
|
@ -123,9 +123,6 @@ static void PR_LoadDef(ddef_t *def, byte const **data)
|
|||
def->type = ReadLittleShort(data);
|
||||
def->ofs = ReadLittleShort(data);
|
||||
def->s_name = ReadLittleLong(data);
|
||||
|
||||
if(def->ofs % 4 != 0)
|
||||
Host_Error("PR_LoadDef: offset must be 4 byte aligned");
|
||||
}
|
||||
|
||||
static void PR_LoadGlobalDefs(byte const *data)
|
||||
|
|
|
@ -27,15 +27,6 @@
|
|||
#include "snd_codec.h"
|
||||
#include "snd_codeci.h"
|
||||
|
||||
/* headers for individual codecs */
|
||||
#include "snd_mikmod.h"
|
||||
#include "snd_umx.h"
|
||||
#include "snd_flac.h"
|
||||
#include "snd_mp3.h"
|
||||
#include "snd_vorbis.h"
|
||||
#include "snd_opus.h"
|
||||
|
||||
|
||||
static snd_codec_t *codecs;
|
||||
|
||||
/*
|
||||
|
@ -61,22 +52,24 @@ void S_CodecInit(void)
|
|||
|
||||
/* Register in the inverse order
|
||||
* of codec choice preference: */
|
||||
extern snd_codec_t umx_codec;
|
||||
S_CodecRegister(&umx_codec);
|
||||
#if defined(USE_CODEC_MIKMOD)
|
||||
extern snd_codec_t mikmod_codec;
|
||||
S_CodecRegister(&mikmod_codec);
|
||||
#endif
|
||||
#if defined(USE_CODEC_FLAC)
|
||||
extern snd_codec_t flac_codec;
|
||||
S_CodecRegister(&flac_codec);
|
||||
#endif
|
||||
#if defined(USE_CODEC_OPUS)
|
||||
extern snd_codec_t opus_codec;
|
||||
S_CodecRegister(&opus_codec);
|
||||
#endif
|
||||
#if defined(USE_CODEC_VORBIS)
|
||||
extern snd_codec_t vorbis_codec;
|
||||
S_CodecRegister(&vorbis_codec);
|
||||
#endif
|
||||
#if defined(USE_CODEC_MP3)
|
||||
S_CodecRegister(&mp3_codec);
|
||||
#endif
|
||||
|
||||
codec = codecs;
|
||||
while(codec)
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#if defined(USE_CODEC_FLAC)
|
||||
#include "snd_codec.h"
|
||||
#include "snd_codeci.h"
|
||||
#include "snd_flac.h"
|
||||
|
||||
#undef LEGACY_FLAC
|
||||
#include <FLAC/stream_decoder.h>
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/* fLaC streaming music support. */
|
||||
|
||||
#ifndef spingle__snd_flac_h
|
||||
#define spingle__snd_flac_h
|
||||
|
||||
#if defined(USE_CODEC_FLAC)
|
||||
|
||||
extern snd_codec_t flac_codec;
|
||||
|
||||
#endif /* USE_CODEC_FLAC */
|
||||
|
||||
#endif
|
|
@ -23,7 +23,6 @@
|
|||
#if defined(USE_CODEC_MIKMOD)
|
||||
#include "snd_codec.h"
|
||||
#include "snd_codeci.h"
|
||||
#include "snd_mikmod.h"
|
||||
#include <mikmod.h>
|
||||
|
||||
#if ((LIBMIKMOD_VERSION+0) < 0x030105)
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/* module tracker decoding support using libmikmod */
|
||||
|
||||
#ifndef spingle__snd_mikmod_h
|
||||
#define spingle__snd_mikmod_h
|
||||
|
||||
#if defined(USE_CODEC_MIKMOD)
|
||||
|
||||
extern snd_codec_t mikmod_codec;
|
||||
|
||||
#endif /* USE_CODEC_MIKMOD */
|
||||
|
||||
#endif
|
556
source/snd_mp3.c
556
source/snd_mp3.c
|
@ -1,556 +0,0 @@
|
|||
/*
|
||||
* MP3 decoding support using libmad: Adapted from the SoX library at
|
||||
* http://sourceforge.net/projects/sox/, LGPLv2, Copyright (c) 2007-2009
|
||||
* SoX contributors, written by Fabrizio Gennari <fabrizio.ge@tiscali.it>,
|
||||
* with the decoding part based on the decoder tutorial program madlld
|
||||
* written by Bertrand Petit <madlld@phoe.fmug.org> (BSD license, see at
|
||||
* http://www.bsd-dk.dk/~elrond/audio/madlld/). The tag identification
|
||||
* functions were adapted from the GPL-licensed libid3tag library, see at
|
||||
* http://www.underbit.com/products/mad/. Adapted to Quake and Hexen II
|
||||
* game engines by O.Sezer :
|
||||
* Copyright (C) 2010-2015 O.Sezer <sezero@users.sourceforge.net>
|
||||
*
|
||||
* 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 program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "q_defs.h"
|
||||
|
||||
#if defined(USE_CODEC_MP3)
|
||||
#include "snd_codec.h"
|
||||
#include "snd_codeci.h"
|
||||
#include "snd_mp3.h"
|
||||
#include <mad.h>
|
||||
|
||||
#define ID3_TAG_FLAG_FOOTERPRESENT 0x10
|
||||
|
||||
/* Under Windows, importing data from DLLs is a dicey proposition. This is true
|
||||
* when using dlopen, but also true if linking directly against the DLL if the
|
||||
* header does not mark the data as __declspec(dllexport), which mad.h does not.
|
||||
* Sidestep the issue by defining our own mad_timer_zero. This is needed because
|
||||
* mad_timer_zero is used in some of the mad.h macros.
|
||||
*/
|
||||
#define mad_timer_zero mad_timer_zero_stub
|
||||
static mad_timer_t const mad_timer_zero_stub = {0, 0};
|
||||
|
||||
/* MAD returns values with MAD_F_FRACBITS (28) bits of precision, though it's
|
||||
not certain that all of them are meaningful. Default to 16 bits to
|
||||
align with most users expectation of output file should be 16 bits. */
|
||||
#define MP3_MAD_SAMPLEBITS 16
|
||||
#define MP3_MAD_SAMPLEWIDTH 2
|
||||
#define MP3_BUFFER_SIZE (5 * 8192)
|
||||
|
||||
/* Private data */
|
||||
typedef struct _mp3_priv_t
|
||||
{
|
||||
uint8_t mp3_buffer[MP3_BUFFER_SIZE];
|
||||
struct mad_stream stream;
|
||||
struct mad_frame frame;
|
||||
struct mad_synth synth;
|
||||
mad_timer_t timer;
|
||||
ptrdiff_t cursamp;
|
||||
size_t frame_count;
|
||||
} mp3_priv_t;
|
||||
|
||||
/* This function merges the functions tagtype() and id3_tag_query()
|
||||
* from MAD's libid3tag, so we don't have to link to it
|
||||
* Returns 0 if the frame is not an ID3 tag, tag length if it is */
|
||||
static inline bool tag_is_id3v1(const uint8_t *data, size_t length)
|
||||
{
|
||||
if(length >= 3 &&
|
||||
data[0] == 'T' && data[1] == 'A' && data[2] == 'G')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool tag_is_id3v2(const uint8_t *data, size_t length)
|
||||
{
|
||||
if(length >= 10 &&
|
||||
(data[0] == 'I' && data[1] == 'D' && data[2] == '3') &&
|
||||
data[3] < 0xff && data[4] < 0xff &&
|
||||
data[6] < 0x80 && data[7] < 0x80 && data[8] < 0x80 && data[9] < 0x80)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* http://wiki.hydrogenaud.io/index.php?title=APEv1_specification
|
||||
* http://wiki.hydrogenaud.io/index.php?title=APEv2_specification
|
||||
* Detect an APEv2 tag. (APEv1 has no header, so no luck.)
|
||||
*/
|
||||
static inline bool tag_is_apetag(const uint8_t *data, size_t length)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
if(length < 32) return false;
|
||||
if(memcmp(data, "APETAGEX", 8) != 0)
|
||||
return false;
|
||||
v = LittleLong(BytesLong(&data[8]));
|
||||
if(v != 2000)
|
||||
return false;
|
||||
v = 0;
|
||||
if(memcmp(&data[24], &v, 4) != 0 || memcmp(&data[28], &v, 4) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static size_t mp3_tagsize(const uint8_t *data, size_t length)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
if(tag_is_id3v1(data, length))
|
||||
return 128;
|
||||
|
||||
if(tag_is_id3v2(data, length))
|
||||
{
|
||||
uint8_t flags = data[5];
|
||||
size = 10 + (data[6] << 21) + (data[7] << 14) + (data[8] << 7) + data[9];
|
||||
if(flags & ID3_TAG_FLAG_FOOTERPRESENT)
|
||||
size += 10;
|
||||
for(; size < length && !data[size]; ++size)
|
||||
; /* Consume padding */
|
||||
return size;
|
||||
}
|
||||
|
||||
if(tag_is_apetag(data, length))
|
||||
{
|
||||
size = LittleLong(BytesLong(&data[12]));
|
||||
size += 32;
|
||||
return size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Attempts to read an ID3 tag at the current location in stream and
|
||||
* consume it all. Returns -1 if no tag is found. Its up to caller
|
||||
* to recover. */
|
||||
static int32_t mp3_inputtag(snd_stream_t *stream)
|
||||
{
|
||||
mp3_priv_t *p = (mp3_priv_t *) stream->priv;
|
||||
int32_t rc = -1;
|
||||
size_t remaining;
|
||||
size_t tagsize;
|
||||
|
||||
/* FIXME: This needs some more work if we are to ever
|
||||
* look at the ID3 frame. This is because the stream
|
||||
* may not be able to hold the complete ID3 frame.
|
||||
* We should consume the whole frame inside tagtype()
|
||||
* instead of outside of tagframe(). That would support
|
||||
* recovering when stream contains less then 8-bytes (header)
|
||||
* and also when ID3v2 is bigger then stream buffer size.
|
||||
* Need to pass in stream so that buffer can be
|
||||
* consumed as well as letting additional data to be
|
||||
* read in.
|
||||
*/
|
||||
remaining = p->stream.bufend - p->stream.next_frame;
|
||||
tagsize = mp3_tagsize(p->stream.this_frame, remaining);
|
||||
if(tagsize != 0)
|
||||
{
|
||||
mad_stream_skip(&p->stream, tagsize);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
/* We know that a valid frame hasn't been found yet
|
||||
* so help libmad out and go back into frame seek mode.
|
||||
* This is true whether an ID3 tag was found or not.
|
||||
*/
|
||||
mad_stream_sync(&p->stream);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* (Re)fill the stream buffer that is to be decoded. If any data
|
||||
* still exists in the buffer then they are first shifted to be
|
||||
* front of the stream buffer. */
|
||||
static int32_t mp3_inputdata(snd_stream_t *stream)
|
||||
{
|
||||
mp3_priv_t *p = (mp3_priv_t *) stream->priv;
|
||||
size_t bytes_read;
|
||||
size_t remaining;
|
||||
|
||||
remaining = p->stream.bufend - p->stream.next_frame;
|
||||
|
||||
/* libmad does not consume all the buffer it's given. Some
|
||||
* data, part of a truncated frame, is left unused at the
|
||||
* end of the buffer. That data must be put back at the
|
||||
* beginning of the buffer and taken in account for
|
||||
* refilling the buffer. This means that the input buffer
|
||||
* must be large enough to hold a complete frame at the
|
||||
* highest observable bit-rate (currently 448 kb/s).
|
||||
* TODO: Is 2016 bytes the size of the largest frame?
|
||||
* (448000*(1152/32000))/8
|
||||
*/
|
||||
memmove(p->mp3_buffer, p->stream.next_frame, remaining);
|
||||
|
||||
bytes_read = FS_fread(p->mp3_buffer + remaining, 1,
|
||||
MP3_BUFFER_SIZE - remaining, &stream->fh);
|
||||
if(bytes_read == 0)
|
||||
return -1;
|
||||
|
||||
mad_stream_buffer(&p->stream, p->mp3_buffer, bytes_read + remaining);
|
||||
p->stream.error = MAD_ERROR_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t mp3_startread(snd_stream_t *stream)
|
||||
{
|
||||
mp3_priv_t *p = (mp3_priv_t *) stream->priv;
|
||||
size_t ReadSize;
|
||||
|
||||
mad_stream_init(&p->stream);
|
||||
mad_frame_init(&p->frame);
|
||||
mad_synth_init(&p->synth);
|
||||
mad_timer_reset(&p->timer);
|
||||
|
||||
/* Decode at least one valid frame to find out the input
|
||||
* format. The decoded frame will be saved off so that it
|
||||
* can be processed later.
|
||||
*/
|
||||
ReadSize = FS_fread(p->mp3_buffer, 1, MP3_BUFFER_SIZE, &stream->fh);
|
||||
if(!ReadSize || FS_ferror(&stream->fh))
|
||||
return -1;
|
||||
|
||||
mad_stream_buffer(&p->stream, p->mp3_buffer, ReadSize);
|
||||
|
||||
/* Find a valid frame before starting up. This makes sure
|
||||
* that we have a valid MP3 and also skips past ID3v2 tags
|
||||
* at the beginning of the audio file.
|
||||
*/
|
||||
p->stream.error = MAD_ERROR_NONE;
|
||||
while(mad_frame_decode(&p->frame, &p->stream))
|
||||
{
|
||||
/* check whether input buffer needs a refill */
|
||||
if(p->stream.error == MAD_ERROR_BUFLEN)
|
||||
{
|
||||
if(mp3_inputdata(stream) == -1)
|
||||
return -1;/* EOF with no valid data */
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Consume any ID3 tags */
|
||||
mp3_inputtag(stream);
|
||||
|
||||
/* FIXME: We should probably detect when we've read
|
||||
* a bunch of non-ID3 data and still haven't found a
|
||||
* frame. In that case we can abort early without
|
||||
* scanning the whole file.
|
||||
*/
|
||||
p->stream.error = MAD_ERROR_NONE;
|
||||
}
|
||||
|
||||
if(p->stream.error)
|
||||
{
|
||||
Con_Printf("MP3: No valid MP3 frame found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(p->frame.header.mode)
|
||||
{
|
||||
case MAD_MODE_SINGLE_CHANNEL:
|
||||
case MAD_MODE_DUAL_CHANNEL:
|
||||
case MAD_MODE_JOINT_STEREO:
|
||||
case MAD_MODE_STEREO:
|
||||
stream->info.channels = MAD_NCHANNELS(&p->frame.header);
|
||||
break;
|
||||
default:
|
||||
Con_Printf("MP3: Cannot determine number of channels\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p->frame_count = 1;
|
||||
|
||||
mad_timer_add(&p->timer, p->frame.header.duration);
|
||||
mad_synth_frame(&p->synth, &p->frame);
|
||||
stream->info.rate = p->synth.pcm.samplerate;
|
||||
stream->info.bits = MP3_MAD_SAMPLEBITS;
|
||||
stream->info.width = MP3_MAD_SAMPLEWIDTH;
|
||||
|
||||
p->cursamp = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read up to len samples from p->synth
|
||||
* If needed, read some more MP3 data, decode them and synth them
|
||||
* Place in buf[].
|
||||
* Return number of samples read. */
|
||||
static int32_t mp3_decode(snd_stream_t *stream, byte *buf, int32_t len)
|
||||
{
|
||||
mp3_priv_t *p = (mp3_priv_t *) stream->priv;
|
||||
int32_t donow, i, done = 0;
|
||||
mad_fixed_t sample;
|
||||
int32_t chan, x;
|
||||
|
||||
do
|
||||
{
|
||||
x = (p->synth.pcm.length - p->cursamp) * stream->info.channels;
|
||||
donow = q_min(len, x);
|
||||
i = 0;
|
||||
while(i < donow)
|
||||
{
|
||||
for(chan = 0; chan < stream->info.channels; chan++)
|
||||
{
|
||||
sample = p->synth.pcm.samples[chan][p->cursamp];
|
||||
/* convert from fixed to int16_t,
|
||||
* write in host-endian format. */
|
||||
if(sample <= -MAD_F_ONE)
|
||||
sample = -0x7FFF;
|
||||
else if(sample >= MAD_F_ONE)
|
||||
sample = 0x7FFF;
|
||||
else
|
||||
sample >>= (MAD_F_FRACBITS + 1 - 16);
|
||||
#if HOST_BIGENDIAN
|
||||
*buf++ = (sample >> 8) & 0xFF;
|
||||
*buf++ = sample & 0xFF;
|
||||
#else
|
||||
*buf++ = sample & 0xFF;
|
||||
*buf++ = (sample >> 8) & 0xFF;
|
||||
#endif
|
||||
i++;
|
||||
}
|
||||
p->cursamp++;
|
||||
}
|
||||
|
||||
len -= donow;
|
||||
done += donow;
|
||||
|
||||
if(len == 0)
|
||||
break;
|
||||
|
||||
/* check whether input buffer needs a refill */
|
||||
if(p->stream.error == MAD_ERROR_BUFLEN)
|
||||
{
|
||||
if(mp3_inputdata(stream) == -1)
|
||||
{
|
||||
/* check feof() ?? */
|
||||
Con_DPrintf("mp3 EOF\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(mad_frame_decode(&p->frame, &p->stream))
|
||||
{
|
||||
if(MAD_RECOVERABLE(p->stream.error))
|
||||
{
|
||||
mp3_inputtag(stream);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(p->stream.error == MAD_ERROR_BUFLEN)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
Con_Printf("MP3: unrecoverable frame level error (%s)\n",
|
||||
mad_stream_errorstr(&p->stream));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
p->frame_count++;
|
||||
mad_timer_add(&p->timer, p->frame.header.duration);
|
||||
mad_synth_frame(&p->synth, &p->frame);
|
||||
p->cursamp = 0;
|
||||
}
|
||||
while(1);
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
static int32_t mp3_stopread(snd_stream_t *stream)
|
||||
{
|
||||
mp3_priv_t *p = (mp3_priv_t*) stream->priv;
|
||||
|
||||
mad_synth_finish(&p->synth);
|
||||
mad_frame_finish(&p->frame);
|
||||
mad_stream_finish(&p->stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool S_MP3_CodecInitialize(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void S_MP3_CodecShutdown(void)
|
||||
{
|
||||
}
|
||||
|
||||
static bool S_MP3_CodecOpenStream(snd_stream_t *stream)
|
||||
{
|
||||
int32_t err;
|
||||
|
||||
stream->priv = calloc(1, sizeof(mp3_priv_t));
|
||||
if(!stream->priv)
|
||||
{
|
||||
Con_Printf("Insufficient memory for MP3 audio\n");
|
||||
return false;
|
||||
}
|
||||
err = mp3_startread(stream);
|
||||
if(err != 0)
|
||||
{
|
||||
Con_Printf("%s is not a valid mp3 file\n", stream->name);
|
||||
}
|
||||
else if(stream->info.channels != 1 && stream->info.channels != 2)
|
||||
{
|
||||
Con_Printf("Unsupported number of channels %" PRIi32 " in %s\n",
|
||||
stream->info.channels, stream->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
free(stream->priv);
|
||||
return false;
|
||||
}
|
||||
|
||||
static int32_t S_MP3_CodecReadStream(snd_stream_t *stream, int32_t bytes, void *buffer)
|
||||
{
|
||||
int32_t res = mp3_decode(stream, (byte *)buffer, bytes / stream->info.width);
|
||||
return res * stream->info.width;
|
||||
}
|
||||
|
||||
static void S_MP3_CodecCloseStream(snd_stream_t *stream)
|
||||
{
|
||||
mp3_stopread(stream);
|
||||
free(stream->priv);
|
||||
S_CodecUtilClose(&stream);
|
||||
}
|
||||
|
||||
static int32_t S_MP3_CodecRewindStream(snd_stream_t *stream)
|
||||
{
|
||||
mp3_priv_t *p = (mp3_priv_t *) stream->priv;
|
||||
size_t initial_bitrate = p->frame.header.bitrate;
|
||||
size_t tagsize = 0, consumed = 0;
|
||||
int32_t vbr = 0; /* Variable Bit Rate, bool */
|
||||
bool depadded = false;
|
||||
|
||||
/* Reset all */
|
||||
FS_rewind(&stream->fh);
|
||||
mad_timer_reset(&p->timer);
|
||||
p->frame_count = 0;
|
||||
|
||||
/* They where opened in startread */
|
||||
mad_synth_finish(&p->synth);
|
||||
mad_frame_finish(&p->frame);
|
||||
mad_stream_finish(&p->stream);
|
||||
|
||||
mad_stream_init(&p->stream);
|
||||
mad_frame_init(&p->frame);
|
||||
mad_synth_init(&p->synth);
|
||||
|
||||
while(1) /* Read data from the MP3 file */
|
||||
{
|
||||
int32_t bytes_read, padding = 0;
|
||||
size_t leftover = p->stream.bufend - p->stream.next_frame;
|
||||
|
||||
memcpy(p->mp3_buffer, p->stream.this_frame, leftover);
|
||||
bytes_read = FS_fread(p->mp3_buffer + leftover, (size_t) 1,
|
||||
MP3_BUFFER_SIZE - leftover, &stream->fh);
|
||||
if(bytes_read <= 0)
|
||||
{
|
||||
Con_DPrintf("seek failure. unexpected EOF (frames=%" PRIu32 " leftover=%" PRIu32 ")\n",
|
||||
p->frame_count, leftover);
|
||||
break;
|
||||
}
|
||||
for(; !depadded && padding < bytes_read && !p->mp3_buffer[padding]; ++padding)
|
||||
;
|
||||
depadded = true;
|
||||
mad_stream_buffer(&p->stream, p->mp3_buffer + padding, leftover + bytes_read - padding);
|
||||
|
||||
while(1) /* Decode frame headers */
|
||||
{
|
||||
static uint16_t samples;
|
||||
p->stream.error = MAD_ERROR_NONE;
|
||||
|
||||
/* Not an audio frame */
|
||||
if(mad_header_decode(&p->frame.header, &p->stream) == -1)
|
||||
{
|
||||
if(p->stream.error == MAD_ERROR_BUFLEN)
|
||||
break; /* Normal behaviour; get some more data from the file */
|
||||
if(!MAD_RECOVERABLE(p->stream.error))
|
||||
{
|
||||
Con_DPrintf("unrecoverable MAD error\n");
|
||||
break;
|
||||
}
|
||||
if(p->stream.error == MAD_ERROR_LOSTSYNC)
|
||||
{
|
||||
size_t available = (p->stream.bufend - p->stream.this_frame);
|
||||
tagsize = mp3_tagsize(p->stream.this_frame, (size_t) available);
|
||||
if(tagsize)
|
||||
{
|
||||
/* It's some ID3 tags, so just skip */
|
||||
if(tagsize >= available)
|
||||
{
|
||||
FS_fseek(&stream->fh,
|
||||
(ptrdiff_t)tagsize - (ptrdiff_t)available,
|
||||
SEEK_CUR);
|
||||
depadded = false;
|
||||
}
|
||||
mad_stream_skip(&p->stream, q_min(tagsize, available));
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_DPrintf("MAD lost sync\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_DPrintf("recoverable MAD error\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
consumed += p->stream.next_frame - p->stream.this_frame;
|
||||
vbr |= (p->frame.header.bitrate != initial_bitrate);
|
||||
|
||||
samples = 32 * MAD_NSBSAMPLES(&p->frame.header);
|
||||
|
||||
p->frame_count++;
|
||||
mad_timer_add(&p->timer, p->frame.header.duration);
|
||||
|
||||
mad_frame_decode(&p->frame, &p->stream);
|
||||
mad_synth_frame(&p->synth, &p->frame);
|
||||
p->cursamp = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
snd_codec_t mp3_codec =
|
||||
{
|
||||
CODECTYPE_MP3,
|
||||
true, /* always available. */
|
||||
"mp3",
|
||||
S_MP3_CodecInitialize,
|
||||
S_MP3_CodecShutdown,
|
||||
S_MP3_CodecOpenStream,
|
||||
S_MP3_CodecReadStream,
|
||||
S_MP3_CodecRewindStream,
|
||||
S_MP3_CodecCloseStream,
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* USE_CODEC_MP3 */
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
/* MP3 decoding support using libmad or libmpg123. */
|
||||
|
||||
#ifndef spingle__snd_mp3_h
|
||||
#define spingle__snd_mp3_h
|
||||
|
||||
#if defined(USE_CODEC_MP3)
|
||||
|
||||
extern snd_codec_t mp3_codec;
|
||||
|
||||
#endif /* USE_CODEC_MP3 */
|
||||
|
||||
#endif
|
|
@ -1,226 +0,0 @@
|
|||
/*
|
||||
* MP3 decoding support using libmpg123, loosely based on an SDL_mixer
|
||||
* See: http://bubu.lv/changeset/4/public/libs/SDL/generated/SDL_mixer
|
||||
*
|
||||
* Copyright (C) 2011-2012 O.Sezer <sezero@users.sourceforge.net>
|
||||
*
|
||||
* 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 program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "q_defs.h"
|
||||
|
||||
#if defined(USE_CODEC_MP3)
|
||||
#include "snd_codec.h"
|
||||
#include "snd_codeci.h"
|
||||
#include "snd_mp3.h"
|
||||
#include <errno.h>
|
||||
#include <mpg123.h>
|
||||
|
||||
#if !defined(MPG123_API_VERSION) || (MPG123_API_VERSION < 24)
|
||||
#error minimum required libmpg123 version is 1.12.0 (api version 24)
|
||||
#endif /* MPG123_API_VERSION */
|
||||
|
||||
/* Private data */
|
||||
typedef struct _mp3_priv_t
|
||||
{
|
||||
int32_t handle_newed, handle_opened;
|
||||
mpg123_handle* handle;
|
||||
} mp3_priv_t;
|
||||
|
||||
/* CALLBACK FUNCTIONS: */
|
||||
/* CAREFUL: libmpg123 expects POSIX read() and lseek() behavior,
|
||||
* however our FS_fread() and FS_fseek() return fread() and fseek()
|
||||
* compatible values. */
|
||||
|
||||
static ssize_t mp3_read(void *f, void *buf, size_t size)
|
||||
{
|
||||
ssize_t ret = (ssize_t) FS_fread(buf, 1, size, (fshandle_t *)f);
|
||||
if(ret == 0 && errno != 0)
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static off_t mp3_seek(void *f, off_t offset, int32_t whence)
|
||||
{
|
||||
if(f == NULL) return (-1);
|
||||
if(FS_fseek((fshandle_t *)f, (long) offset, whence) < 0)
|
||||
return (off_t) -1;
|
||||
return (off_t) FS_ftell((fshandle_t *)f);
|
||||
}
|
||||
|
||||
static bool S_MP3_CodecInitialize(void)
|
||||
{
|
||||
if(!mp3_codec.initialized)
|
||||
{
|
||||
if(mpg123_init() != MPG123_OK)
|
||||
{
|
||||
Con_Printf("Could not initialize mpg123\n");
|
||||
return false;
|
||||
}
|
||||
mp3_codec.initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void S_MP3_CodecShutdown(void)
|
||||
{
|
||||
if(mp3_codec.initialized)
|
||||
{
|
||||
mp3_codec.initialized = false;
|
||||
mpg123_exit();
|
||||
}
|
||||
}
|
||||
|
||||
static bool S_MP3_CodecOpenStream(snd_stream_t *stream)
|
||||
{
|
||||
long rate = 0;
|
||||
int32_t encoding = 0, channels = 0;
|
||||
mp3_priv_t *priv = NULL;
|
||||
|
||||
stream->priv = Z_Malloc(sizeof(mp3_priv_t));
|
||||
priv = (mp3_priv_t *) stream->priv;
|
||||
priv->handle = mpg123_new(NULL, NULL);
|
||||
if(priv->handle == NULL)
|
||||
{
|
||||
Con_Printf("Unable to allocate mpg123 handle\n");
|
||||
goto fail;
|
||||
}
|
||||
priv->handle_newed = 1;
|
||||
|
||||
if(mpg123_replace_reader_handle(priv->handle, mp3_read, mp3_seek, NULL) != MPG123_OK ||
|
||||
mpg123_open_handle(priv->handle, &stream->fh) != MPG123_OK)
|
||||
{
|
||||
Con_Printf("Unable to open mpg123 handle\n");
|
||||
goto fail;
|
||||
}
|
||||
priv->handle_opened = 1;
|
||||
|
||||
if(mpg123_getformat(priv->handle, &rate, &channels, &encoding) != MPG123_OK)
|
||||
{
|
||||
Con_Printf("Unable to retrieve mpg123 format for %s\n", stream->name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch(channels)
|
||||
{
|
||||
case MPG123_MONO:
|
||||
stream->info.channels = 1;
|
||||
break;
|
||||
case MPG123_STEREO:
|
||||
stream->info.channels = 2;
|
||||
break;
|
||||
default:
|
||||
Con_Printf("Unsupported number of channels %" PRIi32 " in %s\n", channels, stream->name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
stream->info.rate = rate;
|
||||
|
||||
switch(encoding)
|
||||
{
|
||||
case MPG123_ENC_UNSIGNED_8:
|
||||
stream->info.bits = 8;
|
||||
stream->info.width = 1;
|
||||
break;
|
||||
case MPG123_ENC_SIGNED_8:
|
||||
/* unsupported: force mpg123 to convert */
|
||||
stream->info.bits = 8;
|
||||
stream->info.width = 1;
|
||||
encoding = MPG123_ENC_UNSIGNED_8;
|
||||
break;
|
||||
case MPG123_ENC_SIGNED_16:
|
||||
stream->info.bits = 16;
|
||||
stream->info.width = 2;
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_16:
|
||||
default:
|
||||
/* unsupported: force mpg123 to convert */
|
||||
stream->info.bits = 16;
|
||||
stream->info.width = 2;
|
||||
encoding = MPG123_ENC_SIGNED_16;
|
||||
break;
|
||||
}
|
||||
if(mpg123_format_support(priv->handle, rate, encoding) == 0)
|
||||
{
|
||||
Con_Printf("Unsupported format for %s\n", stream->name);
|
||||
goto fail;
|
||||
}
|
||||
mpg123_format_none(priv->handle);
|
||||
mpg123_format(priv->handle, rate, channels, encoding);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
if(priv)
|
||||
{
|
||||
if(priv->handle_opened)
|
||||
mpg123_close(priv->handle);
|
||||
if(priv->handle_newed)
|
||||
mpg123_delete(priv->handle);
|
||||
Z_Free(stream->priv);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int32_t S_MP3_CodecReadStream(snd_stream_t *stream, int32_t bytes, void *buffer)
|
||||
{
|
||||
mp3_priv_t *priv = (mp3_priv_t *) stream->priv;
|
||||
size_t bytes_read = 0;
|
||||
int32_t res = mpg123_read(priv->handle, (uint8_t *)buffer, (size_t)bytes, &bytes_read);
|
||||
switch(res)
|
||||
{
|
||||
case MPG123_DONE:
|
||||
Con_DPrintf("mp3 EOF\n");
|
||||
case MPG123_OK:
|
||||
return (int32_t)bytes_read;
|
||||
}
|
||||
return -1; /* error */
|
||||
}
|
||||
|
||||
static void S_MP3_CodecCloseStream(snd_stream_t *stream)
|
||||
{
|
||||
mp3_priv_t *priv = (mp3_priv_t *) stream->priv;
|
||||
mpg123_close(priv->handle);
|
||||
mpg123_delete(priv->handle);
|
||||
Z_Free(stream->priv);
|
||||
S_CodecUtilClose(&stream);
|
||||
}
|
||||
|
||||
static int32_t S_MP3_CodecRewindStream(snd_stream_t *stream)
|
||||
{
|
||||
mp3_priv_t *priv = (mp3_priv_t *) stream->priv;
|
||||
off_t res = mpg123_seek(priv->handle, 0, SEEK_SET);
|
||||
if(res >= 0) return (0);
|
||||
return res;
|
||||
}
|
||||
|
||||
snd_codec_t mp3_codec =
|
||||
{
|
||||
CODECTYPE_MP3,
|
||||
false,
|
||||
"mp3",
|
||||
S_MP3_CodecInitialize,
|
||||
S_MP3_CodecShutdown,
|
||||
S_MP3_CodecOpenStream,
|
||||
S_MP3_CodecReadStream,
|
||||
S_MP3_CodecRewindStream,
|
||||
S_MP3_CodecCloseStream,
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* USE_CODEC_MP3 */
|
||||
|
|
@ -26,7 +26,6 @@
|
|||
#if defined(USE_CODEC_OPUS)
|
||||
#include "snd_codec.h"
|
||||
#include "snd_codeci.h"
|
||||
#include "snd_opus.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <opusfile.h>
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/* Ogg/Opus streaming music support. */
|
||||
|
||||
#ifndef spingle__snd_opus
|
||||
#define spingle__snd_opus
|
||||
|
||||
#if defined(USE_CODEC_OPUS)
|
||||
|
||||
extern snd_codec_t opus_codec;
|
||||
|
||||
#endif /* USE_CODEC_OPUS */
|
||||
|
||||
#endif
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include "snd_codec.h"
|
||||
#include "snd_codeci.h"
|
||||
#include "snd_umx.h"
|
||||
|
||||
typedef int32_t fci_t; /* FCompactIndex */
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
/* Unreal UMX format support */
|
||||
#ifndef spingle__snd_umx_h
|
||||
#define spingle__snd_umx_h
|
||||
|
||||
extern snd_codec_t umx_codec;
|
||||
|
||||
#endif
|
|
@ -26,7 +26,6 @@
|
|||
#if defined(USE_CODEC_VORBIS)
|
||||
#include "snd_codec.h"
|
||||
#include "snd_codeci.h"
|
||||
#include "snd_vorbis.h"
|
||||
|
||||
#define OV_EXCLUDE_STATIC_CALLBACKS
|
||||
#include <vorbis/vorbisfile.h>
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/* Ogg/Vorbis streaming music support. */
|
||||
|
||||
#ifndef spingle__snd_vorbis_h
|
||||
#define spingle__snd_vorbis_h
|
||||
|
||||
#if defined(USE_CODEC_VORBIS)
|
||||
|
||||
extern snd_codec_t vorbis_codec;
|
||||
|
||||
#endif /* USE_CODEC_VORBIS */
|
||||
|
||||
#endif
|
|
@ -19,7 +19,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "strl_fn.h"
|
||||
#include "q_defs.h"
|
||||
|
||||
/*
|
||||
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||
|
@ -29,8 +29,7 @@
|
|||
* If retval >= siz, truncation occurred.
|
||||
*/
|
||||
|
||||
size_t
|
||||
q_strlcat(char *dst, const char *src, size_t siz)
|
||||
size_t q_strlcat(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
|
@ -56,6 +55,40 @@ q_strlcat(char *dst, const char *src, size_t siz)
|
|||
}
|
||||
*d = '\0';
|
||||
|
||||
return(dlen + (s - src)); /* count does not include NUL */
|
||||
return dlen + (s - src); /* count does not include NUL */
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy src to string dst of size siz. At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz == 0).
|
||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||
*/
|
||||
|
||||
size_t q_strlcpy(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if(n != 0)
|
||||
{
|
||||
while(--n != 0)
|
||||
{
|
||||
if((*d++ = *s++) == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if(n == 0)
|
||||
{
|
||||
if(siz != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while(*s++)
|
||||
;
|
||||
}
|
||||
|
||||
return s - src - 1; /* count does not include NUL */
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
/* header file for BSD strlcat and strlcpy */
|
||||
|
||||
#ifndef spingle__strl_fn_h
|
||||
#define spingle__strl_fn_h
|
||||
|
||||
/* use our own copies of strlcpy and strlcat taken from OpenBSD */
|
||||
extern size_t q_strlcpy(char *dst, const char *src, size_t size);
|
||||
extern size_t q_strlcat(char *dst, const char *src, size_t size);
|
||||
|
||||
#endif
|
|
@ -1,58 +0,0 @@
|
|||
/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "strl_fn.h"
|
||||
|
||||
/*
|
||||
* Copy src to string dst of size siz. At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz == 0).
|
||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||
*/
|
||||
|
||||
size_t
|
||||
q_strlcpy(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if(n != 0)
|
||||
{
|
||||
while(--n != 0)
|
||||
{
|
||||
if((*d++ = *s++) == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if(n == 0)
|
||||
{
|
||||
if(siz != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while(*s++)
|
||||
;
|
||||
}
|
||||
|
||||
return(s - src - 1); /* count does not include NUL */
|
||||
}
|
||||
|
Loading…
Reference in New Issue