Force consistent line endings.
I'd suggest enabling the EolExtension: this way we won't go back and forth here.
This commit is contained in:
+764
-764
File diff suppressed because it is too large
Load Diff
+63
-63
@@ -1,63 +1,63 @@
|
||||
#ifndef NOTES_LOADER_SMA_H
|
||||
#define NOTES_LOADER_SMA_H
|
||||
|
||||
#include "GameConstantsAndTypes.h"
|
||||
#include "BackgroundUtil.h"
|
||||
|
||||
class MsdFile;
|
||||
class Song;
|
||||
class Steps;
|
||||
class TimingData;
|
||||
|
||||
/** @brief Reads a Song from a .SMA file. */
|
||||
namespace SMALoader
|
||||
{
|
||||
void LoadFromSMATokens( RString sStepsType,
|
||||
RString sDescription,
|
||||
RString sDifficulty,
|
||||
RString sMeter,
|
||||
RString sRadarValues,
|
||||
RString sNoteData,
|
||||
Steps &out );
|
||||
|
||||
bool LoadFromDir( const RString &sPath, Song &out );
|
||||
void TidyUpData( Song &song, bool bFromCache );
|
||||
|
||||
bool LoadFromSMAFile( const RString &sPath, Song &out );
|
||||
void GetApplicableFiles( const RString &sPath, vector<RString> &out );
|
||||
bool LoadTimingFromFile( const RString &fn, TimingData &out );
|
||||
void LoadTimingFromSMAFile( const MsdFile &msd, TimingData &out );
|
||||
bool LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
|
||||
bool LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot );
|
||||
bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
|
||||
bool LoadFromBGChangesString( BackgroundChange &change, const RString &sBGChangeExpression );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @author Aldo Fregoso, Jason Felds (c) 2009-2011
|
||||
* @section LICENSE
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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.
|
||||
*/
|
||||
#ifndef NOTES_LOADER_SMA_H
|
||||
#define NOTES_LOADER_SMA_H
|
||||
|
||||
#include "GameConstantsAndTypes.h"
|
||||
#include "BackgroundUtil.h"
|
||||
|
||||
class MsdFile;
|
||||
class Song;
|
||||
class Steps;
|
||||
class TimingData;
|
||||
|
||||
/** @brief Reads a Song from a .SMA file. */
|
||||
namespace SMALoader
|
||||
{
|
||||
void LoadFromSMATokens( RString sStepsType,
|
||||
RString sDescription,
|
||||
RString sDifficulty,
|
||||
RString sMeter,
|
||||
RString sRadarValues,
|
||||
RString sNoteData,
|
||||
Steps &out );
|
||||
|
||||
bool LoadFromDir( const RString &sPath, Song &out );
|
||||
void TidyUpData( Song &song, bool bFromCache );
|
||||
|
||||
bool LoadFromSMAFile( const RString &sPath, Song &out );
|
||||
void GetApplicableFiles( const RString &sPath, vector<RString> &out );
|
||||
bool LoadTimingFromFile( const RString &fn, TimingData &out );
|
||||
void LoadTimingFromSMAFile( const MsdFile &msd, TimingData &out );
|
||||
bool LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
|
||||
bool LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot );
|
||||
bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
|
||||
bool LoadFromBGChangesString( BackgroundChange &change, const RString &sBGChangeExpression );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @author Aldo Fregoso, Jason Felds (c) 2009-2011
|
||||
* @section LICENSE
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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.
|
||||
*/
|
||||
|
||||
+1260
-1260
File diff suppressed because it is too large
Load Diff
+103
-103
@@ -1,103 +1,103 @@
|
||||
/** @brief SSCLoader - Reads a Song and its Steps from a .SSC file. */
|
||||
#ifndef NotesLoaderSSC_H
|
||||
#define NotesLoaderSSC_H
|
||||
|
||||
#include "GameConstantsAndTypes.h"
|
||||
|
||||
class MsdFile;
|
||||
class Song;
|
||||
class Steps;
|
||||
class TimingData;
|
||||
|
||||
/**
|
||||
* @brief The various states while parsing a .ssc file.
|
||||
*/
|
||||
enum SSCLoadingStates
|
||||
{
|
||||
GETTING_SONG_INFO, /**< Retrieving song information. */
|
||||
GETTING_STEP_INFO, /**< Retrieving step information. */
|
||||
GETTING_STEP_TIMING_INFO, /**< Retrieving a step's individual timing information. */
|
||||
GETTING_NOTE_INFO, /**< Retrieving the specific notes. This state may be deprecated. */
|
||||
NUM_SSCLoadingStates /**< The number of states used. */
|
||||
};
|
||||
|
||||
const float VERSION_RADAR_FAKE = 0.53f;
|
||||
|
||||
/**
|
||||
* @brief The SSCLoader handles all of the parsing needed for .ssc files.
|
||||
*/
|
||||
namespace SSCLoader
|
||||
{
|
||||
/**
|
||||
* @brief Attempt to load a song from a specified path.
|
||||
* @param sPath a const reference to the path on the hard drive to check.
|
||||
* @param out a reference to the Song that will retrieve the song information.
|
||||
* @return its success or failure.
|
||||
*/
|
||||
bool LoadFromDir( const RString &sPath, Song &out );
|
||||
/**
|
||||
* @brief Attempt to load the specified ssc file.
|
||||
* @param sPath a const reference to the path on the hard drive to check.
|
||||
* @param out a reference to the Song that will retrieve the song information.
|
||||
* @param bFromCache a check to see if we are getting certain information from the cache file.
|
||||
* @return its success or failure.
|
||||
*/
|
||||
bool LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCache = false );
|
||||
/**
|
||||
* @brief Retrieve the list of .ssc files.
|
||||
* @param sPath a const reference to the path on the hard drive to check.
|
||||
* @param out a vector of files found in the path.
|
||||
*/
|
||||
void GetApplicableFiles( const RString &sPath, vector<RString> &out );
|
||||
/**
|
||||
* @brief Attempt to load an edit from the hard drive.
|
||||
* @param sEditFilePath a path on the hard drive to check.
|
||||
* @param slot the Profile of the user with the edit.
|
||||
* @param bAddStepsToSong a flag to determine if we add the edit steps to the song file.
|
||||
* @return its success or failure.
|
||||
*/
|
||||
bool LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
|
||||
/**
|
||||
* @brief Attempt to parse the edit file in question.
|
||||
* @param msd the edit file itself.
|
||||
* @param sEditFilePath a const reference to a path on the hard drive to check.
|
||||
* @param slot the Profile of the user with the edit.
|
||||
* @param bAddStepsToSong a flag to determine if we add the edit steps to the song file.
|
||||
* @return its success or failure.
|
||||
*/
|
||||
bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
|
||||
/**
|
||||
* @brief Perform some cleanup on the loaded song.
|
||||
* @param song a reference to the song that may need cleaning up.
|
||||
* @param bFromCache a flag to determine if this song is loaded from a cache file.
|
||||
*/
|
||||
void TidyUpData( Song &song, bool bFromCache );
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @file
|
||||
* @author Jason Felds (c) 2011
|
||||
*
|
||||
* @section LICENSE
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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.
|
||||
*/
|
||||
/** @brief SSCLoader - Reads a Song and its Steps from a .SSC file. */
|
||||
#ifndef NotesLoaderSSC_H
|
||||
#define NotesLoaderSSC_H
|
||||
|
||||
#include "GameConstantsAndTypes.h"
|
||||
|
||||
class MsdFile;
|
||||
class Song;
|
||||
class Steps;
|
||||
class TimingData;
|
||||
|
||||
/**
|
||||
* @brief The various states while parsing a .ssc file.
|
||||
*/
|
||||
enum SSCLoadingStates
|
||||
{
|
||||
GETTING_SONG_INFO, /**< Retrieving song information. */
|
||||
GETTING_STEP_INFO, /**< Retrieving step information. */
|
||||
GETTING_STEP_TIMING_INFO, /**< Retrieving a step's individual timing information. */
|
||||
GETTING_NOTE_INFO, /**< Retrieving the specific notes. This state may be deprecated. */
|
||||
NUM_SSCLoadingStates /**< The number of states used. */
|
||||
};
|
||||
|
||||
const float VERSION_RADAR_FAKE = 0.53f;
|
||||
|
||||
/**
|
||||
* @brief The SSCLoader handles all of the parsing needed for .ssc files.
|
||||
*/
|
||||
namespace SSCLoader
|
||||
{
|
||||
/**
|
||||
* @brief Attempt to load a song from a specified path.
|
||||
* @param sPath a const reference to the path on the hard drive to check.
|
||||
* @param out a reference to the Song that will retrieve the song information.
|
||||
* @return its success or failure.
|
||||
*/
|
||||
bool LoadFromDir( const RString &sPath, Song &out );
|
||||
/**
|
||||
* @brief Attempt to load the specified ssc file.
|
||||
* @param sPath a const reference to the path on the hard drive to check.
|
||||
* @param out a reference to the Song that will retrieve the song information.
|
||||
* @param bFromCache a check to see if we are getting certain information from the cache file.
|
||||
* @return its success or failure.
|
||||
*/
|
||||
bool LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCache = false );
|
||||
/**
|
||||
* @brief Retrieve the list of .ssc files.
|
||||
* @param sPath a const reference to the path on the hard drive to check.
|
||||
* @param out a vector of files found in the path.
|
||||
*/
|
||||
void GetApplicableFiles( const RString &sPath, vector<RString> &out );
|
||||
/**
|
||||
* @brief Attempt to load an edit from the hard drive.
|
||||
* @param sEditFilePath a path on the hard drive to check.
|
||||
* @param slot the Profile of the user with the edit.
|
||||
* @param bAddStepsToSong a flag to determine if we add the edit steps to the song file.
|
||||
* @return its success or failure.
|
||||
*/
|
||||
bool LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
|
||||
/**
|
||||
* @brief Attempt to parse the edit file in question.
|
||||
* @param msd the edit file itself.
|
||||
* @param sEditFilePath a const reference to a path on the hard drive to check.
|
||||
* @param slot the Profile of the user with the edit.
|
||||
* @param bAddStepsToSong a flag to determine if we add the edit steps to the song file.
|
||||
* @return its success or failure.
|
||||
*/
|
||||
bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
|
||||
/**
|
||||
* @brief Perform some cleanup on the loaded song.
|
||||
* @param song a reference to the song that may need cleaning up.
|
||||
* @param bFromCache a flag to determine if this song is loaded from a cache file.
|
||||
*/
|
||||
void TidyUpData( Song &song, bool bFromCache );
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @file
|
||||
* @author Jason Felds (c) 2011
|
||||
*
|
||||
* @section LICENSE
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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.
|
||||
*/
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
#ifndef RAGE_FILE_MANAGER_READAHEAD_H
|
||||
#define RAGE_FILE_MANAGER_READAHEAD_H
|
||||
|
||||
#include "RageFileBasic.h"
|
||||
/** @brief Utilities for reading the RageFiles. */
|
||||
namespace RageFileManagerReadAhead
|
||||
{
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
// Nonblockingly read ahead iBytes in pFile, starting at the current file position.
|
||||
void ReadAhead( RageFileBasic *pFile, int iBytes );
|
||||
|
||||
/* Discard iBytes of kernel cache, starting at the current file position plus
|
||||
* iRelativePosition (which may be negative). */
|
||||
void DiscardCache( RageFileBasic *pFile, int iRelativePosition, int iBytes );
|
||||
|
||||
void CacheHintStreaming( RageFileBasic *pFile );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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.
|
||||
*/
|
||||
#ifndef RAGE_FILE_MANAGER_READAHEAD_H
|
||||
#define RAGE_FILE_MANAGER_READAHEAD_H
|
||||
|
||||
#include "RageFileBasic.h"
|
||||
/** @brief Utilities for reading the RageFiles. */
|
||||
namespace RageFileManagerReadAhead
|
||||
{
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
// Nonblockingly read ahead iBytes in pFile, starting at the current file position.
|
||||
void ReadAhead( RageFileBasic *pFile, int iBytes );
|
||||
|
||||
/* Discard iBytes of kernel cache, starting at the current file position plus
|
||||
* iRelativePosition (which may be negative). */
|
||||
void DiscardCache( RageFileBasic *pFile, int iRelativePosition, int iBytes );
|
||||
|
||||
void CacheHintStreaming( RageFileBasic *pFile );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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.
|
||||
*/
|
||||
|
||||
+318
-318
@@ -1,318 +1,318 @@
|
||||
#include "global.h"
|
||||
#include "RageSurface_Load_PNG.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageSurface.h"
|
||||
|
||||
|
||||
#if defined(_WINDOWS) || defined(_XBOX)
|
||||
# include "libpng/include/png.h"
|
||||
# if defined(_MSC_VER)
|
||||
# if defined(_XBOX)
|
||||
# pragma comment(lib, "libpng/lib/xboxlibpng.lib")
|
||||
# else
|
||||
# pragma comment(lib, "libpng/lib/libpng.lib")
|
||||
# endif
|
||||
# pragma warning(disable: 4611) /* interaction between '_setjmp' and C++ object destruction is non-portable */
|
||||
# endif // _MSC_VER
|
||||
#else
|
||||
# include <png.h>
|
||||
#endif
|
||||
|
||||
#if defined(_XBOX)
|
||||
# include <malloc.h> // for alloca
|
||||
# include "archutils/Xbox/VirtualMemory.h"
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
void RageFile_png_read( png_struct *png, png_byte *p, png_size_t size )
|
||||
{
|
||||
CHECKPOINT;
|
||||
RageFile *f = (RageFile *) png_get_io_ptr(png);
|
||||
|
||||
int got = f->Read( p, size );
|
||||
if( got == -1 )
|
||||
{
|
||||
/* png_error will call PNG_Error, which will longjmp. If we just pass
|
||||
* GetError().c_str() to it, a temporary may be created; since control
|
||||
* never returns here, it may never be destructed and we could leak. */
|
||||
static char error[256];
|
||||
strncpy( error, f->GetError(), sizeof(error) );
|
||||
error[sizeof(error)-1] = 0;
|
||||
png_error( png, error );
|
||||
}
|
||||
else if( got != (int) size )
|
||||
png_error( png, "Unexpected EOF" );
|
||||
}
|
||||
|
||||
struct error_info
|
||||
{
|
||||
char *err;
|
||||
const char *fn;
|
||||
};
|
||||
|
||||
void PNG_Error( png_struct *png, const char *error )
|
||||
{
|
||||
CHECKPOINT;
|
||||
error_info *info = (error_info *) png_get_error_ptr(png);
|
||||
strncpy( info->err, error, 1024 );
|
||||
info->err[1023] = 0;
|
||||
LOG->Trace( "loading \"%s\": err: %s", info->fn, info->err );
|
||||
longjmp( png_jmpbuf(png), 1 );
|
||||
}
|
||||
|
||||
void PNG_Warning( png_struct *png, const char *warning )
|
||||
{
|
||||
CHECKPOINT;
|
||||
error_info *info = (error_info *) png_get_io_ptr(png);
|
||||
LOG->Trace( "loading \"%s\": warning: %s", info->fn, warning );
|
||||
}
|
||||
|
||||
/* Since libpng forces us to use longjmp (gross!), this function shouldn't create any C++
|
||||
* objects, and needs to watch out for memleaks. */
|
||||
static RageSurface *RageSurface_Load_PNG( RageFile *f, const char *fn, char errorbuf[1024], bool bHeaderOnly )
|
||||
{
|
||||
error_info error;
|
||||
error.err = errorbuf;
|
||||
error.fn = fn;
|
||||
|
||||
png_struct *png = png_create_read_struct( PNG_LIBPNG_VER_STRING, &error, PNG_Error, PNG_Warning );
|
||||
|
||||
#if defined(XBOX)
|
||||
while(png == NULL)
|
||||
{
|
||||
if(!vmem_Manager.DecommitLRU())
|
||||
break;
|
||||
|
||||
png = png_create_read_struct( PNG_LIBPNG_VER_STRING, &error, PNG_Error, PNG_Warning );
|
||||
}
|
||||
#endif
|
||||
|
||||
if( png == NULL )
|
||||
{
|
||||
sprintf( errorbuf, "creating png_create_read_struct failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
png_info *info_ptr = png_create_info_struct(png);
|
||||
if( info_ptr == NULL )
|
||||
{
|
||||
png_destroy_read_struct( &png, NULL, NULL );
|
||||
sprintf( errorbuf, "creating png_create_info_struct failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RageSurface *volatile img = NULL;
|
||||
CHECKPOINT;
|
||||
if( setjmp(png_jmpbuf(png) ))
|
||||
{
|
||||
png_destroy_read_struct( &png, &info_ptr, NULL );
|
||||
delete img;
|
||||
return NULL;
|
||||
}
|
||||
CHECKPOINT;
|
||||
|
||||
png_set_read_fn( png, f, RageFile_png_read );
|
||||
|
||||
png_read_info( png, info_ptr );
|
||||
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type;
|
||||
png_get_IHDR( png, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL );
|
||||
|
||||
/* If bHeaderOnly is true, don't allocate the pixel storage space or decompress
|
||||
* the image. Just return an empty surface with only the width and height set. */
|
||||
if( bHeaderOnly )
|
||||
{
|
||||
CHECKPOINT;
|
||||
img = CreateSurfaceFrom( width, height, 32, 0, 0, 0, 0, NULL, width*4 );
|
||||
png_destroy_read_struct( &png, &info_ptr, NULL );
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
CHECKPOINT;
|
||||
png_set_strip_16(png); /* 16bit->8bit */
|
||||
png_set_packing( png ); /* 1,2,4 bit->8 bit */
|
||||
|
||||
/* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
|
||||
if( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 )
|
||||
png_set_expand_gray_1_2_4_to_8( png );
|
||||
|
||||
/* These are set for type == PALETTE. */
|
||||
RageSurfaceColor colors[256];
|
||||
int iColorKey = -1;
|
||||
|
||||
/* We import three types of files: paletted, RGBX and RGBA. The only difference
|
||||
* between RGBX and RGBA is that RGBX won't set the alpha mask, so it's easier
|
||||
* to tell later on that there's no alpha (without actually having to do a pixel scan). */
|
||||
enum { PALETTE, RGBX, RGBA } type;
|
||||
switch( color_type )
|
||||
{
|
||||
case PNG_COLOR_TYPE_GRAY:
|
||||
/* Fake PNG_COLOR_TYPE_GRAY. */
|
||||
for( int i = 0; i < 256; ++i )
|
||||
{
|
||||
colors[i].r = colors[i].g = colors[i].b = (int8_t) i;
|
||||
colors[i].a = 0xFF;
|
||||
}
|
||||
|
||||
type = PALETTE;
|
||||
break;
|
||||
|
||||
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
||||
type = RGBA;
|
||||
png_set_gray_to_rgb( png );
|
||||
break;
|
||||
case PNG_COLOR_TYPE_PALETTE:
|
||||
type = PALETTE;
|
||||
break;
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
type = RGBX;
|
||||
break;
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
type = RGBA;
|
||||
break;
|
||||
default:
|
||||
FAIL_M(ssprintf( "%i", color_type) );
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
if( color_type == PNG_COLOR_TYPE_GRAY )
|
||||
{
|
||||
png_color_16 *trans;
|
||||
if( png_get_tRNS( png, info_ptr, NULL, NULL, &trans ) == PNG_INFO_tRNS )
|
||||
iColorKey = trans->gray;
|
||||
}
|
||||
else if( color_type == PNG_COLOR_TYPE_PALETTE )
|
||||
{
|
||||
int num_palette;
|
||||
png_color *palette;
|
||||
int ret = png_get_PLTE( png, info_ptr, &palette, &num_palette );
|
||||
ASSERT( ret == PNG_INFO_PLTE );
|
||||
|
||||
png_byte *trans = NULL;
|
||||
int num_trans = 0;
|
||||
png_get_tRNS( png, info_ptr, &trans, &num_trans, NULL );
|
||||
|
||||
for( int i = 0; i < num_palette; ++i )
|
||||
{
|
||||
colors[i].r = palette[i].red;
|
||||
colors[i].g = palette[i].green;
|
||||
colors[i].b = palette[i].blue;
|
||||
colors[i].a = 0xFF;
|
||||
if( i < num_trans )
|
||||
colors[i].a = trans[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we have RGB image and tRNS, it's a color key. Just convert it to RGBA. */
|
||||
if( png_get_valid(png, info_ptr, PNG_INFO_tRNS) )
|
||||
{
|
||||
/* We don't care about RGB color keys; just convert them to alpha. */
|
||||
png_set_tRNS_to_alpha( png );
|
||||
type = RGBA;
|
||||
}
|
||||
|
||||
/* RGB->RGBX */
|
||||
png_set_filler( png, 0xff, PNG_FILLER_AFTER );
|
||||
}
|
||||
|
||||
png_set_interlace_handling( png );
|
||||
|
||||
CHECKPOINT;
|
||||
png_read_update_info( png, info_ptr );
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case PALETTE:
|
||||
img = CreateSurface( width, height, 8, 0, 0, 0, 0 );
|
||||
memcpy( img->fmt.palette->colors, colors, 256*sizeof(RageSurfaceColor) );
|
||||
|
||||
if( iColorKey != -1 )
|
||||
img->format->palette->colors[ iColorKey ].a = 0;
|
||||
|
||||
break;
|
||||
case RGBX:
|
||||
case RGBA:
|
||||
img = CreateSurface( width, height, 32,
|
||||
Swap32BE( 0xFF000000 ),
|
||||
Swap32BE( 0x00FF0000 ),
|
||||
Swap32BE( 0x0000FF00 ),
|
||||
Swap32BE( type == RGBA? 0x000000FF:0x00000000 ) );
|
||||
break;
|
||||
default:
|
||||
FAIL_M(ssprintf( "%i", type) );
|
||||
}
|
||||
ASSERT( img );
|
||||
|
||||
/* alloca to prevent memleaks if libpng longjmps us */
|
||||
png_byte **row_pointers = (png_byte **) alloca( sizeof(png_byte*) * height );
|
||||
CHECKPOINT_M( ssprintf("%p",row_pointers) );
|
||||
|
||||
for( unsigned y = 0; y < height; ++y )
|
||||
{
|
||||
png_byte *p = (png_byte *) img->pixels;
|
||||
row_pointers[y] = p + img->pitch*y;
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
png_read_image( png, row_pointers );
|
||||
|
||||
CHECKPOINT;
|
||||
png_read_end( png, info_ptr );
|
||||
png_destroy_read_struct( &png, &info_ptr, NULL );
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
RageSurfaceUtils::OpenResult RageSurface_Load_PNG( const RString &sPath, RageSurface *&ret, bool bHeaderOnly, RString &error )
|
||||
{
|
||||
RageFile f;
|
||||
if( !f.Open( sPath ) )
|
||||
{
|
||||
error = f.GetError();
|
||||
return RageSurfaceUtils::OPEN_FATAL_ERROR;
|
||||
}
|
||||
|
||||
char errorbuf[1024];
|
||||
ret = RageSurface_Load_PNG( &f, sPath, errorbuf, bHeaderOnly );
|
||||
if( ret == NULL )
|
||||
{
|
||||
error = errorbuf;
|
||||
return RageSurfaceUtils::OPEN_UNKNOWN_FILE_FORMAT; // XXX
|
||||
}
|
||||
|
||||
return RageSurfaceUtils::OPEN_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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 "global.h"
|
||||
#include "RageSurface_Load_PNG.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageSurface.h"
|
||||
|
||||
|
||||
#if defined(_WINDOWS) || defined(_XBOX)
|
||||
# include "libpng/include/png.h"
|
||||
# if defined(_MSC_VER)
|
||||
# if defined(_XBOX)
|
||||
# pragma comment(lib, "libpng/lib/xboxlibpng.lib")
|
||||
# else
|
||||
# pragma comment(lib, "libpng/lib/libpng.lib")
|
||||
# endif
|
||||
# pragma warning(disable: 4611) /* interaction between '_setjmp' and C++ object destruction is non-portable */
|
||||
# endif // _MSC_VER
|
||||
#else
|
||||
# include <png.h>
|
||||
#endif
|
||||
|
||||
#if defined(_XBOX)
|
||||
# include <malloc.h> // for alloca
|
||||
# include "archutils/Xbox/VirtualMemory.h"
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
void RageFile_png_read( png_struct *png, png_byte *p, png_size_t size )
|
||||
{
|
||||
CHECKPOINT;
|
||||
RageFile *f = (RageFile *) png_get_io_ptr(png);
|
||||
|
||||
int got = f->Read( p, size );
|
||||
if( got == -1 )
|
||||
{
|
||||
/* png_error will call PNG_Error, which will longjmp. If we just pass
|
||||
* GetError().c_str() to it, a temporary may be created; since control
|
||||
* never returns here, it may never be destructed and we could leak. */
|
||||
static char error[256];
|
||||
strncpy( error, f->GetError(), sizeof(error) );
|
||||
error[sizeof(error)-1] = 0;
|
||||
png_error( png, error );
|
||||
}
|
||||
else if( got != (int) size )
|
||||
png_error( png, "Unexpected EOF" );
|
||||
}
|
||||
|
||||
struct error_info
|
||||
{
|
||||
char *err;
|
||||
const char *fn;
|
||||
};
|
||||
|
||||
void PNG_Error( png_struct *png, const char *error )
|
||||
{
|
||||
CHECKPOINT;
|
||||
error_info *info = (error_info *) png_get_error_ptr(png);
|
||||
strncpy( info->err, error, 1024 );
|
||||
info->err[1023] = 0;
|
||||
LOG->Trace( "loading \"%s\": err: %s", info->fn, info->err );
|
||||
longjmp( png_jmpbuf(png), 1 );
|
||||
}
|
||||
|
||||
void PNG_Warning( png_struct *png, const char *warning )
|
||||
{
|
||||
CHECKPOINT;
|
||||
error_info *info = (error_info *) png_get_io_ptr(png);
|
||||
LOG->Trace( "loading \"%s\": warning: %s", info->fn, warning );
|
||||
}
|
||||
|
||||
/* Since libpng forces us to use longjmp (gross!), this function shouldn't create any C++
|
||||
* objects, and needs to watch out for memleaks. */
|
||||
static RageSurface *RageSurface_Load_PNG( RageFile *f, const char *fn, char errorbuf[1024], bool bHeaderOnly )
|
||||
{
|
||||
error_info error;
|
||||
error.err = errorbuf;
|
||||
error.fn = fn;
|
||||
|
||||
png_struct *png = png_create_read_struct( PNG_LIBPNG_VER_STRING, &error, PNG_Error, PNG_Warning );
|
||||
|
||||
#if defined(XBOX)
|
||||
while(png == NULL)
|
||||
{
|
||||
if(!vmem_Manager.DecommitLRU())
|
||||
break;
|
||||
|
||||
png = png_create_read_struct( PNG_LIBPNG_VER_STRING, &error, PNG_Error, PNG_Warning );
|
||||
}
|
||||
#endif
|
||||
|
||||
if( png == NULL )
|
||||
{
|
||||
sprintf( errorbuf, "creating png_create_read_struct failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
png_info *info_ptr = png_create_info_struct(png);
|
||||
if( info_ptr == NULL )
|
||||
{
|
||||
png_destroy_read_struct( &png, NULL, NULL );
|
||||
sprintf( errorbuf, "creating png_create_info_struct failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RageSurface *volatile img = NULL;
|
||||
CHECKPOINT;
|
||||
if( setjmp(png_jmpbuf(png) ))
|
||||
{
|
||||
png_destroy_read_struct( &png, &info_ptr, NULL );
|
||||
delete img;
|
||||
return NULL;
|
||||
}
|
||||
CHECKPOINT;
|
||||
|
||||
png_set_read_fn( png, f, RageFile_png_read );
|
||||
|
||||
png_read_info( png, info_ptr );
|
||||
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type;
|
||||
png_get_IHDR( png, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL );
|
||||
|
||||
/* If bHeaderOnly is true, don't allocate the pixel storage space or decompress
|
||||
* the image. Just return an empty surface with only the width and height set. */
|
||||
if( bHeaderOnly )
|
||||
{
|
||||
CHECKPOINT;
|
||||
img = CreateSurfaceFrom( width, height, 32, 0, 0, 0, 0, NULL, width*4 );
|
||||
png_destroy_read_struct( &png, &info_ptr, NULL );
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
CHECKPOINT;
|
||||
png_set_strip_16(png); /* 16bit->8bit */
|
||||
png_set_packing( png ); /* 1,2,4 bit->8 bit */
|
||||
|
||||
/* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
|
||||
if( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 )
|
||||
png_set_expand_gray_1_2_4_to_8( png );
|
||||
|
||||
/* These are set for type == PALETTE. */
|
||||
RageSurfaceColor colors[256];
|
||||
int iColorKey = -1;
|
||||
|
||||
/* We import three types of files: paletted, RGBX and RGBA. The only difference
|
||||
* between RGBX and RGBA is that RGBX won't set the alpha mask, so it's easier
|
||||
* to tell later on that there's no alpha (without actually having to do a pixel scan). */
|
||||
enum { PALETTE, RGBX, RGBA } type;
|
||||
switch( color_type )
|
||||
{
|
||||
case PNG_COLOR_TYPE_GRAY:
|
||||
/* Fake PNG_COLOR_TYPE_GRAY. */
|
||||
for( int i = 0; i < 256; ++i )
|
||||
{
|
||||
colors[i].r = colors[i].g = colors[i].b = (int8_t) i;
|
||||
colors[i].a = 0xFF;
|
||||
}
|
||||
|
||||
type = PALETTE;
|
||||
break;
|
||||
|
||||
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
||||
type = RGBA;
|
||||
png_set_gray_to_rgb( png );
|
||||
break;
|
||||
case PNG_COLOR_TYPE_PALETTE:
|
||||
type = PALETTE;
|
||||
break;
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
type = RGBX;
|
||||
break;
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
type = RGBA;
|
||||
break;
|
||||
default:
|
||||
FAIL_M(ssprintf( "%i", color_type) );
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
if( color_type == PNG_COLOR_TYPE_GRAY )
|
||||
{
|
||||
png_color_16 *trans;
|
||||
if( png_get_tRNS( png, info_ptr, NULL, NULL, &trans ) == PNG_INFO_tRNS )
|
||||
iColorKey = trans->gray;
|
||||
}
|
||||
else if( color_type == PNG_COLOR_TYPE_PALETTE )
|
||||
{
|
||||
int num_palette;
|
||||
png_color *palette;
|
||||
int ret = png_get_PLTE( png, info_ptr, &palette, &num_palette );
|
||||
ASSERT( ret == PNG_INFO_PLTE );
|
||||
|
||||
png_byte *trans = NULL;
|
||||
int num_trans = 0;
|
||||
png_get_tRNS( png, info_ptr, &trans, &num_trans, NULL );
|
||||
|
||||
for( int i = 0; i < num_palette; ++i )
|
||||
{
|
||||
colors[i].r = palette[i].red;
|
||||
colors[i].g = palette[i].green;
|
||||
colors[i].b = palette[i].blue;
|
||||
colors[i].a = 0xFF;
|
||||
if( i < num_trans )
|
||||
colors[i].a = trans[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we have RGB image and tRNS, it's a color key. Just convert it to RGBA. */
|
||||
if( png_get_valid(png, info_ptr, PNG_INFO_tRNS) )
|
||||
{
|
||||
/* We don't care about RGB color keys; just convert them to alpha. */
|
||||
png_set_tRNS_to_alpha( png );
|
||||
type = RGBA;
|
||||
}
|
||||
|
||||
/* RGB->RGBX */
|
||||
png_set_filler( png, 0xff, PNG_FILLER_AFTER );
|
||||
}
|
||||
|
||||
png_set_interlace_handling( png );
|
||||
|
||||
CHECKPOINT;
|
||||
png_read_update_info( png, info_ptr );
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case PALETTE:
|
||||
img = CreateSurface( width, height, 8, 0, 0, 0, 0 );
|
||||
memcpy( img->fmt.palette->colors, colors, 256*sizeof(RageSurfaceColor) );
|
||||
|
||||
if( iColorKey != -1 )
|
||||
img->format->palette->colors[ iColorKey ].a = 0;
|
||||
|
||||
break;
|
||||
case RGBX:
|
||||
case RGBA:
|
||||
img = CreateSurface( width, height, 32,
|
||||
Swap32BE( 0xFF000000 ),
|
||||
Swap32BE( 0x00FF0000 ),
|
||||
Swap32BE( 0x0000FF00 ),
|
||||
Swap32BE( type == RGBA? 0x000000FF:0x00000000 ) );
|
||||
break;
|
||||
default:
|
||||
FAIL_M(ssprintf( "%i", type) );
|
||||
}
|
||||
ASSERT( img );
|
||||
|
||||
/* alloca to prevent memleaks if libpng longjmps us */
|
||||
png_byte **row_pointers = (png_byte **) alloca( sizeof(png_byte*) * height );
|
||||
CHECKPOINT_M( ssprintf("%p",row_pointers) );
|
||||
|
||||
for( unsigned y = 0; y < height; ++y )
|
||||
{
|
||||
png_byte *p = (png_byte *) img->pixels;
|
||||
row_pointers[y] = p + img->pitch*y;
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
png_read_image( png, row_pointers );
|
||||
|
||||
CHECKPOINT;
|
||||
png_read_end( png, info_ptr );
|
||||
png_destroy_read_struct( &png, &info_ptr, NULL );
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
RageSurfaceUtils::OpenResult RageSurface_Load_PNG( const RString &sPath, RageSurface *&ret, bool bHeaderOnly, RString &error )
|
||||
{
|
||||
RageFile f;
|
||||
if( !f.Open( sPath ) )
|
||||
{
|
||||
error = f.GetError();
|
||||
return RageSurfaceUtils::OPEN_FATAL_ERROR;
|
||||
}
|
||||
|
||||
char errorbuf[1024];
|
||||
ret = RageSurface_Load_PNG( &f, sPath, errorbuf, bHeaderOnly );
|
||||
if( ret == NULL )
|
||||
{
|
||||
error = errorbuf;
|
||||
return RageSurfaceUtils::OPEN_UNKNOWN_FILE_FORMAT; // XXX
|
||||
}
|
||||
|
||||
return RageSurfaceUtils::OPEN_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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.
|
||||
*/
|
||||
|
||||
+168
-168
@@ -1,168 +1,168 @@
|
||||
#include "global.h"
|
||||
#include "RageSurface_Save_PNG.h"
|
||||
#include "RageSurface.h"
|
||||
#include "RageSurfaceUtils.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
|
||||
#if defined(WINDOWS) || defined(_XBOX)
|
||||
#include "libpng/include/png.h"
|
||||
#if defined(_MSC_VER)
|
||||
# if defined(_XBOX)
|
||||
# pragma comment(lib, "libpng/lib/xboxlibpng.lib")
|
||||
# else
|
||||
# pragma comment(lib, "libpng/lib/libpng.lib")
|
||||
# endif
|
||||
#pragma warning(disable: 4611) /* interaction between '_setjmp' and C++ object destruction is non-portable */
|
||||
#endif
|
||||
#else
|
||||
#include <png.h>
|
||||
#endif
|
||||
|
||||
static void SafePngError( png_struct *pPng, const RString &sStr )
|
||||
{
|
||||
/* png_error will call PNG_Error, which will longjmp. If we just pass
|
||||
* GetError().c_str() to it, a temporary may be created; since control
|
||||
* never returns, it may never be destructed and leak. */
|
||||
static char error[256];
|
||||
strncpy( error, sStr, sizeof(error) );
|
||||
error[sizeof(error)-1] = 0;
|
||||
png_error( pPng, error );
|
||||
}
|
||||
|
||||
static void RageFile_png_write( png_struct *pPng, png_byte *pData, png_size_t iSize )
|
||||
{
|
||||
RageFile *pFile = (RageFile *) png_get_io_ptr(pPng);
|
||||
|
||||
int iGot = pFile->Write( pData, iSize );
|
||||
if( iGot == -1 )
|
||||
SafePngError( pPng, pFile->GetError() );
|
||||
}
|
||||
|
||||
static void RageFile_png_flush( png_struct *pPng )
|
||||
{
|
||||
RageFile *pFile = (RageFile *) png_get_io_ptr(pPng);
|
||||
|
||||
int iGot = pFile->Flush();
|
||||
if( iGot == -1 )
|
||||
SafePngError( pPng, pFile->GetError() );
|
||||
}
|
||||
|
||||
struct error_info
|
||||
{
|
||||
char *szErr;
|
||||
};
|
||||
|
||||
static void PNG_Error( png_struct *pPng, const char *szError )
|
||||
{
|
||||
error_info *pInfo = (error_info *) png_get_error_ptr(pPng);
|
||||
strncpy( pInfo->szErr, szError, 1024 );
|
||||
pInfo->szErr[1023] = 0;
|
||||
longjmp( png_jmpbuf(pPng), 1 );
|
||||
}
|
||||
|
||||
static void PNG_Warning( png_struct *png, const char *warning )
|
||||
{
|
||||
LOG->Trace( "saving PNG: warning: %s", warning );
|
||||
}
|
||||
|
||||
/* Since libpng forces us to use longjmp, this function shouldn't create any C++
|
||||
* objects, and needs to watch out for memleaks. */
|
||||
static bool RageSurface_Save_PNG( RageFile &f, char szErrorbuf[1024], RageSurface *pImgIn )
|
||||
{
|
||||
bool bAlpha = pImgIn->format->Amask != 0;
|
||||
RageSurface *pImg;
|
||||
bool bDeleteImg = RageSurfaceUtils::ConvertSurface( pImgIn, pImg, pImgIn->w, pImgIn->h, 32,
|
||||
Swap32BE( 0xFF000000 ),
|
||||
Swap32BE( 0x00FF0000 ),
|
||||
Swap32BE( 0x0000FF00 ),
|
||||
Swap32BE( 0x000000FF ) );
|
||||
if( !bDeleteImg )
|
||||
pImg = pImgIn;
|
||||
|
||||
error_info error;
|
||||
error.szErr = szErrorbuf;
|
||||
|
||||
png_struct *pPng = png_create_write_struct( PNG_LIBPNG_VER_STRING, &error, PNG_Error, PNG_Warning );
|
||||
if( pPng == NULL )
|
||||
{
|
||||
sprintf( szErrorbuf, "creating png_create_write_struct failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
png_info *pInfo = png_create_info_struct(pPng);
|
||||
if( pInfo == NULL )
|
||||
{
|
||||
png_destroy_read_struct( &pPng, NULL, NULL );
|
||||
if( bDeleteImg )
|
||||
delete pImg;
|
||||
sprintf( szErrorbuf, "creating png_create_info_struct failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if( setjmp(png_jmpbuf(pPng)) )
|
||||
{
|
||||
png_destroy_read_struct( &pPng, &pInfo, NULL );
|
||||
return false;
|
||||
}
|
||||
|
||||
png_set_write_fn( pPng, &f, RageFile_png_write, RageFile_png_flush );
|
||||
png_set_compression_level( pPng, 1 );
|
||||
|
||||
png_set_IHDR( pPng, pInfo, pImg->w, pImg->h, 8, bAlpha? PNG_COLOR_TYPE_RGBA:PNG_COLOR_TYPE_RGB,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE );
|
||||
|
||||
png_write_info( pPng, pInfo );
|
||||
png_set_filler( pPng, 0, PNG_FILLER_AFTER );
|
||||
|
||||
png_byte *pixels = (png_byte *) pImg->pixels;
|
||||
for( int y = 0; y < pImg->h; y++ )
|
||||
png_write_row( pPng, pixels + pImg->pitch*y );
|
||||
|
||||
png_write_end( pPng, pInfo );
|
||||
png_destroy_write_struct( &pPng, &pInfo );
|
||||
|
||||
/* Free the converted image. */
|
||||
if( bDeleteImg )
|
||||
delete pImg;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RageSurfaceUtils::SavePNG( RageSurface *pImg, RageFile &f, RString &sError )
|
||||
{
|
||||
char szErrorBuf[1024];
|
||||
if( !RageSurface_Save_PNG(f, szErrorBuf, pImg) )
|
||||
{
|
||||
sError = szErrorBuf;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2004-2006 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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 "global.h"
|
||||
#include "RageSurface_Save_PNG.h"
|
||||
#include "RageSurface.h"
|
||||
#include "RageSurfaceUtils.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
|
||||
#if defined(WINDOWS) || defined(_XBOX)
|
||||
#include "libpng/include/png.h"
|
||||
#if defined(_MSC_VER)
|
||||
# if defined(_XBOX)
|
||||
# pragma comment(lib, "libpng/lib/xboxlibpng.lib")
|
||||
# else
|
||||
# pragma comment(lib, "libpng/lib/libpng.lib")
|
||||
# endif
|
||||
#pragma warning(disable: 4611) /* interaction between '_setjmp' and C++ object destruction is non-portable */
|
||||
#endif
|
||||
#else
|
||||
#include <png.h>
|
||||
#endif
|
||||
|
||||
static void SafePngError( png_struct *pPng, const RString &sStr )
|
||||
{
|
||||
/* png_error will call PNG_Error, which will longjmp. If we just pass
|
||||
* GetError().c_str() to it, a temporary may be created; since control
|
||||
* never returns, it may never be destructed and leak. */
|
||||
static char error[256];
|
||||
strncpy( error, sStr, sizeof(error) );
|
||||
error[sizeof(error)-1] = 0;
|
||||
png_error( pPng, error );
|
||||
}
|
||||
|
||||
static void RageFile_png_write( png_struct *pPng, png_byte *pData, png_size_t iSize )
|
||||
{
|
||||
RageFile *pFile = (RageFile *) png_get_io_ptr(pPng);
|
||||
|
||||
int iGot = pFile->Write( pData, iSize );
|
||||
if( iGot == -1 )
|
||||
SafePngError( pPng, pFile->GetError() );
|
||||
}
|
||||
|
||||
static void RageFile_png_flush( png_struct *pPng )
|
||||
{
|
||||
RageFile *pFile = (RageFile *) png_get_io_ptr(pPng);
|
||||
|
||||
int iGot = pFile->Flush();
|
||||
if( iGot == -1 )
|
||||
SafePngError( pPng, pFile->GetError() );
|
||||
}
|
||||
|
||||
struct error_info
|
||||
{
|
||||
char *szErr;
|
||||
};
|
||||
|
||||
static void PNG_Error( png_struct *pPng, const char *szError )
|
||||
{
|
||||
error_info *pInfo = (error_info *) png_get_error_ptr(pPng);
|
||||
strncpy( pInfo->szErr, szError, 1024 );
|
||||
pInfo->szErr[1023] = 0;
|
||||
longjmp( png_jmpbuf(pPng), 1 );
|
||||
}
|
||||
|
||||
static void PNG_Warning( png_struct *png, const char *warning )
|
||||
{
|
||||
LOG->Trace( "saving PNG: warning: %s", warning );
|
||||
}
|
||||
|
||||
/* Since libpng forces us to use longjmp, this function shouldn't create any C++
|
||||
* objects, and needs to watch out for memleaks. */
|
||||
static bool RageSurface_Save_PNG( RageFile &f, char szErrorbuf[1024], RageSurface *pImgIn )
|
||||
{
|
||||
bool bAlpha = pImgIn->format->Amask != 0;
|
||||
RageSurface *pImg;
|
||||
bool bDeleteImg = RageSurfaceUtils::ConvertSurface( pImgIn, pImg, pImgIn->w, pImgIn->h, 32,
|
||||
Swap32BE( 0xFF000000 ),
|
||||
Swap32BE( 0x00FF0000 ),
|
||||
Swap32BE( 0x0000FF00 ),
|
||||
Swap32BE( 0x000000FF ) );
|
||||
if( !bDeleteImg )
|
||||
pImg = pImgIn;
|
||||
|
||||
error_info error;
|
||||
error.szErr = szErrorbuf;
|
||||
|
||||
png_struct *pPng = png_create_write_struct( PNG_LIBPNG_VER_STRING, &error, PNG_Error, PNG_Warning );
|
||||
if( pPng == NULL )
|
||||
{
|
||||
sprintf( szErrorbuf, "creating png_create_write_struct failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
png_info *pInfo = png_create_info_struct(pPng);
|
||||
if( pInfo == NULL )
|
||||
{
|
||||
png_destroy_read_struct( &pPng, NULL, NULL );
|
||||
if( bDeleteImg )
|
||||
delete pImg;
|
||||
sprintf( szErrorbuf, "creating png_create_info_struct failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if( setjmp(png_jmpbuf(pPng)) )
|
||||
{
|
||||
png_destroy_read_struct( &pPng, &pInfo, NULL );
|
||||
return false;
|
||||
}
|
||||
|
||||
png_set_write_fn( pPng, &f, RageFile_png_write, RageFile_png_flush );
|
||||
png_set_compression_level( pPng, 1 );
|
||||
|
||||
png_set_IHDR( pPng, pInfo, pImg->w, pImg->h, 8, bAlpha? PNG_COLOR_TYPE_RGBA:PNG_COLOR_TYPE_RGB,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE );
|
||||
|
||||
png_write_info( pPng, pInfo );
|
||||
png_set_filler( pPng, 0, PNG_FILLER_AFTER );
|
||||
|
||||
png_byte *pixels = (png_byte *) pImg->pixels;
|
||||
for( int y = 0; y < pImg->h; y++ )
|
||||
png_write_row( pPng, pixels + pImg->pitch*y );
|
||||
|
||||
png_write_end( pPng, pInfo );
|
||||
png_destroy_write_struct( &pPng, &pInfo );
|
||||
|
||||
/* Free the converted image. */
|
||||
if( bDeleteImg )
|
||||
delete pImg;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RageSurfaceUtils::SavePNG( RageSurface *pImg, RageFile &f, RString &sError )
|
||||
{
|
||||
char szErrorBuf[1024];
|
||||
if( !RageSurface_Save_PNG(f, szErrorBuf, pImg) )
|
||||
{
|
||||
sError = szErrorBuf;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2004-2006 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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.
|
||||
*/
|
||||
|
||||
@@ -1,447 +1,447 @@
|
||||
#include "global.h"
|
||||
#include "InputHandler_Linux_Event.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
REGISTER_INPUT_HANDLER_CLASS2( Event, Linux_Event );
|
||||
|
||||
bool InputHandler_Linux_Event::m_bFoundAnyJoysticks;
|
||||
|
||||
static RString BustypeToString( int iBus )
|
||||
{
|
||||
switch( iBus )
|
||||
{
|
||||
// case BUS_ADB:
|
||||
// case BUS_AMIGA: return "amiga input";
|
||||
case BUS_BLUETOOTH: return "Bluetooth";
|
||||
case BUS_GAMEPORT: return "gameport";
|
||||
// case BUS_HIL:
|
||||
// case BUS_HOST:
|
||||
// case BUS_I2C:
|
||||
case BUS_I8042: return "keyboard";
|
||||
case BUS_ISA: return "ISA";
|
||||
case BUS_ISAPNP: return "ISAPNP";
|
||||
case BUS_PARPORT: return "parallel port";
|
||||
case BUS_PCI: return "PCI";
|
||||
case BUS_RS232: return "serial port";
|
||||
case BUS_USB: return "USB";
|
||||
case BUS_XTKBD: return "XT keyboard";
|
||||
default: return ssprintf("unknown bus %x", iBus);
|
||||
}
|
||||
}
|
||||
|
||||
struct EventDevice
|
||||
{
|
||||
EventDevice();
|
||||
~EventDevice();
|
||||
bool Open( RString sFile, InputDevice dev );
|
||||
bool IsOpen() const { return m_iFD != -1; }
|
||||
void Close()
|
||||
{
|
||||
if( m_iFD != -1 )
|
||||
close( m_iFD );
|
||||
m_iFD = -1;
|
||||
}
|
||||
|
||||
int m_iFD;
|
||||
RString m_sPath;
|
||||
RString m_sName;
|
||||
InputDevice m_Dev;
|
||||
|
||||
int aiAbsMin[ABS_MAX];
|
||||
int aiAbsMax[ABS_MAX];
|
||||
DeviceButton aiAbsMappingHigh[ABS_MAX];
|
||||
DeviceButton aiAbsMappingLow[ABS_MAX];
|
||||
};
|
||||
|
||||
static vector<EventDevice *> g_apEventDevices;
|
||||
|
||||
/* Return true if the numbered event device exists. sysfs may not always be
|
||||
* there; return false if we don't know. */
|
||||
static bool EventDeviceExists( int iNum )
|
||||
{
|
||||
RString sDir = ssprintf( "/sys/class" );
|
||||
struct stat st;
|
||||
if( stat(sDir, &st) == -1 )
|
||||
return true;
|
||||
|
||||
RString sFile = ssprintf( "/sys/class/input/event%i", iNum );
|
||||
return stat(sFile, &st) == 0;
|
||||
}
|
||||
|
||||
static bool BitIsSet( const uint8_t *pArray, uint32_t iBit )
|
||||
{
|
||||
return !!(pArray[iBit/8] & (1<<(iBit%8)));
|
||||
}
|
||||
|
||||
EventDevice::EventDevice()
|
||||
{
|
||||
m_iFD = -1;
|
||||
}
|
||||
|
||||
bool EventDevice::Open( RString sFile, InputDevice dev )
|
||||
{
|
||||
m_sPath = sFile;
|
||||
m_Dev = dev;
|
||||
m_iFD = open( sFile, O_RDWR );
|
||||
if( m_iFD == -1 )
|
||||
{
|
||||
if( errno == ENODEV )
|
||||
return false;
|
||||
|
||||
if( !EventDeviceExists(m_iFD) )
|
||||
return false;
|
||||
|
||||
LOG->Warn( "Error opening %s: %s", sFile.c_str(), strerror(errno) );
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool bLogged = false;
|
||||
if( !bLogged )
|
||||
{
|
||||
bLogged = true;
|
||||
int iVersion;
|
||||
if( ioctl(m_iFD, EVIOCGVERSION, &iVersion) == -1 )
|
||||
LOG->Warn( "ioctl(EVIOCGVERSION): %s", strerror(errno) );
|
||||
else
|
||||
LOG->Info( "Event driver: v%i.%i.%i", (iVersion >> 16) & 0xFF, (iVersion >> 8) & 0xFF, iVersion & 0xFF );
|
||||
}
|
||||
|
||||
char szName[1024];
|
||||
if( ioctl(m_iFD, EVIOCGNAME(sizeof(szName)), szName) == -1 )
|
||||
{
|
||||
LOG->Warn( "ioctl(EVIOCGNAME): %s", strerror(errno) );
|
||||
|
||||
m_sName = "(unknown)";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sName = szName;
|
||||
}
|
||||
|
||||
input_id DevInfo;
|
||||
if( ioctl(m_iFD, EVIOCGID, &DevInfo) == -1 )
|
||||
{
|
||||
LOG->Warn( "ioctl(EVIOCGID): %s", strerror(errno) );
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG->Info( "Input device: %s: %s device, ID %04x:%04x, version %x: %s", sFile.c_str(),
|
||||
BustypeToString(DevInfo.bustype).c_str(), DevInfo.vendor, DevInfo.product,
|
||||
DevInfo.version, m_sName.c_str() );
|
||||
}
|
||||
|
||||
uint8_t iABSMask[ABS_MAX/8 + 1];
|
||||
memset( iABSMask, 0, sizeof(iABSMask) );
|
||||
if( ioctl(m_iFD, EVIOCGBIT(EV_ABS, sizeof(iABSMask)), iABSMask) < 0 )
|
||||
LOG->Warn( "ioctl(EVIOCGBIT(EV_ABS)): %s", strerror(errno) );
|
||||
|
||||
if( !BitIsSet(iABSMask, ABS_X) && !BitIsSet(iABSMask, ABS_THROTTLE) && !BitIsSet(iABSMask, ABS_WHEEL) )
|
||||
{
|
||||
LOG->Info( " Not a joystick; ignored" );
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t iKeyMask[KEY_MAX/8 + 1];
|
||||
memset( iKeyMask, 0, sizeof(iKeyMask) );
|
||||
if( ioctl(m_iFD, EVIOCGBIT(EV_KEY, sizeof(iKeyMask)), iKeyMask) < 0 )
|
||||
LOG->Warn( "ioctl(EVIOCGBIT(EV_KEY)): %s", strerror(errno) );
|
||||
|
||||
uint8_t iEventTypes[EV_MAX/8];
|
||||
memset( iEventTypes, 0, sizeof(iEventTypes) );
|
||||
if( ioctl(m_iFD, EVIOCGBIT(0, EV_MAX), iEventTypes) == -1 )
|
||||
LOG->Warn( "ioctl(EV_MAX): %s", strerror(errno) );
|
||||
|
||||
{
|
||||
vector<RString> setEventTypes;
|
||||
|
||||
if( BitIsSet(iEventTypes, EV_SYN) ) setEventTypes.push_back( "syn" );
|
||||
if( BitIsSet(iEventTypes, EV_KEY) ) setEventTypes.push_back( "key" );
|
||||
if( BitIsSet(iEventTypes, EV_REL) ) setEventTypes.push_back( "rel" );
|
||||
if( BitIsSet(iEventTypes, EV_ABS) ) setEventTypes.push_back( "abs" );
|
||||
if( BitIsSet(iEventTypes, EV_MSC) ) setEventTypes.push_back( "misc" );
|
||||
if( BitIsSet(iEventTypes, EV_SW) ) setEventTypes.push_back( "sw" );
|
||||
if( BitIsSet(iEventTypes, EV_LED) ) setEventTypes.push_back( "led" );
|
||||
if( BitIsSet(iEventTypes, EV_SND) ) setEventTypes.push_back( "snd" );
|
||||
if( BitIsSet(iEventTypes, EV_REP) ) setEventTypes.push_back( "rep" );
|
||||
if( BitIsSet(iEventTypes, EV_FF) ) setEventTypes.push_back( "ff" );
|
||||
if( BitIsSet(iEventTypes, EV_PWR) ) setEventTypes.push_back( "pwr" );
|
||||
if( BitIsSet(iEventTypes, EV_FF_STATUS) ) setEventTypes.push_back( "ff_status" );
|
||||
|
||||
LOG->Info( " Event types: %s", join(", ", setEventTypes).c_str() );
|
||||
}
|
||||
|
||||
int iTotalKeys = 0;
|
||||
for( int i = 0; i < KEY_MAX; ++i )
|
||||
{
|
||||
if( !BitIsSet(iKeyMask, i) )
|
||||
continue;
|
||||
++iTotalKeys;
|
||||
}
|
||||
|
||||
int iTotalAxes = 0;
|
||||
const DeviceButton iExtraAxes[] = { JOY_LEFT_2, JOY_UP_2, JOY_AUX_1, JOY_AUX_3 };
|
||||
int iNextExtraAxis = 0;
|
||||
for( int i = 0; i < ABS_MAX; ++i )
|
||||
{
|
||||
if( !BitIsSet(iABSMask, i) )
|
||||
continue;
|
||||
struct input_absinfo absinfo;
|
||||
if( ioctl(m_iFD, EVIOCGABS(i), &absinfo) < 0 )
|
||||
{
|
||||
LOG->Warn( "ioctl(EVIOCGABS): %s", strerror(errno) );
|
||||
continue;
|
||||
}
|
||||
|
||||
//LOG->Info( " Axis %i: min: %i; max: %i; fuzz: %i; flat: %i",
|
||||
// i, absinfo.minimum, absinfo.maximum, absinfo.fuzz, absinfo.flat );
|
||||
aiAbsMin[i] = absinfo.minimum;
|
||||
aiAbsMax[i] = absinfo.maximum;
|
||||
aiAbsMappingHigh[i] = enum_add2(JOY_RIGHT, 2*i);
|
||||
aiAbsMappingLow[i] = enum_add2(JOY_LEFT, 2*i);
|
||||
|
||||
if( i == ABS_X )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_RIGHT;
|
||||
aiAbsMappingLow[i] = JOY_LEFT;
|
||||
}
|
||||
else if( i == ABS_Y )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_DOWN;
|
||||
aiAbsMappingLow[i] = JOY_UP;
|
||||
}
|
||||
else if( i == ABS_Z )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_Z_DOWN;
|
||||
aiAbsMappingLow[i] = JOY_Z_UP;
|
||||
}
|
||||
else if( i == ABS_RX )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_ROT_RIGHT;
|
||||
aiAbsMappingLow[i] = JOY_ROT_LEFT;
|
||||
}
|
||||
else if( i == ABS_RY )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_ROT_DOWN;
|
||||
aiAbsMappingLow[i] = JOY_ROT_UP;
|
||||
}
|
||||
else if( i == ABS_RZ )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_ROT_Z_DOWN;
|
||||
aiAbsMappingLow[i] = JOY_ROT_Z_UP;
|
||||
}
|
||||
else if( i == ABS_HAT0X )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_HAT_RIGHT;
|
||||
aiAbsMappingLow[i] = JOY_HAT_LEFT;
|
||||
}
|
||||
else if( i == ABS_HAT0Y )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_HAT_UP;
|
||||
aiAbsMappingLow[i] = JOY_HAT_DOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( iNextExtraAxis < (int) ARRAYLEN(iExtraAxes) )
|
||||
{
|
||||
aiAbsMappingLow[i] = iExtraAxes[iNextExtraAxis];
|
||||
aiAbsMappingHigh[i] = enum_add2( aiAbsMappingLow[i], 1 );
|
||||
++iNextExtraAxis;
|
||||
}
|
||||
}
|
||||
|
||||
++iTotalAxes;
|
||||
}
|
||||
LOG->Info( " Total keys: %i; total axes: %i", iTotalKeys, iTotalAxes );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EventDevice::~EventDevice()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
InputHandler_Linux_Event::InputHandler_Linux_Event()
|
||||
{
|
||||
if( InputHandler_Linux_Event::m_bFoundAnyJoysticks )
|
||||
{
|
||||
LOG->Trace( "InputHandler_Linux_Event disabled (joystick driver already loaded)" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Permission problems are likely. We want to warn about them only if there's actually
|
||||
* an underlying device, but if we can't open the device, the only way we can tell if
|
||||
* there'd be anything there is sysfs. That won't always be there. */
|
||||
m_bFoundAnyJoysticks = false;
|
||||
InputDevice NextDevice = DEVICE_JOY1;
|
||||
for( int i = 0; i < 64; ++i )
|
||||
{
|
||||
RString sFile = ssprintf( "/dev/input/event%i", i );
|
||||
|
||||
g_apEventDevices.push_back( new EventDevice );
|
||||
EventDevice *pDev = g_apEventDevices.back();
|
||||
if( !pDev->Open(sFile, NextDevice) )
|
||||
{
|
||||
delete pDev;
|
||||
g_apEventDevices.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
NextDevice = enum_add2(NextDevice, 1);
|
||||
m_bFoundAnyJoysticks = true;
|
||||
}
|
||||
|
||||
m_bShutdown = false;
|
||||
|
||||
if( m_bFoundAnyJoysticks )
|
||||
{
|
||||
m_InputThread.SetName( "Event input thread" );
|
||||
m_InputThread.Create( InputThread_Start, this );
|
||||
|
||||
/* We loaded joysticks, so disable joydev. */
|
||||
}
|
||||
}
|
||||
|
||||
InputHandler_Linux_Event::~InputHandler_Linux_Event()
|
||||
{
|
||||
if( m_InputThread.IsCreated() )
|
||||
{
|
||||
m_bShutdown = true;
|
||||
LOG->Trace( "Shutting down joystick thread ..." );
|
||||
m_InputThread.Wait();
|
||||
LOG->Trace( "Joystick thread shut down." );
|
||||
}
|
||||
|
||||
for( int i = 0; i < (int) g_apEventDevices.size(); ++i )
|
||||
delete g_apEventDevices[i];
|
||||
g_apEventDevices.clear();
|
||||
}
|
||||
|
||||
int InputHandler_Linux_Event::InputThread_Start( void *p )
|
||||
{
|
||||
((InputHandler_Linux_Event *) p)->InputThread();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InputHandler_Linux_Event::InputThread()
|
||||
{
|
||||
while( !m_bShutdown )
|
||||
{
|
||||
fd_set fdset;
|
||||
FD_ZERO( &fdset );
|
||||
int iMaxFD = -1;
|
||||
|
||||
for( int i = 0; i < (int) g_apEventDevices.size(); ++i )
|
||||
{
|
||||
int iFD = g_apEventDevices[i]->m_iFD;
|
||||
if( !g_apEventDevices[i]->IsOpen() )
|
||||
continue;
|
||||
|
||||
FD_SET( iFD, &fdset );
|
||||
iMaxFD = max( iMaxFD, iFD );
|
||||
}
|
||||
|
||||
if( iMaxFD == -1 )
|
||||
break;
|
||||
|
||||
struct timeval zero = {0,100000};
|
||||
if( select(iMaxFD+1, &fdset, NULL, NULL, &zero) <= 0 )
|
||||
continue;
|
||||
RageTimer now;
|
||||
|
||||
for( int i = 0; i < (int) g_apEventDevices.size(); ++i )
|
||||
{
|
||||
if( !g_apEventDevices[i]->IsOpen() )
|
||||
continue;
|
||||
|
||||
if( !FD_ISSET(g_apEventDevices[i]->m_iFD, &fdset) )
|
||||
continue;
|
||||
|
||||
input_event event;
|
||||
int ret = read( g_apEventDevices[i]->m_iFD, &event, sizeof(event) );
|
||||
if( ret == -1 )
|
||||
{
|
||||
LOG->Warn( "Error reading from %s: %s; disabled", g_apEventDevices[i]->m_sPath.c_str(), strerror(errno) );
|
||||
g_apEventDevices[i]->Close();
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ret != sizeof(event) )
|
||||
{
|
||||
LOG->Warn("Unexpected packet (size %i != %i) from joystick %i; disabled", ret, (int)sizeof(event), i);
|
||||
g_apEventDevices[i]->Close();
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case EV_KEY: {
|
||||
int iNum = event.code;
|
||||
// In 2.6.11 using an EMS USB2, the event number for P1 Tri (the first button)
|
||||
// is being reported as 32 instead of 0. Correct for this.
|
||||
wrap( iNum, 32 ); // max number of joystick buttons. Make this a constant?
|
||||
ButtonPressed( DeviceInput(g_apEventDevices[i]->m_Dev, enum_add2(JOY_BUTTON_1, iNum), event.value != 0, now) );
|
||||
break;
|
||||
}
|
||||
|
||||
case EV_ABS: {
|
||||
ASSERT_M( event.code < ABS_MAX, ssprintf("%i", event.code) );
|
||||
DeviceButton neg = g_apEventDevices[i]->aiAbsMappingLow[event.code];
|
||||
DeviceButton pos = g_apEventDevices[i]->aiAbsMappingHigh[event.code];
|
||||
|
||||
float l = SCALE( int(event.value), (float) g_apEventDevices[i]->aiAbsMin[i], (float) g_apEventDevices[i]->aiAbsMax[i], -1.0f, 1.0f );
|
||||
ButtonPressed( DeviceInput(g_apEventDevices[i]->m_Dev, neg, max(-l,0), now) );
|
||||
ButtonPressed( DeviceInput(g_apEventDevices[i]->m_Dev, pos, max(+l,0), now) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
InputHandler::UpdateTimer();
|
||||
}
|
||||
|
||||
void InputHandler_Linux_Event::GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevicesOut )
|
||||
{
|
||||
for( unsigned i = 0; i < g_apEventDevices.size(); ++i )
|
||||
{
|
||||
EventDevice *pDev = g_apEventDevices[i];
|
||||
vDevicesOut.push_back( InputDeviceInfo(pDev->m_Dev, pDev->m_sName) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-2008 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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 "global.h"
|
||||
#include "InputHandler_Linux_Event.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
REGISTER_INPUT_HANDLER_CLASS2( Event, Linux_Event );
|
||||
|
||||
bool InputHandler_Linux_Event::m_bFoundAnyJoysticks;
|
||||
|
||||
static RString BustypeToString( int iBus )
|
||||
{
|
||||
switch( iBus )
|
||||
{
|
||||
// case BUS_ADB:
|
||||
// case BUS_AMIGA: return "amiga input";
|
||||
case BUS_BLUETOOTH: return "Bluetooth";
|
||||
case BUS_GAMEPORT: return "gameport";
|
||||
// case BUS_HIL:
|
||||
// case BUS_HOST:
|
||||
// case BUS_I2C:
|
||||
case BUS_I8042: return "keyboard";
|
||||
case BUS_ISA: return "ISA";
|
||||
case BUS_ISAPNP: return "ISAPNP";
|
||||
case BUS_PARPORT: return "parallel port";
|
||||
case BUS_PCI: return "PCI";
|
||||
case BUS_RS232: return "serial port";
|
||||
case BUS_USB: return "USB";
|
||||
case BUS_XTKBD: return "XT keyboard";
|
||||
default: return ssprintf("unknown bus %x", iBus);
|
||||
}
|
||||
}
|
||||
|
||||
struct EventDevice
|
||||
{
|
||||
EventDevice();
|
||||
~EventDevice();
|
||||
bool Open( RString sFile, InputDevice dev );
|
||||
bool IsOpen() const { return m_iFD != -1; }
|
||||
void Close()
|
||||
{
|
||||
if( m_iFD != -1 )
|
||||
close( m_iFD );
|
||||
m_iFD = -1;
|
||||
}
|
||||
|
||||
int m_iFD;
|
||||
RString m_sPath;
|
||||
RString m_sName;
|
||||
InputDevice m_Dev;
|
||||
|
||||
int aiAbsMin[ABS_MAX];
|
||||
int aiAbsMax[ABS_MAX];
|
||||
DeviceButton aiAbsMappingHigh[ABS_MAX];
|
||||
DeviceButton aiAbsMappingLow[ABS_MAX];
|
||||
};
|
||||
|
||||
static vector<EventDevice *> g_apEventDevices;
|
||||
|
||||
/* Return true if the numbered event device exists. sysfs may not always be
|
||||
* there; return false if we don't know. */
|
||||
static bool EventDeviceExists( int iNum )
|
||||
{
|
||||
RString sDir = ssprintf( "/sys/class" );
|
||||
struct stat st;
|
||||
if( stat(sDir, &st) == -1 )
|
||||
return true;
|
||||
|
||||
RString sFile = ssprintf( "/sys/class/input/event%i", iNum );
|
||||
return stat(sFile, &st) == 0;
|
||||
}
|
||||
|
||||
static bool BitIsSet( const uint8_t *pArray, uint32_t iBit )
|
||||
{
|
||||
return !!(pArray[iBit/8] & (1<<(iBit%8)));
|
||||
}
|
||||
|
||||
EventDevice::EventDevice()
|
||||
{
|
||||
m_iFD = -1;
|
||||
}
|
||||
|
||||
bool EventDevice::Open( RString sFile, InputDevice dev )
|
||||
{
|
||||
m_sPath = sFile;
|
||||
m_Dev = dev;
|
||||
m_iFD = open( sFile, O_RDWR );
|
||||
if( m_iFD == -1 )
|
||||
{
|
||||
if( errno == ENODEV )
|
||||
return false;
|
||||
|
||||
if( !EventDeviceExists(m_iFD) )
|
||||
return false;
|
||||
|
||||
LOG->Warn( "Error opening %s: %s", sFile.c_str(), strerror(errno) );
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool bLogged = false;
|
||||
if( !bLogged )
|
||||
{
|
||||
bLogged = true;
|
||||
int iVersion;
|
||||
if( ioctl(m_iFD, EVIOCGVERSION, &iVersion) == -1 )
|
||||
LOG->Warn( "ioctl(EVIOCGVERSION): %s", strerror(errno) );
|
||||
else
|
||||
LOG->Info( "Event driver: v%i.%i.%i", (iVersion >> 16) & 0xFF, (iVersion >> 8) & 0xFF, iVersion & 0xFF );
|
||||
}
|
||||
|
||||
char szName[1024];
|
||||
if( ioctl(m_iFD, EVIOCGNAME(sizeof(szName)), szName) == -1 )
|
||||
{
|
||||
LOG->Warn( "ioctl(EVIOCGNAME): %s", strerror(errno) );
|
||||
|
||||
m_sName = "(unknown)";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sName = szName;
|
||||
}
|
||||
|
||||
input_id DevInfo;
|
||||
if( ioctl(m_iFD, EVIOCGID, &DevInfo) == -1 )
|
||||
{
|
||||
LOG->Warn( "ioctl(EVIOCGID): %s", strerror(errno) );
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG->Info( "Input device: %s: %s device, ID %04x:%04x, version %x: %s", sFile.c_str(),
|
||||
BustypeToString(DevInfo.bustype).c_str(), DevInfo.vendor, DevInfo.product,
|
||||
DevInfo.version, m_sName.c_str() );
|
||||
}
|
||||
|
||||
uint8_t iABSMask[ABS_MAX/8 + 1];
|
||||
memset( iABSMask, 0, sizeof(iABSMask) );
|
||||
if( ioctl(m_iFD, EVIOCGBIT(EV_ABS, sizeof(iABSMask)), iABSMask) < 0 )
|
||||
LOG->Warn( "ioctl(EVIOCGBIT(EV_ABS)): %s", strerror(errno) );
|
||||
|
||||
if( !BitIsSet(iABSMask, ABS_X) && !BitIsSet(iABSMask, ABS_THROTTLE) && !BitIsSet(iABSMask, ABS_WHEEL) )
|
||||
{
|
||||
LOG->Info( " Not a joystick; ignored" );
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t iKeyMask[KEY_MAX/8 + 1];
|
||||
memset( iKeyMask, 0, sizeof(iKeyMask) );
|
||||
if( ioctl(m_iFD, EVIOCGBIT(EV_KEY, sizeof(iKeyMask)), iKeyMask) < 0 )
|
||||
LOG->Warn( "ioctl(EVIOCGBIT(EV_KEY)): %s", strerror(errno) );
|
||||
|
||||
uint8_t iEventTypes[EV_MAX/8];
|
||||
memset( iEventTypes, 0, sizeof(iEventTypes) );
|
||||
if( ioctl(m_iFD, EVIOCGBIT(0, EV_MAX), iEventTypes) == -1 )
|
||||
LOG->Warn( "ioctl(EV_MAX): %s", strerror(errno) );
|
||||
|
||||
{
|
||||
vector<RString> setEventTypes;
|
||||
|
||||
if( BitIsSet(iEventTypes, EV_SYN) ) setEventTypes.push_back( "syn" );
|
||||
if( BitIsSet(iEventTypes, EV_KEY) ) setEventTypes.push_back( "key" );
|
||||
if( BitIsSet(iEventTypes, EV_REL) ) setEventTypes.push_back( "rel" );
|
||||
if( BitIsSet(iEventTypes, EV_ABS) ) setEventTypes.push_back( "abs" );
|
||||
if( BitIsSet(iEventTypes, EV_MSC) ) setEventTypes.push_back( "misc" );
|
||||
if( BitIsSet(iEventTypes, EV_SW) ) setEventTypes.push_back( "sw" );
|
||||
if( BitIsSet(iEventTypes, EV_LED) ) setEventTypes.push_back( "led" );
|
||||
if( BitIsSet(iEventTypes, EV_SND) ) setEventTypes.push_back( "snd" );
|
||||
if( BitIsSet(iEventTypes, EV_REP) ) setEventTypes.push_back( "rep" );
|
||||
if( BitIsSet(iEventTypes, EV_FF) ) setEventTypes.push_back( "ff" );
|
||||
if( BitIsSet(iEventTypes, EV_PWR) ) setEventTypes.push_back( "pwr" );
|
||||
if( BitIsSet(iEventTypes, EV_FF_STATUS) ) setEventTypes.push_back( "ff_status" );
|
||||
|
||||
LOG->Info( " Event types: %s", join(", ", setEventTypes).c_str() );
|
||||
}
|
||||
|
||||
int iTotalKeys = 0;
|
||||
for( int i = 0; i < KEY_MAX; ++i )
|
||||
{
|
||||
if( !BitIsSet(iKeyMask, i) )
|
||||
continue;
|
||||
++iTotalKeys;
|
||||
}
|
||||
|
||||
int iTotalAxes = 0;
|
||||
const DeviceButton iExtraAxes[] = { JOY_LEFT_2, JOY_UP_2, JOY_AUX_1, JOY_AUX_3 };
|
||||
int iNextExtraAxis = 0;
|
||||
for( int i = 0; i < ABS_MAX; ++i )
|
||||
{
|
||||
if( !BitIsSet(iABSMask, i) )
|
||||
continue;
|
||||
struct input_absinfo absinfo;
|
||||
if( ioctl(m_iFD, EVIOCGABS(i), &absinfo) < 0 )
|
||||
{
|
||||
LOG->Warn( "ioctl(EVIOCGABS): %s", strerror(errno) );
|
||||
continue;
|
||||
}
|
||||
|
||||
//LOG->Info( " Axis %i: min: %i; max: %i; fuzz: %i; flat: %i",
|
||||
// i, absinfo.minimum, absinfo.maximum, absinfo.fuzz, absinfo.flat );
|
||||
aiAbsMin[i] = absinfo.minimum;
|
||||
aiAbsMax[i] = absinfo.maximum;
|
||||
aiAbsMappingHigh[i] = enum_add2(JOY_RIGHT, 2*i);
|
||||
aiAbsMappingLow[i] = enum_add2(JOY_LEFT, 2*i);
|
||||
|
||||
if( i == ABS_X )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_RIGHT;
|
||||
aiAbsMappingLow[i] = JOY_LEFT;
|
||||
}
|
||||
else if( i == ABS_Y )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_DOWN;
|
||||
aiAbsMappingLow[i] = JOY_UP;
|
||||
}
|
||||
else if( i == ABS_Z )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_Z_DOWN;
|
||||
aiAbsMappingLow[i] = JOY_Z_UP;
|
||||
}
|
||||
else if( i == ABS_RX )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_ROT_RIGHT;
|
||||
aiAbsMappingLow[i] = JOY_ROT_LEFT;
|
||||
}
|
||||
else if( i == ABS_RY )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_ROT_DOWN;
|
||||
aiAbsMappingLow[i] = JOY_ROT_UP;
|
||||
}
|
||||
else if( i == ABS_RZ )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_ROT_Z_DOWN;
|
||||
aiAbsMappingLow[i] = JOY_ROT_Z_UP;
|
||||
}
|
||||
else if( i == ABS_HAT0X )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_HAT_RIGHT;
|
||||
aiAbsMappingLow[i] = JOY_HAT_LEFT;
|
||||
}
|
||||
else if( i == ABS_HAT0Y )
|
||||
{
|
||||
aiAbsMappingHigh[i] = JOY_HAT_UP;
|
||||
aiAbsMappingLow[i] = JOY_HAT_DOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( iNextExtraAxis < (int) ARRAYLEN(iExtraAxes) )
|
||||
{
|
||||
aiAbsMappingLow[i] = iExtraAxes[iNextExtraAxis];
|
||||
aiAbsMappingHigh[i] = enum_add2( aiAbsMappingLow[i], 1 );
|
||||
++iNextExtraAxis;
|
||||
}
|
||||
}
|
||||
|
||||
++iTotalAxes;
|
||||
}
|
||||
LOG->Info( " Total keys: %i; total axes: %i", iTotalKeys, iTotalAxes );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EventDevice::~EventDevice()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
InputHandler_Linux_Event::InputHandler_Linux_Event()
|
||||
{
|
||||
if( InputHandler_Linux_Event::m_bFoundAnyJoysticks )
|
||||
{
|
||||
LOG->Trace( "InputHandler_Linux_Event disabled (joystick driver already loaded)" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Permission problems are likely. We want to warn about them only if there's actually
|
||||
* an underlying device, but if we can't open the device, the only way we can tell if
|
||||
* there'd be anything there is sysfs. That won't always be there. */
|
||||
m_bFoundAnyJoysticks = false;
|
||||
InputDevice NextDevice = DEVICE_JOY1;
|
||||
for( int i = 0; i < 64; ++i )
|
||||
{
|
||||
RString sFile = ssprintf( "/dev/input/event%i", i );
|
||||
|
||||
g_apEventDevices.push_back( new EventDevice );
|
||||
EventDevice *pDev = g_apEventDevices.back();
|
||||
if( !pDev->Open(sFile, NextDevice) )
|
||||
{
|
||||
delete pDev;
|
||||
g_apEventDevices.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
NextDevice = enum_add2(NextDevice, 1);
|
||||
m_bFoundAnyJoysticks = true;
|
||||
}
|
||||
|
||||
m_bShutdown = false;
|
||||
|
||||
if( m_bFoundAnyJoysticks )
|
||||
{
|
||||
m_InputThread.SetName( "Event input thread" );
|
||||
m_InputThread.Create( InputThread_Start, this );
|
||||
|
||||
/* We loaded joysticks, so disable joydev. */
|
||||
}
|
||||
}
|
||||
|
||||
InputHandler_Linux_Event::~InputHandler_Linux_Event()
|
||||
{
|
||||
if( m_InputThread.IsCreated() )
|
||||
{
|
||||
m_bShutdown = true;
|
||||
LOG->Trace( "Shutting down joystick thread ..." );
|
||||
m_InputThread.Wait();
|
||||
LOG->Trace( "Joystick thread shut down." );
|
||||
}
|
||||
|
||||
for( int i = 0; i < (int) g_apEventDevices.size(); ++i )
|
||||
delete g_apEventDevices[i];
|
||||
g_apEventDevices.clear();
|
||||
}
|
||||
|
||||
int InputHandler_Linux_Event::InputThread_Start( void *p )
|
||||
{
|
||||
((InputHandler_Linux_Event *) p)->InputThread();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InputHandler_Linux_Event::InputThread()
|
||||
{
|
||||
while( !m_bShutdown )
|
||||
{
|
||||
fd_set fdset;
|
||||
FD_ZERO( &fdset );
|
||||
int iMaxFD = -1;
|
||||
|
||||
for( int i = 0; i < (int) g_apEventDevices.size(); ++i )
|
||||
{
|
||||
int iFD = g_apEventDevices[i]->m_iFD;
|
||||
if( !g_apEventDevices[i]->IsOpen() )
|
||||
continue;
|
||||
|
||||
FD_SET( iFD, &fdset );
|
||||
iMaxFD = max( iMaxFD, iFD );
|
||||
}
|
||||
|
||||
if( iMaxFD == -1 )
|
||||
break;
|
||||
|
||||
struct timeval zero = {0,100000};
|
||||
if( select(iMaxFD+1, &fdset, NULL, NULL, &zero) <= 0 )
|
||||
continue;
|
||||
RageTimer now;
|
||||
|
||||
for( int i = 0; i < (int) g_apEventDevices.size(); ++i )
|
||||
{
|
||||
if( !g_apEventDevices[i]->IsOpen() )
|
||||
continue;
|
||||
|
||||
if( !FD_ISSET(g_apEventDevices[i]->m_iFD, &fdset) )
|
||||
continue;
|
||||
|
||||
input_event event;
|
||||
int ret = read( g_apEventDevices[i]->m_iFD, &event, sizeof(event) );
|
||||
if( ret == -1 )
|
||||
{
|
||||
LOG->Warn( "Error reading from %s: %s; disabled", g_apEventDevices[i]->m_sPath.c_str(), strerror(errno) );
|
||||
g_apEventDevices[i]->Close();
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ret != sizeof(event) )
|
||||
{
|
||||
LOG->Warn("Unexpected packet (size %i != %i) from joystick %i; disabled", ret, (int)sizeof(event), i);
|
||||
g_apEventDevices[i]->Close();
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case EV_KEY: {
|
||||
int iNum = event.code;
|
||||
// In 2.6.11 using an EMS USB2, the event number for P1 Tri (the first button)
|
||||
// is being reported as 32 instead of 0. Correct for this.
|
||||
wrap( iNum, 32 ); // max number of joystick buttons. Make this a constant?
|
||||
ButtonPressed( DeviceInput(g_apEventDevices[i]->m_Dev, enum_add2(JOY_BUTTON_1, iNum), event.value != 0, now) );
|
||||
break;
|
||||
}
|
||||
|
||||
case EV_ABS: {
|
||||
ASSERT_M( event.code < ABS_MAX, ssprintf("%i", event.code) );
|
||||
DeviceButton neg = g_apEventDevices[i]->aiAbsMappingLow[event.code];
|
||||
DeviceButton pos = g_apEventDevices[i]->aiAbsMappingHigh[event.code];
|
||||
|
||||
float l = SCALE( int(event.value), (float) g_apEventDevices[i]->aiAbsMin[i], (float) g_apEventDevices[i]->aiAbsMax[i], -1.0f, 1.0f );
|
||||
ButtonPressed( DeviceInput(g_apEventDevices[i]->m_Dev, neg, max(-l,0), now) );
|
||||
ButtonPressed( DeviceInput(g_apEventDevices[i]->m_Dev, pos, max(+l,0), now) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
InputHandler::UpdateTimer();
|
||||
}
|
||||
|
||||
void InputHandler_Linux_Event::GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevicesOut )
|
||||
{
|
||||
for( unsigned i = 0; i < g_apEventDevices.size(); ++i )
|
||||
{
|
||||
EventDevice *pDev = g_apEventDevices[i];
|
||||
vDevicesOut.push_back( InputDeviceInfo(pDev->m_Dev, pDev->m_sName) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-2008 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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.
|
||||
*/
|
||||
|
||||
@@ -1,227 +1,227 @@
|
||||
#include "global.h"
|
||||
#include "InputHandler_Linux_Joystick.h"
|
||||
#include "InputHandler_Linux_Event.h" // for m_bFoundAnyJoysticks
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <linux/joystick.h>
|
||||
|
||||
#include <set>
|
||||
|
||||
REGISTER_INPUT_HANDLER_CLASS2( Joystick, Linux_Joystick );
|
||||
|
||||
static const char *Paths[InputHandler_Linux_Joystick::NUM_JOYSTICKS] =
|
||||
{
|
||||
"/dev/js0",
|
||||
"/dev/js1",
|
||||
"/dev/input/js0",
|
||||
"/dev/input/js1",
|
||||
};
|
||||
|
||||
InputHandler_Linux_Joystick::InputHandler_Linux_Joystick()
|
||||
{
|
||||
LOG->Trace( "InputHandler_Linux_Joystick::InputHandler_Linux_Joystick" );
|
||||
for(int i = 0; i < NUM_JOYSTICKS; ++i)
|
||||
fds[i] = -1;
|
||||
|
||||
if( InputHandler_Linux_Event::m_bFoundAnyJoysticks )
|
||||
{
|
||||
LOG->Trace( "InputHandler_Linux_Joystick disabled (joystick driver already loaded)" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* We check both eg. /dev/js0 and /dev/input/js0. If both exist, they're probably
|
||||
* the same device; keep track of device IDs so we don't open the same joystick
|
||||
* twice. */
|
||||
set< pair<int,int> > devices;
|
||||
bool bFoundAnyJoysticks = false;
|
||||
|
||||
for(int i = 0; i < NUM_JOYSTICKS; ++i)
|
||||
{
|
||||
struct stat st;
|
||||
if( stat( Paths[i], &st ) == -1 )
|
||||
{
|
||||
if( errno != ENOENT )
|
||||
LOG->Warn( "Couldn't stat %s: %s", Paths[i], strerror(errno) );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !S_ISCHR( st.st_mode ) )
|
||||
{
|
||||
LOG->Warn( "Ignoring %s: not a character device", Paths[i] );
|
||||
continue;
|
||||
}
|
||||
|
||||
pair<int,int> dev( major(st.st_rdev), minor(st.st_rdev) );
|
||||
if( devices.find(dev) != devices.end() )
|
||||
continue; /* dupe */
|
||||
devices.insert( dev );
|
||||
|
||||
fds[i] = open( Paths[i], O_RDONLY );
|
||||
|
||||
if(fds[i] != -1)
|
||||
{
|
||||
char szName[1024];
|
||||
ZERO( szName );
|
||||
if( ioctl(fds[i], JSIOCGNAME(sizeof(szName)), szName) < 0 )
|
||||
m_sDescription[i] = ssprintf( "Unknown joystick at %s", Paths[i] );
|
||||
else
|
||||
m_sDescription[i] = szName;
|
||||
|
||||
LOG->Info("Opened %s", Paths[i]);
|
||||
bFoundAnyJoysticks = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_bShutdown = false;
|
||||
|
||||
if( bFoundAnyJoysticks )
|
||||
{
|
||||
m_InputThread.SetName( "Joystick thread" );
|
||||
m_InputThread.Create( InputThread_Start, this );
|
||||
InputHandler_Linux_Event::m_bFoundAnyJoysticks = true;
|
||||
}
|
||||
}
|
||||
|
||||
InputHandler_Linux_Joystick::~InputHandler_Linux_Joystick()
|
||||
{
|
||||
if( m_InputThread.IsCreated() )
|
||||
{
|
||||
m_bShutdown = true;
|
||||
LOG->Trace( "Shutting down joystick thread ..." );
|
||||
m_InputThread.Wait();
|
||||
LOG->Trace( "Joystick thread shut down." );
|
||||
}
|
||||
|
||||
for(int i = 0; i < NUM_JOYSTICKS; ++i)
|
||||
if(fds[i] != -1) close(fds[i]);
|
||||
}
|
||||
|
||||
int InputHandler_Linux_Joystick::InputThread_Start( void *p )
|
||||
{
|
||||
((InputHandler_Linux_Joystick *) p)->InputThread();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InputHandler_Linux_Joystick::InputThread()
|
||||
{
|
||||
while( !m_bShutdown )
|
||||
{
|
||||
fd_set fdset;
|
||||
FD_ZERO(&fdset);
|
||||
int max_fd = -1;
|
||||
|
||||
for(int i = 0; i < NUM_JOYSTICKS; ++i)
|
||||
{
|
||||
if (fds[i] < 0)
|
||||
continue;
|
||||
|
||||
FD_SET(fds[i], &fdset);
|
||||
max_fd = max(max_fd, fds[i]);
|
||||
}
|
||||
|
||||
if(max_fd == -1)
|
||||
break;
|
||||
|
||||
struct timeval zero = {0,100000};
|
||||
if( select(max_fd+1, &fdset, NULL, NULL, &zero) <= 0 )
|
||||
continue;
|
||||
RageTimer now;
|
||||
|
||||
printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n");
|
||||
for(int i = 0; i < NUM_JOYSTICKS; ++i)
|
||||
{
|
||||
if( fds[i] == -1 )
|
||||
continue;
|
||||
|
||||
if(!FD_ISSET(fds[i], &fdset))
|
||||
continue;
|
||||
|
||||
js_event event;
|
||||
int ret = read(fds[i], &event, sizeof(event));
|
||||
if(ret != sizeof(event))
|
||||
{
|
||||
LOG->Warn("Unexpected packet (size %i != %i) from joystick %i; disabled", ret, (int)sizeof(event), i);
|
||||
close(fds[i]);
|
||||
fds[i] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
InputDevice id = InputDevice(DEVICE_JOY1 + i);
|
||||
|
||||
event.type &= ~JS_EVENT_INIT;
|
||||
switch (event.type) {
|
||||
case JS_EVENT_BUTTON: {
|
||||
int iNum = event.number;
|
||||
// In 2.6.11 using an EMS USB2, the event number for P1 Tri (the first button)
|
||||
// is being reported as 32 instead of 0. Correct for this.
|
||||
wrap( iNum, 32 ); // max number of joystick buttons. Make this a constant?
|
||||
ButtonPressed( DeviceInput(id, enum_add2(JOY_BUTTON_1, iNum), event.value, now) );
|
||||
break;
|
||||
}
|
||||
|
||||
case JS_EVENT_AXIS: {
|
||||
DeviceButton neg = enum_add2(JOY_LEFT, 2*event.number);
|
||||
DeviceButton pos = enum_add2(JOY_RIGHT, 2*event.number);
|
||||
float l = SCALE( int(event.value), 0.0f, 32767, 0.0f, 1.0f );
|
||||
ButtonPressed( DeviceInput(id, neg, max(-l,0), now) );
|
||||
ButtonPressed( DeviceInput(id, pos, max(+l,0), now) );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOG->Warn("Unexpected packet (type %i) from joystick %i; disabled", event.type, i);
|
||||
close(fds[i]);
|
||||
fds[i] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
InputHandler::UpdateTimer();
|
||||
}
|
||||
|
||||
void InputHandler_Linux_Joystick::GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevicesOut )
|
||||
{
|
||||
for(int i = 0; i < NUM_JOYSTICKS; ++i)
|
||||
{
|
||||
if (fds[i] < 0)
|
||||
continue;
|
||||
|
||||
vDevicesOut.push_back( InputDeviceInfo(InputDevice(DEVICE_JOY1+i), m_sDescription[i]) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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 "global.h"
|
||||
#include "InputHandler_Linux_Joystick.h"
|
||||
#include "InputHandler_Linux_Event.h" // for m_bFoundAnyJoysticks
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <linux/joystick.h>
|
||||
|
||||
#include <set>
|
||||
|
||||
REGISTER_INPUT_HANDLER_CLASS2( Joystick, Linux_Joystick );
|
||||
|
||||
static const char *Paths[InputHandler_Linux_Joystick::NUM_JOYSTICKS] =
|
||||
{
|
||||
"/dev/js0",
|
||||
"/dev/js1",
|
||||
"/dev/input/js0",
|
||||
"/dev/input/js1",
|
||||
};
|
||||
|
||||
InputHandler_Linux_Joystick::InputHandler_Linux_Joystick()
|
||||
{
|
||||
LOG->Trace( "InputHandler_Linux_Joystick::InputHandler_Linux_Joystick" );
|
||||
for(int i = 0; i < NUM_JOYSTICKS; ++i)
|
||||
fds[i] = -1;
|
||||
|
||||
if( InputHandler_Linux_Event::m_bFoundAnyJoysticks )
|
||||
{
|
||||
LOG->Trace( "InputHandler_Linux_Joystick disabled (joystick driver already loaded)" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* We check both eg. /dev/js0 and /dev/input/js0. If both exist, they're probably
|
||||
* the same device; keep track of device IDs so we don't open the same joystick
|
||||
* twice. */
|
||||
set< pair<int,int> > devices;
|
||||
bool bFoundAnyJoysticks = false;
|
||||
|
||||
for(int i = 0; i < NUM_JOYSTICKS; ++i)
|
||||
{
|
||||
struct stat st;
|
||||
if( stat( Paths[i], &st ) == -1 )
|
||||
{
|
||||
if( errno != ENOENT )
|
||||
LOG->Warn( "Couldn't stat %s: %s", Paths[i], strerror(errno) );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !S_ISCHR( st.st_mode ) )
|
||||
{
|
||||
LOG->Warn( "Ignoring %s: not a character device", Paths[i] );
|
||||
continue;
|
||||
}
|
||||
|
||||
pair<int,int> dev( major(st.st_rdev), minor(st.st_rdev) );
|
||||
if( devices.find(dev) != devices.end() )
|
||||
continue; /* dupe */
|
||||
devices.insert( dev );
|
||||
|
||||
fds[i] = open( Paths[i], O_RDONLY );
|
||||
|
||||
if(fds[i] != -1)
|
||||
{
|
||||
char szName[1024];
|
||||
ZERO( szName );
|
||||
if( ioctl(fds[i], JSIOCGNAME(sizeof(szName)), szName) < 0 )
|
||||
m_sDescription[i] = ssprintf( "Unknown joystick at %s", Paths[i] );
|
||||
else
|
||||
m_sDescription[i] = szName;
|
||||
|
||||
LOG->Info("Opened %s", Paths[i]);
|
||||
bFoundAnyJoysticks = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_bShutdown = false;
|
||||
|
||||
if( bFoundAnyJoysticks )
|
||||
{
|
||||
m_InputThread.SetName( "Joystick thread" );
|
||||
m_InputThread.Create( InputThread_Start, this );
|
||||
InputHandler_Linux_Event::m_bFoundAnyJoysticks = true;
|
||||
}
|
||||
}
|
||||
|
||||
InputHandler_Linux_Joystick::~InputHandler_Linux_Joystick()
|
||||
{
|
||||
if( m_InputThread.IsCreated() )
|
||||
{
|
||||
m_bShutdown = true;
|
||||
LOG->Trace( "Shutting down joystick thread ..." );
|
||||
m_InputThread.Wait();
|
||||
LOG->Trace( "Joystick thread shut down." );
|
||||
}
|
||||
|
||||
for(int i = 0; i < NUM_JOYSTICKS; ++i)
|
||||
if(fds[i] != -1) close(fds[i]);
|
||||
}
|
||||
|
||||
int InputHandler_Linux_Joystick::InputThread_Start( void *p )
|
||||
{
|
||||
((InputHandler_Linux_Joystick *) p)->InputThread();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InputHandler_Linux_Joystick::InputThread()
|
||||
{
|
||||
while( !m_bShutdown )
|
||||
{
|
||||
fd_set fdset;
|
||||
FD_ZERO(&fdset);
|
||||
int max_fd = -1;
|
||||
|
||||
for(int i = 0; i < NUM_JOYSTICKS; ++i)
|
||||
{
|
||||
if (fds[i] < 0)
|
||||
continue;
|
||||
|
||||
FD_SET(fds[i], &fdset);
|
||||
max_fd = max(max_fd, fds[i]);
|
||||
}
|
||||
|
||||
if(max_fd == -1)
|
||||
break;
|
||||
|
||||
struct timeval zero = {0,100000};
|
||||
if( select(max_fd+1, &fdset, NULL, NULL, &zero) <= 0 )
|
||||
continue;
|
||||
RageTimer now;
|
||||
|
||||
printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n");
|
||||
for(int i = 0; i < NUM_JOYSTICKS; ++i)
|
||||
{
|
||||
if( fds[i] == -1 )
|
||||
continue;
|
||||
|
||||
if(!FD_ISSET(fds[i], &fdset))
|
||||
continue;
|
||||
|
||||
js_event event;
|
||||
int ret = read(fds[i], &event, sizeof(event));
|
||||
if(ret != sizeof(event))
|
||||
{
|
||||
LOG->Warn("Unexpected packet (size %i != %i) from joystick %i; disabled", ret, (int)sizeof(event), i);
|
||||
close(fds[i]);
|
||||
fds[i] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
InputDevice id = InputDevice(DEVICE_JOY1 + i);
|
||||
|
||||
event.type &= ~JS_EVENT_INIT;
|
||||
switch (event.type) {
|
||||
case JS_EVENT_BUTTON: {
|
||||
int iNum = event.number;
|
||||
// In 2.6.11 using an EMS USB2, the event number for P1 Tri (the first button)
|
||||
// is being reported as 32 instead of 0. Correct for this.
|
||||
wrap( iNum, 32 ); // max number of joystick buttons. Make this a constant?
|
||||
ButtonPressed( DeviceInput(id, enum_add2(JOY_BUTTON_1, iNum), event.value, now) );
|
||||
break;
|
||||
}
|
||||
|
||||
case JS_EVENT_AXIS: {
|
||||
DeviceButton neg = enum_add2(JOY_LEFT, 2*event.number);
|
||||
DeviceButton pos = enum_add2(JOY_RIGHT, 2*event.number);
|
||||
float l = SCALE( int(event.value), 0.0f, 32767, 0.0f, 1.0f );
|
||||
ButtonPressed( DeviceInput(id, neg, max(-l,0), now) );
|
||||
ButtonPressed( DeviceInput(id, pos, max(+l,0), now) );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOG->Warn("Unexpected packet (type %i) from joystick %i; disabled", event.type, i);
|
||||
close(fds[i]);
|
||||
fds[i] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
InputHandler::UpdateTimer();
|
||||
}
|
||||
|
||||
void InputHandler_Linux_Joystick::GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevicesOut )
|
||||
{
|
||||
for(int i = 0; i < NUM_JOYSTICKS; ++i)
|
||||
{
|
||||
if (fds[i] < 0)
|
||||
continue;
|
||||
|
||||
vDevicesOut.push_back( InputDeviceInfo(InputDevice(DEVICE_JOY1+i), m_sDescription[i]) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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.
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,392 +1,392 @@
|
||||
#include "global.h"
|
||||
#include "MemoryCardDriverThreaded_Linux.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageTimer.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
bool MemoryCardDriverThreaded_Linux::TestWrite( UsbStorageDevice* pDevice )
|
||||
{
|
||||
if( access(pDevice->sOsMountDir, W_OK) == -1 )
|
||||
{
|
||||
pDevice->SetError( "TestFailed" );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ExecuteCommand( const RString &sCommand )
|
||||
{
|
||||
LOG->Trace( "executing '%s'", sCommand.c_str() );
|
||||
int ret = system(sCommand);
|
||||
LOG->Trace( "done executing '%s'", sCommand.c_str() );
|
||||
if( ret != 0 )
|
||||
{
|
||||
RString sError = ssprintf("failed to execute '%s' with error %d", sCommand.c_str(), ret);
|
||||
if( ret == -1 )
|
||||
sError += ssprintf(": %s", sCommand.c_str());
|
||||
LOG->Warn( "%s", sError.c_str() );
|
||||
}
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
static bool ReadFile( const RString &sPath, RString &sBuf )
|
||||
{
|
||||
sBuf.clear();
|
||||
|
||||
int fd = open( sPath, O_RDONLY );
|
||||
if( fd == -1 )
|
||||
{
|
||||
LOG->Warn( "Error opening \"%s\": %s", sPath.c_str(), strerror(errno) );
|
||||
return false;
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
char buf[1024];
|
||||
int iGot = read( fd, buf, sizeof(buf) );
|
||||
if( iGot == -1 )
|
||||
{
|
||||
close(fd);
|
||||
LOG->Warn( "Error reading \"%s\": %s", sPath.c_str(), strerror(errno) );
|
||||
return false;
|
||||
}
|
||||
|
||||
sBuf.append( buf, iGot );
|
||||
if( iGot < (int) sizeof(buf) )
|
||||
break;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void GetFileList( const RString &sPath, vector<RString> &out )
|
||||
{
|
||||
out.clear();
|
||||
|
||||
DIR *dp = opendir( sPath );
|
||||
if( dp == NULL )
|
||||
return; // false; // XXX warn
|
||||
|
||||
while( const struct dirent *ent = readdir(dp) )
|
||||
out.push_back( ent->d_name );
|
||||
|
||||
closedir( dp );
|
||||
}
|
||||
|
||||
bool MemoryCardDriverThreaded_Linux::USBStorageDevicesChanged()
|
||||
{
|
||||
RString sThisDevices;
|
||||
|
||||
/* If a device is removed and reinserted, the inode of the /sys/block entry
|
||||
* will change. */
|
||||
RString sDevicePath = "/sys/block/";
|
||||
|
||||
vector<RString> asDevices;
|
||||
GetFileList( sDevicePath, asDevices );
|
||||
|
||||
for( unsigned i = 0; i < asDevices.size(); ++i )
|
||||
{
|
||||
struct stat buf;
|
||||
if( stat( sDevicePath + asDevices[i], &buf ) == -1 )
|
||||
continue; // XXX warn
|
||||
|
||||
sThisDevices += ssprintf( "%i,", (int) buf.st_ino );
|
||||
}
|
||||
|
||||
bool bChanged = sThisDevices != m_sLastDevices;
|
||||
m_sLastDevices = sThisDevices;
|
||||
if( bChanged )
|
||||
LOG->Trace( "Change in USB storage devices detected." );
|
||||
return bChanged;
|
||||
}
|
||||
|
||||
void MemoryCardDriverThreaded_Linux::GetUSBStorageDevices( vector<UsbStorageDevice>& vDevicesOut )
|
||||
{
|
||||
LOG->Trace( "GetUSBStorageDevices" );
|
||||
|
||||
vDevicesOut.clear();
|
||||
|
||||
{
|
||||
vector<RString> asDevices;
|
||||
RString sBlockDevicePath = "/sys/block/";
|
||||
GetFileList( sBlockDevicePath, asDevices );
|
||||
|
||||
for( unsigned i = 0; i < asDevices.size(); ++i )
|
||||
{
|
||||
const RString &sDevice = asDevices[i];
|
||||
if( sDevice == "." || sDevice == ".." )
|
||||
continue;
|
||||
|
||||
UsbStorageDevice usbd;
|
||||
|
||||
RString sPath = sBlockDevicePath + sDevice + "/";
|
||||
usbd.sSysPath = sPath;
|
||||
|
||||
/* Ignore non-removable devices. */
|
||||
RString sBuf;
|
||||
if( !ReadFile( sPath + "removable", sBuf ) )
|
||||
continue; // already warned
|
||||
if( atoi(sBuf) != 1 )
|
||||
continue;
|
||||
|
||||
/*
|
||||
* The kernel isn't exposing all of /sys atomically, so we end up missing
|
||||
* the partition due to it not being shown yet. It won't show up until the
|
||||
* kernel has scanned the partition table, which can take a variable amount
|
||||
* of time, sometimes over a second. Watch for the "queue" sysfs directory,
|
||||
* which is created after this, to tell when partition directories are created.
|
||||
*/
|
||||
RageTimer WaitUntil;
|
||||
WaitUntil += 5;
|
||||
RString sQueueFilePath = usbd.sSysPath + "queue";
|
||||
while(1)
|
||||
{
|
||||
if( WaitUntil.Ago() >= 0 )
|
||||
{
|
||||
LOG->Warn( "Timed out waiting for %s", sQueueFilePath.c_str() );
|
||||
break;
|
||||
}
|
||||
|
||||
if( access(usbd.sSysPath, F_OK) == -1 )
|
||||
{
|
||||
LOG->Warn( "Block directory %s went away while we were waiting for %s",
|
||||
usbd.sSysPath.c_str(), sQueueFilePath.c_str() );
|
||||
break;
|
||||
}
|
||||
|
||||
if( access(sQueueFilePath, F_OK) != -1 )
|
||||
break;
|
||||
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
/* If the first partition device exists, eg. /sys/block/uba/uba1, use it. */
|
||||
if( access(usbd.sSysPath + sDevice + "1", F_OK) != -1 )
|
||||
{
|
||||
LOG->Trace("OK");
|
||||
usbd.sDevice = "/dev/" + sDevice + "1";
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG->Trace("error %s", strerror(errno));
|
||||
usbd.sDevice = "/dev/" + sDevice;
|
||||
}
|
||||
|
||||
/*
|
||||
* sPath/device should be a symlink to the actual device. For USB
|
||||
* devices, it looks like this:
|
||||
*
|
||||
* device -> ../../devices/pci0000:00/0000:00:02.1/usb2/2-1/2-1:1.0
|
||||
*
|
||||
* "2-1" is "bus-port".
|
||||
*/
|
||||
char szLink[256];
|
||||
int iRet = readlink( sPath + "device", szLink, sizeof(szLink) );
|
||||
if( iRet == -1 )
|
||||
{
|
||||
LOG->Warn( "readlink(\"%s\"): %s", (sPath + "device").c_str(), strerror(errno) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* The full path looks like
|
||||
*
|
||||
* ../../devices/pci0000:00/0000:00:02.1/usb2/2-2/2-2.1/2-2.1:1.0
|
||||
*
|
||||
* In newer kernels, it looks like:
|
||||
*
|
||||
* ../../../3-2.1:1.0
|
||||
*
|
||||
* Each path element refers to a new hop in the chain.
|
||||
* "usb2" = second USB host
|
||||
* 2- second USB host,
|
||||
* -2 port 1 on the host,
|
||||
* .1 port 1 on an attached hub
|
||||
* .2 ... port 2 on the next hub ...
|
||||
*
|
||||
* We want the bus number and the port of the last hop. The level is
|
||||
* the number of hops.
|
||||
*/
|
||||
szLink[iRet] = 0;
|
||||
vector<RString> asBits;
|
||||
split( szLink, "/", asBits );
|
||||
|
||||
RString sHostPort = asBits[asBits.size()-1];
|
||||
if( !sHostPort.empty() )
|
||||
{
|
||||
/* Strip off the endpoint information after the colon. */
|
||||
size_t pos = sHostPort.find(':');
|
||||
if( pos != string::npos )
|
||||
sHostPort.erase( pos );
|
||||
|
||||
/* sHostPort is eg. 2-2.1. */
|
||||
sHostPort.Replace( "-", "." );
|
||||
asBits.clear();
|
||||
split( sHostPort, ".", asBits );
|
||||
if( asBits.size() > 1 )
|
||||
{
|
||||
usbd.iBus = atoi( asBits[0] );
|
||||
usbd.iPort = atoi( asBits[asBits.size()-1] );
|
||||
usbd.iLevel = asBits.size() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( ReadFile( sPath + "device/../idVendor", sBuf ) )
|
||||
sscanf( sBuf, "%x", &usbd.idVendor );
|
||||
|
||||
if( ReadFile( sPath + "device/../idProduct", sBuf ) )
|
||||
sscanf( sBuf, "%x", &usbd.idProduct );
|
||||
|
||||
if( ReadFile( sPath + "device/../serial", sBuf ) )
|
||||
{
|
||||
usbd.sSerial = sBuf;
|
||||
TrimRight( usbd.sSerial );
|
||||
}
|
||||
if( ReadFile( sPath + "device/../product", sBuf ) )
|
||||
{
|
||||
usbd.sProduct = sBuf;
|
||||
TrimRight( usbd.sProduct );
|
||||
}
|
||||
if( ReadFile( sPath + "device/../manufacturer", sBuf ) )
|
||||
{
|
||||
usbd.sVendor = sBuf;
|
||||
TrimRight( usbd.sVendor );
|
||||
}
|
||||
|
||||
vDevicesOut.push_back( usbd );
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Find where each device is mounted. Output looks like:
|
||||
|
||||
// /dev/sda1 /mnt/flash1 auto noauto,owner 0 0
|
||||
// /dev/sdb1 /mnt/flash2 auto noauto,owner 0 0
|
||||
// /dev/sdc1 /mnt/flash3 auto noauto,owner 0 0
|
||||
|
||||
RString fn = "/rootfs/etc/fstab";
|
||||
RageFile f;
|
||||
if( !f.Open(fn) )
|
||||
{
|
||||
LOG->Warn( "can't open '%s': %s", fn.c_str(), f.GetError().c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
RString sLine;
|
||||
while( !f.AtEOF() )
|
||||
{
|
||||
switch( f.GetLine(sLine) )
|
||||
{
|
||||
case 0: continue; /* eof */
|
||||
case -1:
|
||||
LOG->Warn( "error reading '%s': %s", fn.c_str(), f.GetError().c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
char szScsiDevice[1024];
|
||||
char szMountPoint[1024];
|
||||
int iRet = sscanf( sLine, "%s %s", szScsiDevice, szMountPoint );
|
||||
if( iRet != 2 )
|
||||
continue; // don't process this line
|
||||
|
||||
|
||||
RString sMountPoint = szMountPoint;
|
||||
TrimLeft( sMountPoint );
|
||||
TrimRight( sMountPoint );
|
||||
|
||||
// search for the mountpoint corresponding to the device
|
||||
for( unsigned i=0; i<vDevicesOut.size(); i++ )
|
||||
{
|
||||
UsbStorageDevice& usbd = vDevicesOut[i];
|
||||
if( usbd.sDevice == szScsiDevice ) // found our match
|
||||
{
|
||||
usbd.sOsMountDir = sMountPoint;
|
||||
break; // stop looking for a match
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( unsigned i=0; i<vDevicesOut.size(); i++ )
|
||||
{
|
||||
UsbStorageDevice& usbd = vDevicesOut[i];
|
||||
LOG->Trace( " sDevice: %s, iBus: %d, iLevel: %d, iPort: %d, id: %04X:%04X, Vendor: '%s', Product: '%s', sSerial: \"%s\", sOsMountDir: %s",
|
||||
usbd.sDevice.c_str(), usbd.iBus, usbd.iLevel, usbd.iPort, usbd.idVendor, usbd.idProduct, usbd.sVendor.c_str(),
|
||||
usbd.sProduct.c_str(), usbd.sSerial.c_str(), usbd.sOsMountDir.c_str() );
|
||||
}
|
||||
|
||||
/* Remove any devices that we couldn't find a mountpoint for. */
|
||||
for( unsigned i=0; i<vDevicesOut.size(); i++ )
|
||||
{
|
||||
UsbStorageDevice& usbd = vDevicesOut[i];
|
||||
if( usbd.sOsMountDir.empty() )
|
||||
{
|
||||
LOG->Trace( "Ignoring %s (couldn't find in /etc/fstab)", usbd.sDevice.c_str() );
|
||||
|
||||
vDevicesOut.erase( vDevicesOut.begin()+i );
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
LOG->Trace( "Done with GetUSBStorageDevices" );
|
||||
}
|
||||
|
||||
|
||||
bool MemoryCardDriverThreaded_Linux::Mount( UsbStorageDevice* pDevice )
|
||||
{
|
||||
ASSERT( !pDevice->sDevice.empty() );
|
||||
|
||||
RString sCommand = "mount " + pDevice->sDevice;
|
||||
bool bMountedSuccessfully = ExecuteCommand( sCommand );
|
||||
|
||||
return bMountedSuccessfully;
|
||||
}
|
||||
|
||||
void MemoryCardDriverThreaded_Linux::Unmount( UsbStorageDevice* pDevice )
|
||||
{
|
||||
if( pDevice->sDevice.empty() )
|
||||
return;
|
||||
|
||||
/* Use umount -l, so we unmount the device even if it's in use. Open
|
||||
* files remain usable, and the device (eg. /dev/sda) won't be reused
|
||||
* by new devices until those are closed. Without this, if something
|
||||
* causes the device to not unmount here, we'll never unmount it; that
|
||||
* causes a device name leak, eventually running us out of mountpoints. */
|
||||
RString sCommand = "sync; umount -l \"" + pDevice->sDevice + "\"";
|
||||
ExecuteCommand( sCommand );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-2005 Chris Danford, Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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 "global.h"
|
||||
#include "MemoryCardDriverThreaded_Linux.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageTimer.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
bool MemoryCardDriverThreaded_Linux::TestWrite( UsbStorageDevice* pDevice )
|
||||
{
|
||||
if( access(pDevice->sOsMountDir, W_OK) == -1 )
|
||||
{
|
||||
pDevice->SetError( "TestFailed" );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ExecuteCommand( const RString &sCommand )
|
||||
{
|
||||
LOG->Trace( "executing '%s'", sCommand.c_str() );
|
||||
int ret = system(sCommand);
|
||||
LOG->Trace( "done executing '%s'", sCommand.c_str() );
|
||||
if( ret != 0 )
|
||||
{
|
||||
RString sError = ssprintf("failed to execute '%s' with error %d", sCommand.c_str(), ret);
|
||||
if( ret == -1 )
|
||||
sError += ssprintf(": %s", sCommand.c_str());
|
||||
LOG->Warn( "%s", sError.c_str() );
|
||||
}
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
static bool ReadFile( const RString &sPath, RString &sBuf )
|
||||
{
|
||||
sBuf.clear();
|
||||
|
||||
int fd = open( sPath, O_RDONLY );
|
||||
if( fd == -1 )
|
||||
{
|
||||
LOG->Warn( "Error opening \"%s\": %s", sPath.c_str(), strerror(errno) );
|
||||
return false;
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
char buf[1024];
|
||||
int iGot = read( fd, buf, sizeof(buf) );
|
||||
if( iGot == -1 )
|
||||
{
|
||||
close(fd);
|
||||
LOG->Warn( "Error reading \"%s\": %s", sPath.c_str(), strerror(errno) );
|
||||
return false;
|
||||
}
|
||||
|
||||
sBuf.append( buf, iGot );
|
||||
if( iGot < (int) sizeof(buf) )
|
||||
break;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void GetFileList( const RString &sPath, vector<RString> &out )
|
||||
{
|
||||
out.clear();
|
||||
|
||||
DIR *dp = opendir( sPath );
|
||||
if( dp == NULL )
|
||||
return; // false; // XXX warn
|
||||
|
||||
while( const struct dirent *ent = readdir(dp) )
|
||||
out.push_back( ent->d_name );
|
||||
|
||||
closedir( dp );
|
||||
}
|
||||
|
||||
bool MemoryCardDriverThreaded_Linux::USBStorageDevicesChanged()
|
||||
{
|
||||
RString sThisDevices;
|
||||
|
||||
/* If a device is removed and reinserted, the inode of the /sys/block entry
|
||||
* will change. */
|
||||
RString sDevicePath = "/sys/block/";
|
||||
|
||||
vector<RString> asDevices;
|
||||
GetFileList( sDevicePath, asDevices );
|
||||
|
||||
for( unsigned i = 0; i < asDevices.size(); ++i )
|
||||
{
|
||||
struct stat buf;
|
||||
if( stat( sDevicePath + asDevices[i], &buf ) == -1 )
|
||||
continue; // XXX warn
|
||||
|
||||
sThisDevices += ssprintf( "%i,", (int) buf.st_ino );
|
||||
}
|
||||
|
||||
bool bChanged = sThisDevices != m_sLastDevices;
|
||||
m_sLastDevices = sThisDevices;
|
||||
if( bChanged )
|
||||
LOG->Trace( "Change in USB storage devices detected." );
|
||||
return bChanged;
|
||||
}
|
||||
|
||||
void MemoryCardDriverThreaded_Linux::GetUSBStorageDevices( vector<UsbStorageDevice>& vDevicesOut )
|
||||
{
|
||||
LOG->Trace( "GetUSBStorageDevices" );
|
||||
|
||||
vDevicesOut.clear();
|
||||
|
||||
{
|
||||
vector<RString> asDevices;
|
||||
RString sBlockDevicePath = "/sys/block/";
|
||||
GetFileList( sBlockDevicePath, asDevices );
|
||||
|
||||
for( unsigned i = 0; i < asDevices.size(); ++i )
|
||||
{
|
||||
const RString &sDevice = asDevices[i];
|
||||
if( sDevice == "." || sDevice == ".." )
|
||||
continue;
|
||||
|
||||
UsbStorageDevice usbd;
|
||||
|
||||
RString sPath = sBlockDevicePath + sDevice + "/";
|
||||
usbd.sSysPath = sPath;
|
||||
|
||||
/* Ignore non-removable devices. */
|
||||
RString sBuf;
|
||||
if( !ReadFile( sPath + "removable", sBuf ) )
|
||||
continue; // already warned
|
||||
if( atoi(sBuf) != 1 )
|
||||
continue;
|
||||
|
||||
/*
|
||||
* The kernel isn't exposing all of /sys atomically, so we end up missing
|
||||
* the partition due to it not being shown yet. It won't show up until the
|
||||
* kernel has scanned the partition table, which can take a variable amount
|
||||
* of time, sometimes over a second. Watch for the "queue" sysfs directory,
|
||||
* which is created after this, to tell when partition directories are created.
|
||||
*/
|
||||
RageTimer WaitUntil;
|
||||
WaitUntil += 5;
|
||||
RString sQueueFilePath = usbd.sSysPath + "queue";
|
||||
while(1)
|
||||
{
|
||||
if( WaitUntil.Ago() >= 0 )
|
||||
{
|
||||
LOG->Warn( "Timed out waiting for %s", sQueueFilePath.c_str() );
|
||||
break;
|
||||
}
|
||||
|
||||
if( access(usbd.sSysPath, F_OK) == -1 )
|
||||
{
|
||||
LOG->Warn( "Block directory %s went away while we were waiting for %s",
|
||||
usbd.sSysPath.c_str(), sQueueFilePath.c_str() );
|
||||
break;
|
||||
}
|
||||
|
||||
if( access(sQueueFilePath, F_OK) != -1 )
|
||||
break;
|
||||
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
/* If the first partition device exists, eg. /sys/block/uba/uba1, use it. */
|
||||
if( access(usbd.sSysPath + sDevice + "1", F_OK) != -1 )
|
||||
{
|
||||
LOG->Trace("OK");
|
||||
usbd.sDevice = "/dev/" + sDevice + "1";
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG->Trace("error %s", strerror(errno));
|
||||
usbd.sDevice = "/dev/" + sDevice;
|
||||
}
|
||||
|
||||
/*
|
||||
* sPath/device should be a symlink to the actual device. For USB
|
||||
* devices, it looks like this:
|
||||
*
|
||||
* device -> ../../devices/pci0000:00/0000:00:02.1/usb2/2-1/2-1:1.0
|
||||
*
|
||||
* "2-1" is "bus-port".
|
||||
*/
|
||||
char szLink[256];
|
||||
int iRet = readlink( sPath + "device", szLink, sizeof(szLink) );
|
||||
if( iRet == -1 )
|
||||
{
|
||||
LOG->Warn( "readlink(\"%s\"): %s", (sPath + "device").c_str(), strerror(errno) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* The full path looks like
|
||||
*
|
||||
* ../../devices/pci0000:00/0000:00:02.1/usb2/2-2/2-2.1/2-2.1:1.0
|
||||
*
|
||||
* In newer kernels, it looks like:
|
||||
*
|
||||
* ../../../3-2.1:1.0
|
||||
*
|
||||
* Each path element refers to a new hop in the chain.
|
||||
* "usb2" = second USB host
|
||||
* 2- second USB host,
|
||||
* -2 port 1 on the host,
|
||||
* .1 port 1 on an attached hub
|
||||
* .2 ... port 2 on the next hub ...
|
||||
*
|
||||
* We want the bus number and the port of the last hop. The level is
|
||||
* the number of hops.
|
||||
*/
|
||||
szLink[iRet] = 0;
|
||||
vector<RString> asBits;
|
||||
split( szLink, "/", asBits );
|
||||
|
||||
RString sHostPort = asBits[asBits.size()-1];
|
||||
if( !sHostPort.empty() )
|
||||
{
|
||||
/* Strip off the endpoint information after the colon. */
|
||||
size_t pos = sHostPort.find(':');
|
||||
if( pos != string::npos )
|
||||
sHostPort.erase( pos );
|
||||
|
||||
/* sHostPort is eg. 2-2.1. */
|
||||
sHostPort.Replace( "-", "." );
|
||||
asBits.clear();
|
||||
split( sHostPort, ".", asBits );
|
||||
if( asBits.size() > 1 )
|
||||
{
|
||||
usbd.iBus = atoi( asBits[0] );
|
||||
usbd.iPort = atoi( asBits[asBits.size()-1] );
|
||||
usbd.iLevel = asBits.size() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( ReadFile( sPath + "device/../idVendor", sBuf ) )
|
||||
sscanf( sBuf, "%x", &usbd.idVendor );
|
||||
|
||||
if( ReadFile( sPath + "device/../idProduct", sBuf ) )
|
||||
sscanf( sBuf, "%x", &usbd.idProduct );
|
||||
|
||||
if( ReadFile( sPath + "device/../serial", sBuf ) )
|
||||
{
|
||||
usbd.sSerial = sBuf;
|
||||
TrimRight( usbd.sSerial );
|
||||
}
|
||||
if( ReadFile( sPath + "device/../product", sBuf ) )
|
||||
{
|
||||
usbd.sProduct = sBuf;
|
||||
TrimRight( usbd.sProduct );
|
||||
}
|
||||
if( ReadFile( sPath + "device/../manufacturer", sBuf ) )
|
||||
{
|
||||
usbd.sVendor = sBuf;
|
||||
TrimRight( usbd.sVendor );
|
||||
}
|
||||
|
||||
vDevicesOut.push_back( usbd );
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Find where each device is mounted. Output looks like:
|
||||
|
||||
// /dev/sda1 /mnt/flash1 auto noauto,owner 0 0
|
||||
// /dev/sdb1 /mnt/flash2 auto noauto,owner 0 0
|
||||
// /dev/sdc1 /mnt/flash3 auto noauto,owner 0 0
|
||||
|
||||
RString fn = "/rootfs/etc/fstab";
|
||||
RageFile f;
|
||||
if( !f.Open(fn) )
|
||||
{
|
||||
LOG->Warn( "can't open '%s': %s", fn.c_str(), f.GetError().c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
RString sLine;
|
||||
while( !f.AtEOF() )
|
||||
{
|
||||
switch( f.GetLine(sLine) )
|
||||
{
|
||||
case 0: continue; /* eof */
|
||||
case -1:
|
||||
LOG->Warn( "error reading '%s': %s", fn.c_str(), f.GetError().c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
char szScsiDevice[1024];
|
||||
char szMountPoint[1024];
|
||||
int iRet = sscanf( sLine, "%s %s", szScsiDevice, szMountPoint );
|
||||
if( iRet != 2 )
|
||||
continue; // don't process this line
|
||||
|
||||
|
||||
RString sMountPoint = szMountPoint;
|
||||
TrimLeft( sMountPoint );
|
||||
TrimRight( sMountPoint );
|
||||
|
||||
// search for the mountpoint corresponding to the device
|
||||
for( unsigned i=0; i<vDevicesOut.size(); i++ )
|
||||
{
|
||||
UsbStorageDevice& usbd = vDevicesOut[i];
|
||||
if( usbd.sDevice == szScsiDevice ) // found our match
|
||||
{
|
||||
usbd.sOsMountDir = sMountPoint;
|
||||
break; // stop looking for a match
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( unsigned i=0; i<vDevicesOut.size(); i++ )
|
||||
{
|
||||
UsbStorageDevice& usbd = vDevicesOut[i];
|
||||
LOG->Trace( " sDevice: %s, iBus: %d, iLevel: %d, iPort: %d, id: %04X:%04X, Vendor: '%s', Product: '%s', sSerial: \"%s\", sOsMountDir: %s",
|
||||
usbd.sDevice.c_str(), usbd.iBus, usbd.iLevel, usbd.iPort, usbd.idVendor, usbd.idProduct, usbd.sVendor.c_str(),
|
||||
usbd.sProduct.c_str(), usbd.sSerial.c_str(), usbd.sOsMountDir.c_str() );
|
||||
}
|
||||
|
||||
/* Remove any devices that we couldn't find a mountpoint for. */
|
||||
for( unsigned i=0; i<vDevicesOut.size(); i++ )
|
||||
{
|
||||
UsbStorageDevice& usbd = vDevicesOut[i];
|
||||
if( usbd.sOsMountDir.empty() )
|
||||
{
|
||||
LOG->Trace( "Ignoring %s (couldn't find in /etc/fstab)", usbd.sDevice.c_str() );
|
||||
|
||||
vDevicesOut.erase( vDevicesOut.begin()+i );
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
LOG->Trace( "Done with GetUSBStorageDevices" );
|
||||
}
|
||||
|
||||
|
||||
bool MemoryCardDriverThreaded_Linux::Mount( UsbStorageDevice* pDevice )
|
||||
{
|
||||
ASSERT( !pDevice->sDevice.empty() );
|
||||
|
||||
RString sCommand = "mount " + pDevice->sDevice;
|
||||
bool bMountedSuccessfully = ExecuteCommand( sCommand );
|
||||
|
||||
return bMountedSuccessfully;
|
||||
}
|
||||
|
||||
void MemoryCardDriverThreaded_Linux::Unmount( UsbStorageDevice* pDevice )
|
||||
{
|
||||
if( pDevice->sDevice.empty() )
|
||||
return;
|
||||
|
||||
/* Use umount -l, so we unmount the device even if it's in use. Open
|
||||
* files remain usable, and the device (eg. /dev/sda) won't be reused
|
||||
* by new devices until those are closed. Without this, if something
|
||||
* causes the device to not unmount here, we'll never unmount it; that
|
||||
* causes a device name leak, eventually running us out of mountpoints. */
|
||||
RString sCommand = "sync; umount -l \"" + pDevice->sDevice + "\"";
|
||||
ExecuteCommand( sCommand );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-2005 Chris Danford, Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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.
|
||||
*/
|
||||
|
||||
+3073
-3073
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+272
-272
@@ -1,272 +1,272 @@
|
||||
/*
|
||||
* unbuffered io for ffmpeg system
|
||||
* copyright (c) 2001 Fabrice Bellard
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef AVIO_H
|
||||
#define AVIO_H
|
||||
|
||||
/* output byte stream handling */
|
||||
|
||||
typedef int64_t offset_t;
|
||||
|
||||
/* unbuffered I/O */
|
||||
|
||||
struct URLContext {
|
||||
struct URLProtocol *prot;
|
||||
int flags;
|
||||
int is_streamed; /**< true if streamed (no seek possible), default = false */
|
||||
int max_packet_size; /**< if non zero, the stream is packetized with this max packet size */
|
||||
void *priv_data;
|
||||
#if LIBAVFORMAT_VERSION_INT >= (52<<16)
|
||||
char *filename; /**< specified filename */
|
||||
#else
|
||||
char filename[1]; /**< specified filename */
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct URLContext URLContext;
|
||||
|
||||
typedef struct URLPollEntry {
|
||||
URLContext *handle;
|
||||
int events;
|
||||
int revents;
|
||||
} URLPollEntry;
|
||||
|
||||
#define URL_RDONLY 0
|
||||
#define URL_WRONLY 1
|
||||
#define URL_RDWR 2
|
||||
|
||||
typedef int URLInterruptCB(void);
|
||||
|
||||
int url_open(URLContext **h, const char *filename, int flags);
|
||||
int url_read(URLContext *h, unsigned char *buf, int size);
|
||||
int url_write(URLContext *h, unsigned char *buf, int size);
|
||||
offset_t url_seek(URLContext *h, offset_t pos, int whence);
|
||||
int url_close(URLContext *h);
|
||||
int url_exist(const char *filename);
|
||||
offset_t url_filesize(URLContext *h);
|
||||
|
||||
/**
|
||||
* Return the maximum packet size associated to packetized file
|
||||
* handle. If the file is not packetized (stream like http or file on
|
||||
* disk), then 0 is returned.
|
||||
*
|
||||
* @param h file handle
|
||||
* @return maximum packet size in bytes
|
||||
*/
|
||||
int url_get_max_packet_size(URLContext *h);
|
||||
void url_get_filename(URLContext *h, char *buf, int buf_size);
|
||||
|
||||
/**
|
||||
* the callback is called in blocking functions to test regulary if
|
||||
* asynchronous interruption is needed. AVERROR(EINTR) is returned
|
||||
* in this case by the interrupted function. 'NULL' means no interrupt
|
||||
* callback is given. i
|
||||
*/
|
||||
void url_set_interrupt_cb(URLInterruptCB *interrupt_cb);
|
||||
|
||||
/* not implemented */
|
||||
int url_poll(URLPollEntry *poll_table, int n, int timeout);
|
||||
|
||||
/**
|
||||
* passing this as the "whence" parameter to a seek function causes it to
|
||||
* return the filesize without seeking anywhere, supporting this is optional
|
||||
* if its not supprted then the seek function will return <0
|
||||
*/
|
||||
#define AVSEEK_SIZE 0x10000
|
||||
|
||||
typedef struct URLProtocol {
|
||||
const char *name;
|
||||
int (*url_open)(URLContext *h, const char *filename, int flags);
|
||||
int (*url_read)(URLContext *h, unsigned char *buf, int size);
|
||||
int (*url_write)(URLContext *h, unsigned char *buf, int size);
|
||||
offset_t (*url_seek)(URLContext *h, offset_t pos, int whence);
|
||||
int (*url_close)(URLContext *h);
|
||||
struct URLProtocol *next;
|
||||
} URLProtocol;
|
||||
|
||||
extern URLProtocol *first_protocol;
|
||||
extern URLInterruptCB *url_interrupt_cb;
|
||||
|
||||
int register_protocol(URLProtocol *protocol);
|
||||
|
||||
typedef struct {
|
||||
unsigned char *buffer;
|
||||
int buffer_size;
|
||||
unsigned char *buf_ptr, *buf_end;
|
||||
void *opaque;
|
||||
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);
|
||||
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);
|
||||
offset_t (*seek)(void *opaque, offset_t offset, int whence);
|
||||
offset_t pos; /**< position in the file of the current buffer */
|
||||
int must_flush; /**< true if the next seek should flush */
|
||||
int eof_reached; /**< true if eof reached */
|
||||
int write_flag; /**< true if open for writing */
|
||||
int is_streamed;
|
||||
int max_packet_size;
|
||||
unsigned long checksum;
|
||||
unsigned char *checksum_ptr;
|
||||
unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);
|
||||
int error; ///< contains the error code or 0 if no error happened
|
||||
} ByteIOContext;
|
||||
|
||||
int init_put_byte(ByteIOContext *s,
|
||||
unsigned char *buffer,
|
||||
int buffer_size,
|
||||
int write_flag,
|
||||
void *opaque,
|
||||
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||
offset_t (*seek)(void *opaque, offset_t offset, int whence));
|
||||
|
||||
void put_byte(ByteIOContext *s, int b);
|
||||
void put_buffer(ByteIOContext *s, const unsigned char *buf, int size);
|
||||
void put_le64(ByteIOContext *s, uint64_t val);
|
||||
void put_be64(ByteIOContext *s, uint64_t val);
|
||||
void put_le32(ByteIOContext *s, unsigned int val);
|
||||
void put_be32(ByteIOContext *s, unsigned int val);
|
||||
void put_le24(ByteIOContext *s, unsigned int val);
|
||||
void put_be24(ByteIOContext *s, unsigned int val);
|
||||
void put_le16(ByteIOContext *s, unsigned int val);
|
||||
void put_be16(ByteIOContext *s, unsigned int val);
|
||||
void put_tag(ByteIOContext *s, const char *tag);
|
||||
|
||||
void put_strz(ByteIOContext *s, const char *buf);
|
||||
|
||||
offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence);
|
||||
void url_fskip(ByteIOContext *s, offset_t offset);
|
||||
offset_t url_ftell(ByteIOContext *s);
|
||||
offset_t url_fsize(ByteIOContext *s);
|
||||
int url_feof(ByteIOContext *s);
|
||||
int url_ferror(ByteIOContext *s);
|
||||
|
||||
#define URL_EOF (-1)
|
||||
/** @note return URL_EOF (-1) if EOF */
|
||||
int url_fgetc(ByteIOContext *s);
|
||||
|
||||
/** @warning currently size is limited */
|
||||
#ifdef __GNUC__
|
||||
int url_fprintf(ByteIOContext *s, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
#else
|
||||
int url_fprintf(ByteIOContext *s, const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
/** @note unlike fgets, the EOL character is not returned and a whole
|
||||
line is parsed. return NULL if first char read was EOF */
|
||||
char *url_fgets(ByteIOContext *s, char *buf, int buf_size);
|
||||
|
||||
void put_flush_packet(ByteIOContext *s);
|
||||
|
||||
int get_buffer(ByteIOContext *s, unsigned char *buf, int size);
|
||||
int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size);
|
||||
|
||||
/** @note return 0 if EOF, so you cannot use it if EOF handling is
|
||||
necessary */
|
||||
int get_byte(ByteIOContext *s);
|
||||
unsigned int get_le24(ByteIOContext *s);
|
||||
unsigned int get_le32(ByteIOContext *s);
|
||||
uint64_t get_le64(ByteIOContext *s);
|
||||
unsigned int get_le16(ByteIOContext *s);
|
||||
|
||||
char *get_strz(ByteIOContext *s, char *buf, int maxlen);
|
||||
unsigned int get_be16(ByteIOContext *s);
|
||||
unsigned int get_be24(ByteIOContext *s);
|
||||
unsigned int get_be32(ByteIOContext *s);
|
||||
uint64_t get_be64(ByteIOContext *s);
|
||||
|
||||
static inline int url_is_streamed(ByteIOContext *s)
|
||||
{
|
||||
return s->is_streamed;
|
||||
}
|
||||
|
||||
int url_fdopen(ByteIOContext *s, URLContext *h);
|
||||
|
||||
/** @warning must be called before any I/O */
|
||||
int url_setbufsize(ByteIOContext *s, int buf_size);
|
||||
|
||||
/** @note when opened as read/write, the buffers are only used for
|
||||
reading */
|
||||
int url_fopen(ByteIOContext *s, const char *filename, int flags);
|
||||
int url_fclose(ByteIOContext *s);
|
||||
URLContext *url_fileno(ByteIOContext *s);
|
||||
|
||||
/**
|
||||
* Return the maximum packet size associated to packetized buffered file
|
||||
* handle. If the file is not packetized (stream like http or file on
|
||||
* disk), then 0 is returned.
|
||||
*
|
||||
* @param h buffered file handle
|
||||
* @return maximum packet size in bytes
|
||||
*/
|
||||
int url_fget_max_packet_size(ByteIOContext *s);
|
||||
|
||||
int url_open_buf(ByteIOContext *s, uint8_t *buf, int buf_size, int flags);
|
||||
|
||||
/** return the written or read size */
|
||||
int url_close_buf(ByteIOContext *s);
|
||||
|
||||
/**
|
||||
* Open a write only memory stream.
|
||||
*
|
||||
* @param s new IO context
|
||||
* @return zero if no error.
|
||||
*/
|
||||
int url_open_dyn_buf(ByteIOContext *s);
|
||||
|
||||
/**
|
||||
* Open a write only packetized memory stream with a maximum packet
|
||||
* size of 'max_packet_size'. The stream is stored in a memory buffer
|
||||
* with a big endian 4 byte header giving the packet size in bytes.
|
||||
*
|
||||
* @param s new IO context
|
||||
* @param max_packet_size maximum packet size (must be > 0)
|
||||
* @return zero if no error.
|
||||
*/
|
||||
int url_open_dyn_packet_buf(ByteIOContext *s, int max_packet_size);
|
||||
|
||||
/**
|
||||
* Return the written size and a pointer to the buffer. The buffer
|
||||
* must be freed with av_free().
|
||||
* @param s IO context
|
||||
* @param pointer to a byte buffer
|
||||
* @return the length of the byte buffer
|
||||
*/
|
||||
int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer);
|
||||
|
||||
unsigned long get_checksum(ByteIOContext *s);
|
||||
void init_checksum(ByteIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum);
|
||||
|
||||
/* file.c */
|
||||
extern URLProtocol file_protocol;
|
||||
extern URLProtocol pipe_protocol;
|
||||
|
||||
/* udp.c */
|
||||
extern URLProtocol udp_protocol;
|
||||
int udp_set_remote_url(URLContext *h, const char *uri);
|
||||
int udp_get_local_port(URLContext *h);
|
||||
int udp_get_file_handle(URLContext *h);
|
||||
|
||||
/* tcp.c */
|
||||
extern URLProtocol tcp_protocol;
|
||||
|
||||
/* http.c */
|
||||
extern URLProtocol http_protocol;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* unbuffered io for ffmpeg system
|
||||
* copyright (c) 2001 Fabrice Bellard
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef AVIO_H
|
||||
#define AVIO_H
|
||||
|
||||
/* output byte stream handling */
|
||||
|
||||
typedef int64_t offset_t;
|
||||
|
||||
/* unbuffered I/O */
|
||||
|
||||
struct URLContext {
|
||||
struct URLProtocol *prot;
|
||||
int flags;
|
||||
int is_streamed; /**< true if streamed (no seek possible), default = false */
|
||||
int max_packet_size; /**< if non zero, the stream is packetized with this max packet size */
|
||||
void *priv_data;
|
||||
#if LIBAVFORMAT_VERSION_INT >= (52<<16)
|
||||
char *filename; /**< specified filename */
|
||||
#else
|
||||
char filename[1]; /**< specified filename */
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct URLContext URLContext;
|
||||
|
||||
typedef struct URLPollEntry {
|
||||
URLContext *handle;
|
||||
int events;
|
||||
int revents;
|
||||
} URLPollEntry;
|
||||
|
||||
#define URL_RDONLY 0
|
||||
#define URL_WRONLY 1
|
||||
#define URL_RDWR 2
|
||||
|
||||
typedef int URLInterruptCB(void);
|
||||
|
||||
int url_open(URLContext **h, const char *filename, int flags);
|
||||
int url_read(URLContext *h, unsigned char *buf, int size);
|
||||
int url_write(URLContext *h, unsigned char *buf, int size);
|
||||
offset_t url_seek(URLContext *h, offset_t pos, int whence);
|
||||
int url_close(URLContext *h);
|
||||
int url_exist(const char *filename);
|
||||
offset_t url_filesize(URLContext *h);
|
||||
|
||||
/**
|
||||
* Return the maximum packet size associated to packetized file
|
||||
* handle. If the file is not packetized (stream like http or file on
|
||||
* disk), then 0 is returned.
|
||||
*
|
||||
* @param h file handle
|
||||
* @return maximum packet size in bytes
|
||||
*/
|
||||
int url_get_max_packet_size(URLContext *h);
|
||||
void url_get_filename(URLContext *h, char *buf, int buf_size);
|
||||
|
||||
/**
|
||||
* the callback is called in blocking functions to test regulary if
|
||||
* asynchronous interruption is needed. AVERROR(EINTR) is returned
|
||||
* in this case by the interrupted function. 'NULL' means no interrupt
|
||||
* callback is given. i
|
||||
*/
|
||||
void url_set_interrupt_cb(URLInterruptCB *interrupt_cb);
|
||||
|
||||
/* not implemented */
|
||||
int url_poll(URLPollEntry *poll_table, int n, int timeout);
|
||||
|
||||
/**
|
||||
* passing this as the "whence" parameter to a seek function causes it to
|
||||
* return the filesize without seeking anywhere, supporting this is optional
|
||||
* if its not supprted then the seek function will return <0
|
||||
*/
|
||||
#define AVSEEK_SIZE 0x10000
|
||||
|
||||
typedef struct URLProtocol {
|
||||
const char *name;
|
||||
int (*url_open)(URLContext *h, const char *filename, int flags);
|
||||
int (*url_read)(URLContext *h, unsigned char *buf, int size);
|
||||
int (*url_write)(URLContext *h, unsigned char *buf, int size);
|
||||
offset_t (*url_seek)(URLContext *h, offset_t pos, int whence);
|
||||
int (*url_close)(URLContext *h);
|
||||
struct URLProtocol *next;
|
||||
} URLProtocol;
|
||||
|
||||
extern URLProtocol *first_protocol;
|
||||
extern URLInterruptCB *url_interrupt_cb;
|
||||
|
||||
int register_protocol(URLProtocol *protocol);
|
||||
|
||||
typedef struct {
|
||||
unsigned char *buffer;
|
||||
int buffer_size;
|
||||
unsigned char *buf_ptr, *buf_end;
|
||||
void *opaque;
|
||||
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);
|
||||
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);
|
||||
offset_t (*seek)(void *opaque, offset_t offset, int whence);
|
||||
offset_t pos; /**< position in the file of the current buffer */
|
||||
int must_flush; /**< true if the next seek should flush */
|
||||
int eof_reached; /**< true if eof reached */
|
||||
int write_flag; /**< true if open for writing */
|
||||
int is_streamed;
|
||||
int max_packet_size;
|
||||
unsigned long checksum;
|
||||
unsigned char *checksum_ptr;
|
||||
unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);
|
||||
int error; ///< contains the error code or 0 if no error happened
|
||||
} ByteIOContext;
|
||||
|
||||
int init_put_byte(ByteIOContext *s,
|
||||
unsigned char *buffer,
|
||||
int buffer_size,
|
||||
int write_flag,
|
||||
void *opaque,
|
||||
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||
offset_t (*seek)(void *opaque, offset_t offset, int whence));
|
||||
|
||||
void put_byte(ByteIOContext *s, int b);
|
||||
void put_buffer(ByteIOContext *s, const unsigned char *buf, int size);
|
||||
void put_le64(ByteIOContext *s, uint64_t val);
|
||||
void put_be64(ByteIOContext *s, uint64_t val);
|
||||
void put_le32(ByteIOContext *s, unsigned int val);
|
||||
void put_be32(ByteIOContext *s, unsigned int val);
|
||||
void put_le24(ByteIOContext *s, unsigned int val);
|
||||
void put_be24(ByteIOContext *s, unsigned int val);
|
||||
void put_le16(ByteIOContext *s, unsigned int val);
|
||||
void put_be16(ByteIOContext *s, unsigned int val);
|
||||
void put_tag(ByteIOContext *s, const char *tag);
|
||||
|
||||
void put_strz(ByteIOContext *s, const char *buf);
|
||||
|
||||
offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence);
|
||||
void url_fskip(ByteIOContext *s, offset_t offset);
|
||||
offset_t url_ftell(ByteIOContext *s);
|
||||
offset_t url_fsize(ByteIOContext *s);
|
||||
int url_feof(ByteIOContext *s);
|
||||
int url_ferror(ByteIOContext *s);
|
||||
|
||||
#define URL_EOF (-1)
|
||||
/** @note return URL_EOF (-1) if EOF */
|
||||
int url_fgetc(ByteIOContext *s);
|
||||
|
||||
/** @warning currently size is limited */
|
||||
#ifdef __GNUC__
|
||||
int url_fprintf(ByteIOContext *s, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
#else
|
||||
int url_fprintf(ByteIOContext *s, const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
/** @note unlike fgets, the EOL character is not returned and a whole
|
||||
line is parsed. return NULL if first char read was EOF */
|
||||
char *url_fgets(ByteIOContext *s, char *buf, int buf_size);
|
||||
|
||||
void put_flush_packet(ByteIOContext *s);
|
||||
|
||||
int get_buffer(ByteIOContext *s, unsigned char *buf, int size);
|
||||
int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size);
|
||||
|
||||
/** @note return 0 if EOF, so you cannot use it if EOF handling is
|
||||
necessary */
|
||||
int get_byte(ByteIOContext *s);
|
||||
unsigned int get_le24(ByteIOContext *s);
|
||||
unsigned int get_le32(ByteIOContext *s);
|
||||
uint64_t get_le64(ByteIOContext *s);
|
||||
unsigned int get_le16(ByteIOContext *s);
|
||||
|
||||
char *get_strz(ByteIOContext *s, char *buf, int maxlen);
|
||||
unsigned int get_be16(ByteIOContext *s);
|
||||
unsigned int get_be24(ByteIOContext *s);
|
||||
unsigned int get_be32(ByteIOContext *s);
|
||||
uint64_t get_be64(ByteIOContext *s);
|
||||
|
||||
static inline int url_is_streamed(ByteIOContext *s)
|
||||
{
|
||||
return s->is_streamed;
|
||||
}
|
||||
|
||||
int url_fdopen(ByteIOContext *s, URLContext *h);
|
||||
|
||||
/** @warning must be called before any I/O */
|
||||
int url_setbufsize(ByteIOContext *s, int buf_size);
|
||||
|
||||
/** @note when opened as read/write, the buffers are only used for
|
||||
reading */
|
||||
int url_fopen(ByteIOContext *s, const char *filename, int flags);
|
||||
int url_fclose(ByteIOContext *s);
|
||||
URLContext *url_fileno(ByteIOContext *s);
|
||||
|
||||
/**
|
||||
* Return the maximum packet size associated to packetized buffered file
|
||||
* handle. If the file is not packetized (stream like http or file on
|
||||
* disk), then 0 is returned.
|
||||
*
|
||||
* @param h buffered file handle
|
||||
* @return maximum packet size in bytes
|
||||
*/
|
||||
int url_fget_max_packet_size(ByteIOContext *s);
|
||||
|
||||
int url_open_buf(ByteIOContext *s, uint8_t *buf, int buf_size, int flags);
|
||||
|
||||
/** return the written or read size */
|
||||
int url_close_buf(ByteIOContext *s);
|
||||
|
||||
/**
|
||||
* Open a write only memory stream.
|
||||
*
|
||||
* @param s new IO context
|
||||
* @return zero if no error.
|
||||
*/
|
||||
int url_open_dyn_buf(ByteIOContext *s);
|
||||
|
||||
/**
|
||||
* Open a write only packetized memory stream with a maximum packet
|
||||
* size of 'max_packet_size'. The stream is stored in a memory buffer
|
||||
* with a big endian 4 byte header giving the packet size in bytes.
|
||||
*
|
||||
* @param s new IO context
|
||||
* @param max_packet_size maximum packet size (must be > 0)
|
||||
* @return zero if no error.
|
||||
*/
|
||||
int url_open_dyn_packet_buf(ByteIOContext *s, int max_packet_size);
|
||||
|
||||
/**
|
||||
* Return the written size and a pointer to the buffer. The buffer
|
||||
* must be freed with av_free().
|
||||
* @param s IO context
|
||||
* @param pointer to a byte buffer
|
||||
* @return the length of the byte buffer
|
||||
*/
|
||||
int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer);
|
||||
|
||||
unsigned long get_checksum(ByteIOContext *s);
|
||||
void init_checksum(ByteIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum);
|
||||
|
||||
/* file.c */
|
||||
extern URLProtocol file_protocol;
|
||||
extern URLProtocol pipe_protocol;
|
||||
|
||||
/* udp.c */
|
||||
extern URLProtocol udp_protocol;
|
||||
int udp_set_remote_url(URLContext *h, const char *uri);
|
||||
int udp_get_local_port(URLContext *h);
|
||||
int udp_get_file_handle(URLContext *h);
|
||||
|
||||
/* tcp.c */
|
||||
extern URLProtocol tcp_protocol;
|
||||
|
||||
/* http.c */
|
||||
extern URLProtocol http_protocol;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+137
-137
@@ -1,137 +1,137 @@
|
||||
/*
|
||||
* copyright (c) 2006 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVUTIL_H
|
||||
#define AVUTIL_H
|
||||
|
||||
/**
|
||||
* @file avutil.h
|
||||
* external api header.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AV_STRINGIFY(s) AV_TOSTRING(s)
|
||||
#define AV_TOSTRING(s) #s
|
||||
|
||||
#define LIBAVUTIL_VERSION_INT ((49<<16)+(4<<8)+0)
|
||||
#define LIBAVUTIL_VERSION 49.4.0
|
||||
#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT
|
||||
|
||||
#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION)
|
||||
|
||||
|
||||
#include "common.h"
|
||||
#include "mathematics.h"
|
||||
#include "rational.h"
|
||||
#include "integer.h"
|
||||
#include "intfloat_readwrite.h"
|
||||
#include "log.h"
|
||||
|
||||
/**
|
||||
* Pixel format. Notes:
|
||||
*
|
||||
* PIX_FMT_RGB32 is handled in an endian-specific manner. A RGBA
|
||||
* color is put together as:
|
||||
* (A << 24) | (R << 16) | (G << 8) | B
|
||||
* This is stored as BGRA on little endian CPU architectures and ARGB on
|
||||
* big endian CPUs.
|
||||
*
|
||||
* When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized
|
||||
* image data is stored in AVFrame.data[0]. The palette is transported in
|
||||
* AVFrame.data[1] and, is 1024 bytes long (256 4-byte entries) and is
|
||||
* formatted the same as in PIX_FMT_RGB32 described above (i.e., it is
|
||||
* also endian-specific). Note also that the individual RGB palette
|
||||
* components stored in AVFrame.data[1] should be in the range 0..255.
|
||||
* This is important as many custom PAL8 video codecs that were designed
|
||||
* to run on the IBM VGA graphics adapter use 6-bit palette components.
|
||||
*/
|
||||
enum PixelFormat {
|
||||
PIX_FMT_NONE= -1,
|
||||
PIX_FMT_YUV420P, ///< Planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
|
||||
PIX_FMT_YUYV422, ///< Packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
|
||||
PIX_FMT_RGB24, ///< Packed RGB 8:8:8, 24bpp, RGBRGB...
|
||||
PIX_FMT_BGR24, ///< Packed RGB 8:8:8, 24bpp, BGRBGR...
|
||||
PIX_FMT_YUV422P, ///< Planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
|
||||
PIX_FMT_YUV444P, ///< Planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
|
||||
PIX_FMT_RGB32, ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8R 8G 8B(lsb), in cpu endianness
|
||||
PIX_FMT_YUV410P, ///< Planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
|
||||
PIX_FMT_YUV411P, ///< Planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
|
||||
PIX_FMT_RGB565, ///< Packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), in cpu endianness
|
||||
PIX_FMT_RGB555, ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), in cpu endianness most significant bit to 0
|
||||
PIX_FMT_GRAY8, ///< Y , 8bpp
|
||||
PIX_FMT_MONOWHITE, ///< Y , 1bpp, 1 is white
|
||||
PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black
|
||||
PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette
|
||||
PIX_FMT_YUVJ420P, ///< Planar YUV 4:2:0, 12bpp, full scale (jpeg)
|
||||
PIX_FMT_YUVJ422P, ///< Planar YUV 4:2:2, 16bpp, full scale (jpeg)
|
||||
PIX_FMT_YUVJ444P, ///< Planar YUV 4:4:4, 24bpp, full scale (jpeg)
|
||||
PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing(xvmc_render.h)
|
||||
PIX_FMT_XVMC_MPEG2_IDCT,
|
||||
PIX_FMT_UYVY422, ///< Packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
|
||||
PIX_FMT_UYYVYY411, ///< Packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
|
||||
PIX_FMT_BGR32, ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8B 8G 8R(lsb), in cpu endianness
|
||||
PIX_FMT_BGR565, ///< Packed RGB 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), in cpu endianness
|
||||
PIX_FMT_BGR555, ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), in cpu endianness most significant bit to 1
|
||||
PIX_FMT_BGR8, ///< Packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
|
||||
PIX_FMT_BGR4, ///< Packed RGB 1:2:1, 4bpp, (msb)1B 2G 1R(lsb)
|
||||
PIX_FMT_BGR4_BYTE, ///< Packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb)
|
||||
PIX_FMT_RGB8, ///< Packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
|
||||
PIX_FMT_RGB4, ///< Packed RGB 1:2:1, 4bpp, (msb)2R 3G 3B(lsb)
|
||||
PIX_FMT_RGB4_BYTE, ///< Packed RGB 1:2:1, 8bpp, (msb)2R 3G 3B(lsb)
|
||||
PIX_FMT_NV12, ///< Planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 for UV
|
||||
PIX_FMT_NV21, ///< as above, but U and V bytes are swapped
|
||||
|
||||
PIX_FMT_RGB32_1, ///< Packed RGB 8:8:8, 32bpp, (msb)8R 8G 8B 8A(lsb), in cpu endianness
|
||||
PIX_FMT_BGR32_1, ///< Packed RGB 8:8:8, 32bpp, (msb)8B 8G 8R 8A(lsb), in cpu endianness
|
||||
|
||||
PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian
|
||||
PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian
|
||||
PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
|
||||
};
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define PIX_FMT_RGBA PIX_FMT_RGB32_1
|
||||
#define PIX_FMT_BGRA PIX_FMT_BGR32_1
|
||||
#define PIX_FMT_ARGB PIX_FMT_RGB32
|
||||
#define PIX_FMT_ABGR PIX_FMT_BGR32
|
||||
#define PIX_FMT_GRAY16 PIX_FMT_GRAY16BE
|
||||
#else
|
||||
#define PIX_FMT_RGBA PIX_FMT_BGR32
|
||||
#define PIX_FMT_BGRA PIX_FMT_RGB32
|
||||
#define PIX_FMT_ARGB PIX_FMT_BGR32_1
|
||||
#define PIX_FMT_ABGR PIX_FMT_RGB32_1
|
||||
#define PIX_FMT_GRAY16 PIX_FMT_GRAY16LE
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < (50<<16)
|
||||
#define PIX_FMT_UYVY411 PIX_FMT_UYYVYY411
|
||||
#define PIX_FMT_RGBA32 PIX_FMT_RGB32
|
||||
#define PIX_FMT_YUV422 PIX_FMT_YUYV422
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AVUTIL_H */
|
||||
/*
|
||||
* copyright (c) 2006 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVUTIL_H
|
||||
#define AVUTIL_H
|
||||
|
||||
/**
|
||||
* @file avutil.h
|
||||
* external api header.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AV_STRINGIFY(s) AV_TOSTRING(s)
|
||||
#define AV_TOSTRING(s) #s
|
||||
|
||||
#define LIBAVUTIL_VERSION_INT ((49<<16)+(4<<8)+0)
|
||||
#define LIBAVUTIL_VERSION 49.4.0
|
||||
#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT
|
||||
|
||||
#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION)
|
||||
|
||||
|
||||
#include "common.h"
|
||||
#include "mathematics.h"
|
||||
#include "rational.h"
|
||||
#include "integer.h"
|
||||
#include "intfloat_readwrite.h"
|
||||
#include "log.h"
|
||||
|
||||
/**
|
||||
* Pixel format. Notes:
|
||||
*
|
||||
* PIX_FMT_RGB32 is handled in an endian-specific manner. A RGBA
|
||||
* color is put together as:
|
||||
* (A << 24) | (R << 16) | (G << 8) | B
|
||||
* This is stored as BGRA on little endian CPU architectures and ARGB on
|
||||
* big endian CPUs.
|
||||
*
|
||||
* When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized
|
||||
* image data is stored in AVFrame.data[0]. The palette is transported in
|
||||
* AVFrame.data[1] and, is 1024 bytes long (256 4-byte entries) and is
|
||||
* formatted the same as in PIX_FMT_RGB32 described above (i.e., it is
|
||||
* also endian-specific). Note also that the individual RGB palette
|
||||
* components stored in AVFrame.data[1] should be in the range 0..255.
|
||||
* This is important as many custom PAL8 video codecs that were designed
|
||||
* to run on the IBM VGA graphics adapter use 6-bit palette components.
|
||||
*/
|
||||
enum PixelFormat {
|
||||
PIX_FMT_NONE= -1,
|
||||
PIX_FMT_YUV420P, ///< Planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
|
||||
PIX_FMT_YUYV422, ///< Packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
|
||||
PIX_FMT_RGB24, ///< Packed RGB 8:8:8, 24bpp, RGBRGB...
|
||||
PIX_FMT_BGR24, ///< Packed RGB 8:8:8, 24bpp, BGRBGR...
|
||||
PIX_FMT_YUV422P, ///< Planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
|
||||
PIX_FMT_YUV444P, ///< Planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
|
||||
PIX_FMT_RGB32, ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8R 8G 8B(lsb), in cpu endianness
|
||||
PIX_FMT_YUV410P, ///< Planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
|
||||
PIX_FMT_YUV411P, ///< Planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
|
||||
PIX_FMT_RGB565, ///< Packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), in cpu endianness
|
||||
PIX_FMT_RGB555, ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), in cpu endianness most significant bit to 0
|
||||
PIX_FMT_GRAY8, ///< Y , 8bpp
|
||||
PIX_FMT_MONOWHITE, ///< Y , 1bpp, 1 is white
|
||||
PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black
|
||||
PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette
|
||||
PIX_FMT_YUVJ420P, ///< Planar YUV 4:2:0, 12bpp, full scale (jpeg)
|
||||
PIX_FMT_YUVJ422P, ///< Planar YUV 4:2:2, 16bpp, full scale (jpeg)
|
||||
PIX_FMT_YUVJ444P, ///< Planar YUV 4:4:4, 24bpp, full scale (jpeg)
|
||||
PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing(xvmc_render.h)
|
||||
PIX_FMT_XVMC_MPEG2_IDCT,
|
||||
PIX_FMT_UYVY422, ///< Packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
|
||||
PIX_FMT_UYYVYY411, ///< Packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
|
||||
PIX_FMT_BGR32, ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8B 8G 8R(lsb), in cpu endianness
|
||||
PIX_FMT_BGR565, ///< Packed RGB 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), in cpu endianness
|
||||
PIX_FMT_BGR555, ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), in cpu endianness most significant bit to 1
|
||||
PIX_FMT_BGR8, ///< Packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
|
||||
PIX_FMT_BGR4, ///< Packed RGB 1:2:1, 4bpp, (msb)1B 2G 1R(lsb)
|
||||
PIX_FMT_BGR4_BYTE, ///< Packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb)
|
||||
PIX_FMT_RGB8, ///< Packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
|
||||
PIX_FMT_RGB4, ///< Packed RGB 1:2:1, 4bpp, (msb)2R 3G 3B(lsb)
|
||||
PIX_FMT_RGB4_BYTE, ///< Packed RGB 1:2:1, 8bpp, (msb)2R 3G 3B(lsb)
|
||||
PIX_FMT_NV12, ///< Planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 for UV
|
||||
PIX_FMT_NV21, ///< as above, but U and V bytes are swapped
|
||||
|
||||
PIX_FMT_RGB32_1, ///< Packed RGB 8:8:8, 32bpp, (msb)8R 8G 8B 8A(lsb), in cpu endianness
|
||||
PIX_FMT_BGR32_1, ///< Packed RGB 8:8:8, 32bpp, (msb)8B 8G 8R 8A(lsb), in cpu endianness
|
||||
|
||||
PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian
|
||||
PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian
|
||||
PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
|
||||
};
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define PIX_FMT_RGBA PIX_FMT_RGB32_1
|
||||
#define PIX_FMT_BGRA PIX_FMT_BGR32_1
|
||||
#define PIX_FMT_ARGB PIX_FMT_RGB32
|
||||
#define PIX_FMT_ABGR PIX_FMT_BGR32
|
||||
#define PIX_FMT_GRAY16 PIX_FMT_GRAY16BE
|
||||
#else
|
||||
#define PIX_FMT_RGBA PIX_FMT_BGR32
|
||||
#define PIX_FMT_BGRA PIX_FMT_RGB32
|
||||
#define PIX_FMT_ARGB PIX_FMT_BGR32_1
|
||||
#define PIX_FMT_ABGR PIX_FMT_RGB32_1
|
||||
#define PIX_FMT_GRAY16 PIX_FMT_GRAY16LE
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < (50<<16)
|
||||
#define PIX_FMT_UYVY411 PIX_FMT_UYYVYY411
|
||||
#define PIX_FMT_RGBA32 PIX_FMT_RGB32
|
||||
#define PIX_FMT_YUV422 PIX_FMT_YUYV422
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AVUTIL_H */
|
||||
|
||||
+328
-328
@@ -1,328 +1,328 @@
|
||||
/*
|
||||
* copyright (c) 2006 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file common.h
|
||||
* common internal and external api header.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#if 0
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AV_CONFIG_H
|
||||
/* only include the following when compiling package */
|
||||
# include "config.h"
|
||||
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# include <string.h>
|
||||
# include <ctype.h>
|
||||
# include <limits.h>
|
||||
# include <errno.h>
|
||||
# include <math.h>
|
||||
#endif /* HAVE_AV_CONFIG_H */
|
||||
|
||||
#ifndef av_always_inline
|
||||
#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
|
||||
# define av_always_inline __attribute__((always_inline)) inline
|
||||
# define av_noinline __attribute__((noinline))
|
||||
#else
|
||||
# define av_always_inline inline
|
||||
# define av_noinline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AV_CONFIG_H
|
||||
# include "internal.h"
|
||||
#endif /* HAVE_AV_CONFIG_H */
|
||||
|
||||
#ifndef attribute_deprecated
|
||||
#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
|
||||
# define attribute_deprecated __attribute__((deprecated))
|
||||
#else
|
||||
# define attribute_deprecated
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "mem.h"
|
||||
|
||||
//rounded divison & shift
|
||||
#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b))
|
||||
/* assume b>0 */
|
||||
#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))
|
||||
#define FFABS(a) ((a) >= 0 ? (a) : (-(a)))
|
||||
#define FFSIGN(a) ((a) > 0 ? 1 : -1)
|
||||
|
||||
#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
|
||||
|
||||
#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
|
||||
|
||||
/* misc math functions */
|
||||
extern const uint8_t ff_log2_tab[256];
|
||||
|
||||
static inline int av_log2(unsigned int v)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
if (v & 0xffff0000) {
|
||||
v >>= 16;
|
||||
n += 16;
|
||||
}
|
||||
if (v & 0xff00) {
|
||||
v >>= 8;
|
||||
n += 8;
|
||||
}
|
||||
n += ff_log2_tab[v];
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static inline int av_log2_16bit(unsigned int v)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
if (v & 0xff00) {
|
||||
v >>= 8;
|
||||
n += 8;
|
||||
}
|
||||
n += ff_log2_tab[v];
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* median of 3 */
|
||||
static inline int mid_pred(int a, int b, int c)
|
||||
{
|
||||
#ifdef HAVE_CMOV
|
||||
int i=b;
|
||||
asm volatile(
|
||||
"cmp %2, %1 \n\t"
|
||||
"cmovg %1, %0 \n\t"
|
||||
"cmovg %2, %1 \n\t"
|
||||
"cmp %3, %1 \n\t"
|
||||
"cmovl %3, %1 \n\t"
|
||||
"cmp %1, %0 \n\t"
|
||||
"cmovg %1, %0 \n\t"
|
||||
:"+&r"(i), "+&r"(a)
|
||||
:"r"(b), "r"(c)
|
||||
);
|
||||
return i;
|
||||
#elif 0
|
||||
int t= (a-b)&((a-b)>>31);
|
||||
a-=t;
|
||||
b+=t;
|
||||
b-= (b-c)&((b-c)>>31);
|
||||
b+= (a-b)&((a-b)>>31);
|
||||
|
||||
return b;
|
||||
#else
|
||||
if(a>b){
|
||||
if(c>b){
|
||||
if(c>a) b=a;
|
||||
else b=c;
|
||||
}
|
||||
}else{
|
||||
if(b>c){
|
||||
if(c>a) b=c;
|
||||
else b=a;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* clip a signed integer value into the amin-amax range
|
||||
* @param a value to clip
|
||||
* @param amin minimum value of the clip range
|
||||
* @param amax maximum value of the clip range
|
||||
* @return clipped value
|
||||
*/
|
||||
static inline int av_clip(int a, int amin, int amax)
|
||||
{
|
||||
if (a < amin) return amin;
|
||||
else if (a > amax) return amax;
|
||||
else return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* clip a signed integer value into the 0-255 range
|
||||
* @param a value to clip
|
||||
* @return clipped value
|
||||
*/
|
||||
static inline uint8_t av_clip_uint8(int a)
|
||||
{
|
||||
if (a&(~255)) return (-a)>>31;
|
||||
else return a;
|
||||
}
|
||||
|
||||
/* math */
|
||||
int64_t ff_gcd(int64_t a, int64_t b);
|
||||
|
||||
/**
|
||||
* converts fourcc string to int
|
||||
*/
|
||||
static inline int ff_get_fourcc(const char *s){
|
||||
#ifdef HAVE_AV_CONFIG_H
|
||||
assert( strlen(s)==4 );
|
||||
#endif
|
||||
|
||||
return (s[0]) + (s[1]<<8) + (s[2]<<16) + (s[3]<<24);
|
||||
}
|
||||
|
||||
#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
|
||||
#define MKBETAG(a,b,c,d) (d | (c << 8) | (b << 16) | (a << 24))
|
||||
|
||||
/*!
|
||||
* \def GET_UTF8(val, GET_BYTE, ERROR)
|
||||
* converts a utf-8 character (up to 4 bytes long) to its 32-bit ucs-4 encoded form
|
||||
* \param val is the output and should be of type uint32_t. It holds the converted
|
||||
* ucs-4 character and should be a left value.
|
||||
* \param GET_BYTE gets utf-8 encoded bytes from any proper source. It can be
|
||||
* a function or a statement whose return value or evaluated value is of type
|
||||
* uint8_t. It will be executed up to 4 times for values in the valid utf-8 range,
|
||||
* and up to 7 times in the general case.
|
||||
* \param ERROR action that should be taken when an invalid utf-8 byte is returned
|
||||
* from GET_BYTE. It should be a statement that jumps out of the macro,
|
||||
* like exit(), goto, return, break, or continue.
|
||||
*/
|
||||
#define GET_UTF8(val, GET_BYTE, ERROR)\
|
||||
val= GET_BYTE;\
|
||||
{\
|
||||
int ones= 7 - av_log2(val ^ 255);\
|
||||
if(ones==1)\
|
||||
ERROR\
|
||||
val&= 127>>ones;\
|
||||
while(--ones > 0){\
|
||||
int tmp= GET_BYTE - 128;\
|
||||
if(tmp>>6)\
|
||||
ERROR\
|
||||
val= (val<<6) + tmp;\
|
||||
}\
|
||||
}
|
||||
|
||||
/*!
|
||||
* \def PUT_UTF8(val, tmp, PUT_BYTE)
|
||||
* converts a 32-bit unicode character to its utf-8 encoded form (up to 4 bytes long).
|
||||
* \param val is an input only argument and should be of type uint32_t. It holds
|
||||
* a ucs4 encoded unicode character that is to be converted to utf-8. If
|
||||
* val is given as a function it's executed only once.
|
||||
* \param tmp is a temporary variable and should be of type uint8_t. It
|
||||
* represents an intermediate value during conversion that is to be
|
||||
* outputted by PUT_BYTE.
|
||||
* \param PUT_BYTE writes the converted utf-8 bytes to any proper destination.
|
||||
* It could be a function or a statement, and uses tmp as the input byte.
|
||||
* For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be
|
||||
* executed up to 4 times for values in the valid utf-8 range and up to
|
||||
* 7 times in the general case, depending on the length of the converted
|
||||
* unicode character.
|
||||
*/
|
||||
#define PUT_UTF8(val, tmp, PUT_BYTE)\
|
||||
{\
|
||||
int bytes, shift;\
|
||||
uint32_t in = val;\
|
||||
if (in < 0x80) {\
|
||||
tmp = in;\
|
||||
PUT_BYTE\
|
||||
} else {\
|
||||
bytes = (av_log2(in) + 4) / 5;\
|
||||
shift = (bytes - 1) * 6;\
|
||||
tmp = (256 - (256 >> bytes)) | (in >> shift);\
|
||||
PUT_BYTE\
|
||||
while (shift >= 6) {\
|
||||
shift -= 6;\
|
||||
tmp = 0x80 | ((in >> shift) & 0x3f);\
|
||||
PUT_BYTE\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
|
||||
#if defined(ARCH_X86) || defined(ARCH_POWERPC)
|
||||
#if defined(ARCH_X86_64)
|
||||
static inline uint64_t read_time(void)
|
||||
{
|
||||
uint64_t a, d;
|
||||
asm volatile( "rdtsc\n\t"
|
||||
: "=a" (a), "=d" (d)
|
||||
);
|
||||
return (d << 32) | (a & 0xffffffff);
|
||||
}
|
||||
#elif defined(ARCH_X86_32)
|
||||
static inline long long read_time(void)
|
||||
{
|
||||
long long l;
|
||||
asm volatile( "rdtsc\n\t"
|
||||
: "=A" (l)
|
||||
);
|
||||
return l;
|
||||
}
|
||||
#else //FIXME check ppc64
|
||||
static inline uint64_t read_time(void)
|
||||
{
|
||||
uint32_t tbu, tbl, temp;
|
||||
|
||||
/* from section 2.2.1 of the 32-bit PowerPC PEM */
|
||||
__asm__ __volatile__(
|
||||
"1:\n"
|
||||
"mftbu %2\n"
|
||||
"mftb %0\n"
|
||||
"mftbu %1\n"
|
||||
"cmpw %2,%1\n"
|
||||
"bne 1b\n"
|
||||
: "=r"(tbl), "=r"(tbu), "=r"(temp)
|
||||
:
|
||||
: "cc");
|
||||
|
||||
return (((uint64_t)tbu)<<32) | (uint64_t)tbl;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define START_TIMER \
|
||||
uint64_t tend;\
|
||||
uint64_t tstart= read_time();\
|
||||
|
||||
#define STOP_TIMER(id) \
|
||||
tend= read_time();\
|
||||
{\
|
||||
static uint64_t tsum=0;\
|
||||
static int tcount=0;\
|
||||
static int tskip_count=0;\
|
||||
if(tcount<2 || tend - tstart < FFMAX(8*tsum/tcount, 2000)){\
|
||||
tsum+= tend - tstart;\
|
||||
tcount++;\
|
||||
}else\
|
||||
tskip_count++;\
|
||||
if(((tcount+tskip_count)&(tcount+tskip_count-1))==0){\
|
||||
av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" dezicycles in %s, %d runs, %d skips\n", tsum*10/tcount, id, tcount, tskip_count);\
|
||||
}\
|
||||
}
|
||||
#else
|
||||
#define START_TIMER
|
||||
#define STOP_TIMER(id) {}
|
||||
#endif
|
||||
|
||||
#endif /* COMMON_H */
|
||||
/*
|
||||
* copyright (c) 2006 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file common.h
|
||||
* common internal and external api header.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#if 0
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AV_CONFIG_H
|
||||
/* only include the following when compiling package */
|
||||
# include "config.h"
|
||||
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# include <string.h>
|
||||
# include <ctype.h>
|
||||
# include <limits.h>
|
||||
# include <errno.h>
|
||||
# include <math.h>
|
||||
#endif /* HAVE_AV_CONFIG_H */
|
||||
|
||||
#ifndef av_always_inline
|
||||
#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
|
||||
# define av_always_inline __attribute__((always_inline)) inline
|
||||
# define av_noinline __attribute__((noinline))
|
||||
#else
|
||||
# define av_always_inline inline
|
||||
# define av_noinline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AV_CONFIG_H
|
||||
# include "internal.h"
|
||||
#endif /* HAVE_AV_CONFIG_H */
|
||||
|
||||
#ifndef attribute_deprecated
|
||||
#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
|
||||
# define attribute_deprecated __attribute__((deprecated))
|
||||
#else
|
||||
# define attribute_deprecated
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "mem.h"
|
||||
|
||||
//rounded divison & shift
|
||||
#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b))
|
||||
/* assume b>0 */
|
||||
#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))
|
||||
#define FFABS(a) ((a) >= 0 ? (a) : (-(a)))
|
||||
#define FFSIGN(a) ((a) > 0 ? 1 : -1)
|
||||
|
||||
#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
|
||||
|
||||
#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
|
||||
|
||||
/* misc math functions */
|
||||
extern const uint8_t ff_log2_tab[256];
|
||||
|
||||
static inline int av_log2(unsigned int v)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
if (v & 0xffff0000) {
|
||||
v >>= 16;
|
||||
n += 16;
|
||||
}
|
||||
if (v & 0xff00) {
|
||||
v >>= 8;
|
||||
n += 8;
|
||||
}
|
||||
n += ff_log2_tab[v];
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static inline int av_log2_16bit(unsigned int v)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
if (v & 0xff00) {
|
||||
v >>= 8;
|
||||
n += 8;
|
||||
}
|
||||
n += ff_log2_tab[v];
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* median of 3 */
|
||||
static inline int mid_pred(int a, int b, int c)
|
||||
{
|
||||
#ifdef HAVE_CMOV
|
||||
int i=b;
|
||||
asm volatile(
|
||||
"cmp %2, %1 \n\t"
|
||||
"cmovg %1, %0 \n\t"
|
||||
"cmovg %2, %1 \n\t"
|
||||
"cmp %3, %1 \n\t"
|
||||
"cmovl %3, %1 \n\t"
|
||||
"cmp %1, %0 \n\t"
|
||||
"cmovg %1, %0 \n\t"
|
||||
:"+&r"(i), "+&r"(a)
|
||||
:"r"(b), "r"(c)
|
||||
);
|
||||
return i;
|
||||
#elif 0
|
||||
int t= (a-b)&((a-b)>>31);
|
||||
a-=t;
|
||||
b+=t;
|
||||
b-= (b-c)&((b-c)>>31);
|
||||
b+= (a-b)&((a-b)>>31);
|
||||
|
||||
return b;
|
||||
#else
|
||||
if(a>b){
|
||||
if(c>b){
|
||||
if(c>a) b=a;
|
||||
else b=c;
|
||||
}
|
||||
}else{
|
||||
if(b>c){
|
||||
if(c>a) b=c;
|
||||
else b=a;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* clip a signed integer value into the amin-amax range
|
||||
* @param a value to clip
|
||||
* @param amin minimum value of the clip range
|
||||
* @param amax maximum value of the clip range
|
||||
* @return clipped value
|
||||
*/
|
||||
static inline int av_clip(int a, int amin, int amax)
|
||||
{
|
||||
if (a < amin) return amin;
|
||||
else if (a > amax) return amax;
|
||||
else return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* clip a signed integer value into the 0-255 range
|
||||
* @param a value to clip
|
||||
* @return clipped value
|
||||
*/
|
||||
static inline uint8_t av_clip_uint8(int a)
|
||||
{
|
||||
if (a&(~255)) return (-a)>>31;
|
||||
else return a;
|
||||
}
|
||||
|
||||
/* math */
|
||||
int64_t ff_gcd(int64_t a, int64_t b);
|
||||
|
||||
/**
|
||||
* converts fourcc string to int
|
||||
*/
|
||||
static inline int ff_get_fourcc(const char *s){
|
||||
#ifdef HAVE_AV_CONFIG_H
|
||||
assert( strlen(s)==4 );
|
||||
#endif
|
||||
|
||||
return (s[0]) + (s[1]<<8) + (s[2]<<16) + (s[3]<<24);
|
||||
}
|
||||
|
||||
#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
|
||||
#define MKBETAG(a,b,c,d) (d | (c << 8) | (b << 16) | (a << 24))
|
||||
|
||||
/*!
|
||||
* \def GET_UTF8(val, GET_BYTE, ERROR)
|
||||
* converts a utf-8 character (up to 4 bytes long) to its 32-bit ucs-4 encoded form
|
||||
* \param val is the output and should be of type uint32_t. It holds the converted
|
||||
* ucs-4 character and should be a left value.
|
||||
* \param GET_BYTE gets utf-8 encoded bytes from any proper source. It can be
|
||||
* a function or a statement whose return value or evaluated value is of type
|
||||
* uint8_t. It will be executed up to 4 times for values in the valid utf-8 range,
|
||||
* and up to 7 times in the general case.
|
||||
* \param ERROR action that should be taken when an invalid utf-8 byte is returned
|
||||
* from GET_BYTE. It should be a statement that jumps out of the macro,
|
||||
* like exit(), goto, return, break, or continue.
|
||||
*/
|
||||
#define GET_UTF8(val, GET_BYTE, ERROR)\
|
||||
val= GET_BYTE;\
|
||||
{\
|
||||
int ones= 7 - av_log2(val ^ 255);\
|
||||
if(ones==1)\
|
||||
ERROR\
|
||||
val&= 127>>ones;\
|
||||
while(--ones > 0){\
|
||||
int tmp= GET_BYTE - 128;\
|
||||
if(tmp>>6)\
|
||||
ERROR\
|
||||
val= (val<<6) + tmp;\
|
||||
}\
|
||||
}
|
||||
|
||||
/*!
|
||||
* \def PUT_UTF8(val, tmp, PUT_BYTE)
|
||||
* converts a 32-bit unicode character to its utf-8 encoded form (up to 4 bytes long).
|
||||
* \param val is an input only argument and should be of type uint32_t. It holds
|
||||
* a ucs4 encoded unicode character that is to be converted to utf-8. If
|
||||
* val is given as a function it's executed only once.
|
||||
* \param tmp is a temporary variable and should be of type uint8_t. It
|
||||
* represents an intermediate value during conversion that is to be
|
||||
* outputted by PUT_BYTE.
|
||||
* \param PUT_BYTE writes the converted utf-8 bytes to any proper destination.
|
||||
* It could be a function or a statement, and uses tmp as the input byte.
|
||||
* For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be
|
||||
* executed up to 4 times for values in the valid utf-8 range and up to
|
||||
* 7 times in the general case, depending on the length of the converted
|
||||
* unicode character.
|
||||
*/
|
||||
#define PUT_UTF8(val, tmp, PUT_BYTE)\
|
||||
{\
|
||||
int bytes, shift;\
|
||||
uint32_t in = val;\
|
||||
if (in < 0x80) {\
|
||||
tmp = in;\
|
||||
PUT_BYTE\
|
||||
} else {\
|
||||
bytes = (av_log2(in) + 4) / 5;\
|
||||
shift = (bytes - 1) * 6;\
|
||||
tmp = (256 - (256 >> bytes)) | (in >> shift);\
|
||||
PUT_BYTE\
|
||||
while (shift >= 6) {\
|
||||
shift -= 6;\
|
||||
tmp = 0x80 | ((in >> shift) & 0x3f);\
|
||||
PUT_BYTE\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
|
||||
#if defined(ARCH_X86) || defined(ARCH_POWERPC)
|
||||
#if defined(ARCH_X86_64)
|
||||
static inline uint64_t read_time(void)
|
||||
{
|
||||
uint64_t a, d;
|
||||
asm volatile( "rdtsc\n\t"
|
||||
: "=a" (a), "=d" (d)
|
||||
);
|
||||
return (d << 32) | (a & 0xffffffff);
|
||||
}
|
||||
#elif defined(ARCH_X86_32)
|
||||
static inline long long read_time(void)
|
||||
{
|
||||
long long l;
|
||||
asm volatile( "rdtsc\n\t"
|
||||
: "=A" (l)
|
||||
);
|
||||
return l;
|
||||
}
|
||||
#else //FIXME check ppc64
|
||||
static inline uint64_t read_time(void)
|
||||
{
|
||||
uint32_t tbu, tbl, temp;
|
||||
|
||||
/* from section 2.2.1 of the 32-bit PowerPC PEM */
|
||||
__asm__ __volatile__(
|
||||
"1:\n"
|
||||
"mftbu %2\n"
|
||||
"mftb %0\n"
|
||||
"mftbu %1\n"
|
||||
"cmpw %2,%1\n"
|
||||
"bne 1b\n"
|
||||
: "=r"(tbl), "=r"(tbu), "=r"(temp)
|
||||
:
|
||||
: "cc");
|
||||
|
||||
return (((uint64_t)tbu)<<32) | (uint64_t)tbl;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define START_TIMER \
|
||||
uint64_t tend;\
|
||||
uint64_t tstart= read_time();\
|
||||
|
||||
#define STOP_TIMER(id) \
|
||||
tend= read_time();\
|
||||
{\
|
||||
static uint64_t tsum=0;\
|
||||
static int tcount=0;\
|
||||
static int tskip_count=0;\
|
||||
if(tcount<2 || tend - tstart < FFMAX(8*tsum/tcount, 2000)){\
|
||||
tsum+= tend - tstart;\
|
||||
tcount++;\
|
||||
}else\
|
||||
tskip_count++;\
|
||||
if(((tcount+tskip_count)&(tcount+tskip_count-1))==0){\
|
||||
av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" dezicycles in %s, %d runs, %d skips\n", tsum*10/tcount, id, tcount, tskip_count);\
|
||||
}\
|
||||
}
|
||||
#else
|
||||
#define START_TIMER
|
||||
#define STOP_TIMER(id) {}
|
||||
#endif
|
||||
|
||||
#endif /* COMMON_H */
|
||||
|
||||
@@ -1,82 +1,82 @@
|
||||
/*
|
||||
* arbitrary precision integers
|
||||
* Copyright (c) 2004 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file integer.h
|
||||
* arbitrary precision integers
|
||||
* @author Michael Niedermayer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef INTEGER_H
|
||||
#define INTEGER_H
|
||||
|
||||
#define AV_INTEGER_SIZE 8
|
||||
|
||||
typedef struct AVInteger{
|
||||
uint16_t v[AV_INTEGER_SIZE];
|
||||
} AVInteger;
|
||||
|
||||
AVInteger av_add_i(AVInteger a, AVInteger b);
|
||||
AVInteger av_sub_i(AVInteger a, AVInteger b);
|
||||
|
||||
/**
|
||||
* returns the rounded down value of the logarithm of base 2 of the given AVInteger.
|
||||
* this is simply the index of the most significant bit which is 1. Or 0 of all bits are 0
|
||||
*/
|
||||
int av_log2_i(AVInteger a);
|
||||
AVInteger av_mul_i(AVInteger a, AVInteger b);
|
||||
|
||||
/**
|
||||
* returns 0 if a==b, 1 if a>b and -1 if a<b.
|
||||
*/
|
||||
int av_cmp_i(AVInteger a, AVInteger b);
|
||||
|
||||
/**
|
||||
* bitwise shift.
|
||||
* @param s the number of bits by which the value should be shifted right, may be negative for shifting left
|
||||
*/
|
||||
AVInteger av_shr_i(AVInteger a, int s);
|
||||
|
||||
/**
|
||||
* returns a % b.
|
||||
* @param quot a/b will be stored here
|
||||
*/
|
||||
AVInteger av_mod_i(AVInteger *quot, AVInteger a, AVInteger b);
|
||||
|
||||
/**
|
||||
* returns a/b.
|
||||
*/
|
||||
AVInteger av_div_i(AVInteger a, AVInteger b);
|
||||
|
||||
/**
|
||||
* converts the given int64_t to an AVInteger.
|
||||
*/
|
||||
AVInteger av_int2i(int64_t a);
|
||||
|
||||
/**
|
||||
* converts the given AVInteger to an int64_t.
|
||||
* if the AVInteger is too large to fit into an int64_t,
|
||||
* then only the least significant 64bit will be used
|
||||
*/
|
||||
int64_t av_i2int(AVInteger a);
|
||||
|
||||
#endif // INTEGER_H
|
||||
/*
|
||||
* arbitrary precision integers
|
||||
* Copyright (c) 2004 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file integer.h
|
||||
* arbitrary precision integers
|
||||
* @author Michael Niedermayer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef INTEGER_H
|
||||
#define INTEGER_H
|
||||
|
||||
#define AV_INTEGER_SIZE 8
|
||||
|
||||
typedef struct AVInteger{
|
||||
uint16_t v[AV_INTEGER_SIZE];
|
||||
} AVInteger;
|
||||
|
||||
AVInteger av_add_i(AVInteger a, AVInteger b);
|
||||
AVInteger av_sub_i(AVInteger a, AVInteger b);
|
||||
|
||||
/**
|
||||
* returns the rounded down value of the logarithm of base 2 of the given AVInteger.
|
||||
* this is simply the index of the most significant bit which is 1. Or 0 of all bits are 0
|
||||
*/
|
||||
int av_log2_i(AVInteger a);
|
||||
AVInteger av_mul_i(AVInteger a, AVInteger b);
|
||||
|
||||
/**
|
||||
* returns 0 if a==b, 1 if a>b and -1 if a<b.
|
||||
*/
|
||||
int av_cmp_i(AVInteger a, AVInteger b);
|
||||
|
||||
/**
|
||||
* bitwise shift.
|
||||
* @param s the number of bits by which the value should be shifted right, may be negative for shifting left
|
||||
*/
|
||||
AVInteger av_shr_i(AVInteger a, int s);
|
||||
|
||||
/**
|
||||
* returns a % b.
|
||||
* @param quot a/b will be stored here
|
||||
*/
|
||||
AVInteger av_mod_i(AVInteger *quot, AVInteger a, AVInteger b);
|
||||
|
||||
/**
|
||||
* returns a/b.
|
||||
*/
|
||||
AVInteger av_div_i(AVInteger a, AVInteger b);
|
||||
|
||||
/**
|
||||
* converts the given int64_t to an AVInteger.
|
||||
*/
|
||||
AVInteger av_int2i(int64_t a);
|
||||
|
||||
/**
|
||||
* converts the given AVInteger to an int64_t.
|
||||
* if the AVInteger is too large to fit into an int64_t,
|
||||
* then only the least significant 64bit will be used
|
||||
*/
|
||||
int64_t av_i2int(AVInteger a);
|
||||
|
||||
#endif // INTEGER_H
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
/*
|
||||
* copyright (c) 2005 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef INTFLOAT_READWRITE_H
|
||||
#define INTFLOAT_READWRITE_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* IEEE 80 bits extended float */
|
||||
typedef struct AVExtFloat {
|
||||
uint8_t exponent[2];
|
||||
uint8_t mantissa[8];
|
||||
} AVExtFloat;
|
||||
|
||||
double av_int2dbl(int64_t v);
|
||||
float av_int2flt(int32_t v);
|
||||
double av_ext2dbl(const AVExtFloat ext);
|
||||
int64_t av_dbl2int(double d);
|
||||
int32_t av_flt2int(float d);
|
||||
AVExtFloat av_dbl2ext(double d);
|
||||
|
||||
#endif /* INTFLOAT_READWRITE_H */
|
||||
/*
|
||||
* copyright (c) 2005 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef INTFLOAT_READWRITE_H
|
||||
#define INTFLOAT_READWRITE_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* IEEE 80 bits extended float */
|
||||
typedef struct AVExtFloat {
|
||||
uint8_t exponent[2];
|
||||
uint8_t mantissa[8];
|
||||
} AVExtFloat;
|
||||
|
||||
double av_int2dbl(int64_t v);
|
||||
float av_int2flt(int32_t v);
|
||||
double av_ext2dbl(const AVExtFloat ext);
|
||||
int64_t av_dbl2int(double d);
|
||||
int32_t av_flt2int(float d);
|
||||
AVExtFloat av_dbl2ext(double d);
|
||||
|
||||
#endif /* INTFLOAT_READWRITE_H */
|
||||
|
||||
+116
-116
@@ -1,116 +1,116 @@
|
||||
/*
|
||||
* copyright (c) 2006 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* Used by av_log
|
||||
*/
|
||||
typedef struct AVCLASS AVClass;
|
||||
struct AVCLASS {
|
||||
const char* class_name;
|
||||
const char* (*item_name)(void*); /* actually passing a pointer to an AVCodecContext
|
||||
or AVFormatContext, which begin with an AVClass.
|
||||
Needed because av_log is in libavcodec and has no visibility
|
||||
of AVIn/OutputFormat */
|
||||
const struct AVOption *option;
|
||||
};
|
||||
|
||||
/* av_log API */
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < (50<<16)
|
||||
#define AV_LOG_QUIET -1
|
||||
#define AV_LOG_FATAL 0
|
||||
#define AV_LOG_ERROR 0
|
||||
#define AV_LOG_WARNING 1
|
||||
#define AV_LOG_INFO 1
|
||||
#define AV_LOG_VERBOSE 1
|
||||
#define AV_LOG_DEBUG 2
|
||||
#else
|
||||
#define AV_LOG_QUIET -8
|
||||
|
||||
/**
|
||||
* something went really wrong and we will crash now
|
||||
*/
|
||||
#define AV_LOG_PANIC 0
|
||||
|
||||
/**
|
||||
* something went wrong and recovery is not possible
|
||||
* like no header in a format which depends on it or a combination
|
||||
* of parameters which are not allowed
|
||||
*/
|
||||
#define AV_LOG_FATAL 8
|
||||
|
||||
/**
|
||||
* something went wrong and cannot losslessly be recovered
|
||||
* but not all future data is affected
|
||||
*/
|
||||
#define AV_LOG_ERROR 16
|
||||
|
||||
/**
|
||||
* something somehow does not look correct / something which may or may not
|
||||
* lead to some problems like use of -vstrict -2
|
||||
*/
|
||||
#define AV_LOG_WARNING 24
|
||||
|
||||
#define AV_LOG_INFO 32
|
||||
#define AV_LOG_VERBOSE 40
|
||||
|
||||
/**
|
||||
* stuff which is only useful for libav* developers
|
||||
*/
|
||||
#define AV_LOG_DEBUG 48
|
||||
#endif
|
||||
extern int av_log_level;
|
||||
|
||||
/**
|
||||
* Send the specified message to the log if the level is less than or equal to
|
||||
* the current av_log_level. By default, all logging messages are sent to
|
||||
* stderr. This behavior can be altered by setting a different av_vlog callback
|
||||
* function.
|
||||
*
|
||||
* @param avcl A pointer to an arbitrary struct of which the first field is a
|
||||
* pointer to an AVClass struct.
|
||||
* @param level The importance level of the message, lower values signifying
|
||||
* higher importance.
|
||||
* @param fmt The format string (printf-compatible) that specifies how
|
||||
* subsequent arguments are converted to output.
|
||||
* @see av_vlog
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
extern void av_log(void*, int level, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
#else
|
||||
extern void av_log(void*, int level, const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < (50<<16)
|
||||
extern void av_vlog(void*, int level, const char *fmt, va_list);
|
||||
extern int av_log_get_level(void);
|
||||
extern void av_log_set_level(int);
|
||||
extern void av_log_set_callback(void (*)(void*, int, const char*, va_list));
|
||||
extern void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl);
|
||||
#else
|
||||
extern void (*av_vlog)(void*, int, const char*, va_list);
|
||||
#endif
|
||||
|
||||
#endif /* LOG_H */
|
||||
/*
|
||||
* copyright (c) 2006 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* Used by av_log
|
||||
*/
|
||||
typedef struct AVCLASS AVClass;
|
||||
struct AVCLASS {
|
||||
const char* class_name;
|
||||
const char* (*item_name)(void*); /* actually passing a pointer to an AVCodecContext
|
||||
or AVFormatContext, which begin with an AVClass.
|
||||
Needed because av_log is in libavcodec and has no visibility
|
||||
of AVIn/OutputFormat */
|
||||
const struct AVOption *option;
|
||||
};
|
||||
|
||||
/* av_log API */
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < (50<<16)
|
||||
#define AV_LOG_QUIET -1
|
||||
#define AV_LOG_FATAL 0
|
||||
#define AV_LOG_ERROR 0
|
||||
#define AV_LOG_WARNING 1
|
||||
#define AV_LOG_INFO 1
|
||||
#define AV_LOG_VERBOSE 1
|
||||
#define AV_LOG_DEBUG 2
|
||||
#else
|
||||
#define AV_LOG_QUIET -8
|
||||
|
||||
/**
|
||||
* something went really wrong and we will crash now
|
||||
*/
|
||||
#define AV_LOG_PANIC 0
|
||||
|
||||
/**
|
||||
* something went wrong and recovery is not possible
|
||||
* like no header in a format which depends on it or a combination
|
||||
* of parameters which are not allowed
|
||||
*/
|
||||
#define AV_LOG_FATAL 8
|
||||
|
||||
/**
|
||||
* something went wrong and cannot losslessly be recovered
|
||||
* but not all future data is affected
|
||||
*/
|
||||
#define AV_LOG_ERROR 16
|
||||
|
||||
/**
|
||||
* something somehow does not look correct / something which may or may not
|
||||
* lead to some problems like use of -vstrict -2
|
||||
*/
|
||||
#define AV_LOG_WARNING 24
|
||||
|
||||
#define AV_LOG_INFO 32
|
||||
#define AV_LOG_VERBOSE 40
|
||||
|
||||
/**
|
||||
* stuff which is only useful for libav* developers
|
||||
*/
|
||||
#define AV_LOG_DEBUG 48
|
||||
#endif
|
||||
extern int av_log_level;
|
||||
|
||||
/**
|
||||
* Send the specified message to the log if the level is less than or equal to
|
||||
* the current av_log_level. By default, all logging messages are sent to
|
||||
* stderr. This behavior can be altered by setting a different av_vlog callback
|
||||
* function.
|
||||
*
|
||||
* @param avcl A pointer to an arbitrary struct of which the first field is a
|
||||
* pointer to an AVClass struct.
|
||||
* @param level The importance level of the message, lower values signifying
|
||||
* higher importance.
|
||||
* @param fmt The format string (printf-compatible) that specifies how
|
||||
* subsequent arguments are converted to output.
|
||||
* @see av_vlog
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
extern void av_log(void*, int level, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
#else
|
||||
extern void av_log(void*, int level, const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < (50<<16)
|
||||
extern void av_vlog(void*, int level, const char *fmt, va_list);
|
||||
extern int av_log_get_level(void);
|
||||
extern void av_log_set_level(int);
|
||||
extern void av_log_set_callback(void (*)(void*, int, const char*, va_list));
|
||||
extern void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl);
|
||||
#else
|
||||
extern void (*av_vlog)(void*, int, const char*, va_list);
|
||||
#endif
|
||||
|
||||
#endif /* LOG_H */
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
/*
|
||||
* copyright (c) 2005 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MATHEMATICS_H
|
||||
#define MATHEMATICS_H
|
||||
|
||||
#include "rational.h"
|
||||
|
||||
enum AVRounding {
|
||||
AV_ROUND_ZERO = 0, ///< round toward zero
|
||||
AV_ROUND_INF = 1, ///< round away from zero
|
||||
AV_ROUND_DOWN = 2, ///< round toward -infinity
|
||||
AV_ROUND_UP = 3, ///< round toward +infinity
|
||||
AV_ROUND_NEAR_INF = 5, ///< round to nearest and halfway cases away from zero
|
||||
};
|
||||
|
||||
/**
|
||||
* rescale a 64bit integer with rounding to nearest.
|
||||
* a simple a*b/c isn't possible as it can overflow
|
||||
*/
|
||||
int64_t av_rescale(int64_t a, int64_t b, int64_t c);
|
||||
|
||||
/**
|
||||
* rescale a 64bit integer with specified rounding.
|
||||
* a simple a*b/c isn't possible as it can overflow
|
||||
*/
|
||||
int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding);
|
||||
|
||||
/**
|
||||
* rescale a 64bit integer by 2 rational numbers.
|
||||
*/
|
||||
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq);
|
||||
|
||||
#endif /* MATHEMATICS_H */
|
||||
/*
|
||||
* copyright (c) 2005 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MATHEMATICS_H
|
||||
#define MATHEMATICS_H
|
||||
|
||||
#include "rational.h"
|
||||
|
||||
enum AVRounding {
|
||||
AV_ROUND_ZERO = 0, ///< round toward zero
|
||||
AV_ROUND_INF = 1, ///< round away from zero
|
||||
AV_ROUND_DOWN = 2, ///< round toward -infinity
|
||||
AV_ROUND_UP = 3, ///< round toward +infinity
|
||||
AV_ROUND_NEAR_INF = 5, ///< round to nearest and halfway cases away from zero
|
||||
};
|
||||
|
||||
/**
|
||||
* rescale a 64bit integer with rounding to nearest.
|
||||
* a simple a*b/c isn't possible as it can overflow
|
||||
*/
|
||||
int64_t av_rescale(int64_t a, int64_t b, int64_t c);
|
||||
|
||||
/**
|
||||
* rescale a 64bit integer with specified rounding.
|
||||
* a simple a*b/c isn't possible as it can overflow
|
||||
*/
|
||||
int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding);
|
||||
|
||||
/**
|
||||
* rescale a 64bit integer by 2 rational numbers.
|
||||
*/
|
||||
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq);
|
||||
|
||||
#endif /* MATHEMATICS_H */
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
/*
|
||||
* copyright (c) 2006 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mem.h
|
||||
* Memory handling functions.
|
||||
*/
|
||||
|
||||
#ifndef AV_MEM_H
|
||||
#define AV_MEM_H
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define DECLARE_ALIGNED(n,t,v) t v __attribute__ ((aligned (n)))
|
||||
#else
|
||||
#define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Memory allocation of size byte with alignment suitable for all
|
||||
* memory accesses (including vectors if available on the
|
||||
* CPU). av_malloc(0) must return a non NULL pointer.
|
||||
*/
|
||||
void *av_malloc(unsigned int size);
|
||||
|
||||
/**
|
||||
* av_realloc semantics (same as glibc): if ptr is NULL and size > 0,
|
||||
* identical to malloc(size). If size is zero, it is identical to
|
||||
* free(ptr) and NULL is returned.
|
||||
*/
|
||||
void *av_realloc(void *ptr, unsigned int size);
|
||||
|
||||
/**
|
||||
* Free memory which has been allocated with av_malloc(z)() or av_realloc().
|
||||
* NOTE: ptr = NULL is explicetly allowed
|
||||
* Note2: it is recommended that you use av_freep() instead
|
||||
*/
|
||||
void av_free(void *ptr);
|
||||
|
||||
void *av_mallocz(unsigned int size);
|
||||
char *av_strdup(const char *s);
|
||||
|
||||
/**
|
||||
* Frees memory and sets the pointer to NULL.
|
||||
* @param ptr pointer to the pointer which should be freed
|
||||
*/
|
||||
void av_freep(void *ptr);
|
||||
|
||||
#endif /* AV_MEM_H */
|
||||
/*
|
||||
* copyright (c) 2006 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mem.h
|
||||
* Memory handling functions.
|
||||
*/
|
||||
|
||||
#ifndef AV_MEM_H
|
||||
#define AV_MEM_H
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define DECLARE_ALIGNED(n,t,v) t v __attribute__ ((aligned (n)))
|
||||
#else
|
||||
#define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Memory allocation of size byte with alignment suitable for all
|
||||
* memory accesses (including vectors if available on the
|
||||
* CPU). av_malloc(0) must return a non NULL pointer.
|
||||
*/
|
||||
void *av_malloc(unsigned int size);
|
||||
|
||||
/**
|
||||
* av_realloc semantics (same as glibc): if ptr is NULL and size > 0,
|
||||
* identical to malloc(size). If size is zero, it is identical to
|
||||
* free(ptr) and NULL is returned.
|
||||
*/
|
||||
void *av_realloc(void *ptr, unsigned int size);
|
||||
|
||||
/**
|
||||
* Free memory which has been allocated with av_malloc(z)() or av_realloc().
|
||||
* NOTE: ptr = NULL is explicetly allowed
|
||||
* Note2: it is recommended that you use av_freep() instead
|
||||
*/
|
||||
void av_free(void *ptr);
|
||||
|
||||
void *av_mallocz(unsigned int size);
|
||||
char *av_strdup(const char *s);
|
||||
|
||||
/**
|
||||
* Frees memory and sets the pointer to NULL.
|
||||
* @param ptr pointer to the pointer which should be freed
|
||||
*/
|
||||
void av_freep(void *ptr);
|
||||
|
||||
#endif /* AV_MEM_H */
|
||||
|
||||
@@ -1,114 +1,114 @@
|
||||
/*
|
||||
* Rational numbers
|
||||
* Copyright (c) 2003 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file rational.h
|
||||
* Rational numbers.
|
||||
* @author Michael Niedermayer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef RATIONAL_H
|
||||
#define RATIONAL_H
|
||||
|
||||
/**
|
||||
* Rational number num/den.
|
||||
*/
|
||||
typedef struct AVRational{
|
||||
int num; ///< numerator
|
||||
int den; ///< denominator
|
||||
} AVRational;
|
||||
|
||||
/**
|
||||
* Compare two rationals.
|
||||
* @param a first rational
|
||||
* @param b second rational
|
||||
* @return 0 if a==b, 1 if a>b and -1 if a<b.
|
||||
*/
|
||||
static inline int av_cmp_q(AVRational a, AVRational b){
|
||||
const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den;
|
||||
|
||||
if(tmp) return (int)((tmp>>63)|1);
|
||||
else return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rational to double conversion.
|
||||
* @param a rational to convert
|
||||
* @return (double) a
|
||||
*/
|
||||
static inline double av_q2d(AVRational a){
|
||||
return a.num / (double) a.den;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce a fraction.
|
||||
* This is useful for framerate calculations.
|
||||
* @param dst_nom destination numerator
|
||||
* @param dst_den destination denominator
|
||||
* @param nom source numerator
|
||||
* @param den source denominator
|
||||
* @param max the maximum allowed for dst_nom & dst_den
|
||||
* @return 1 if exact, 0 otherwise
|
||||
*/
|
||||
int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max);
|
||||
|
||||
/**
|
||||
* Multiplies two rationals.
|
||||
* @param b first rational.
|
||||
* @param c second rational.
|
||||
* @return b*c.
|
||||
*/
|
||||
AVRational av_mul_q(AVRational b, AVRational c);
|
||||
|
||||
/**
|
||||
* Divides one rational by another.
|
||||
* @param b first rational.
|
||||
* @param c second rational.
|
||||
* @return b/c.
|
||||
*/
|
||||
AVRational av_div_q(AVRational b, AVRational c);
|
||||
|
||||
/**
|
||||
* Adds two rationals.
|
||||
* @param b first rational.
|
||||
* @param c second rational.
|
||||
* @return b+c.
|
||||
*/
|
||||
AVRational av_add_q(AVRational b, AVRational c);
|
||||
|
||||
/**
|
||||
* Subtracts one rational from another.
|
||||
* @param b first rational.
|
||||
* @param c second rational.
|
||||
* returns b-c.
|
||||
*/
|
||||
AVRational av_sub_q(AVRational b, AVRational c);
|
||||
|
||||
/**
|
||||
* Converts a double precision floating point number to a rational.
|
||||
* @param d double to convert
|
||||
* @param max the maximum allowed numerator and denominator
|
||||
* @return (AVRational) d.
|
||||
*/
|
||||
AVRational av_d2q(double d, int max);
|
||||
|
||||
#endif // RATIONAL_H
|
||||
/*
|
||||
* Rational numbers
|
||||
* Copyright (c) 2003 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file rational.h
|
||||
* Rational numbers.
|
||||
* @author Michael Niedermayer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef RATIONAL_H
|
||||
#define RATIONAL_H
|
||||
|
||||
/**
|
||||
* Rational number num/den.
|
||||
*/
|
||||
typedef struct AVRational{
|
||||
int num; ///< numerator
|
||||
int den; ///< denominator
|
||||
} AVRational;
|
||||
|
||||
/**
|
||||
* Compare two rationals.
|
||||
* @param a first rational
|
||||
* @param b second rational
|
||||
* @return 0 if a==b, 1 if a>b and -1 if a<b.
|
||||
*/
|
||||
static inline int av_cmp_q(AVRational a, AVRational b){
|
||||
const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den;
|
||||
|
||||
if(tmp) return (int)((tmp>>63)|1);
|
||||
else return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rational to double conversion.
|
||||
* @param a rational to convert
|
||||
* @return (double) a
|
||||
*/
|
||||
static inline double av_q2d(AVRational a){
|
||||
return a.num / (double) a.den;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce a fraction.
|
||||
* This is useful for framerate calculations.
|
||||
* @param dst_nom destination numerator
|
||||
* @param dst_den destination denominator
|
||||
* @param nom source numerator
|
||||
* @param den source denominator
|
||||
* @param max the maximum allowed for dst_nom & dst_den
|
||||
* @return 1 if exact, 0 otherwise
|
||||
*/
|
||||
int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max);
|
||||
|
||||
/**
|
||||
* Multiplies two rationals.
|
||||
* @param b first rational.
|
||||
* @param c second rational.
|
||||
* @return b*c.
|
||||
*/
|
||||
AVRational av_mul_q(AVRational b, AVRational c);
|
||||
|
||||
/**
|
||||
* Divides one rational by another.
|
||||
* @param b first rational.
|
||||
* @param c second rational.
|
||||
* @return b/c.
|
||||
*/
|
||||
AVRational av_div_q(AVRational b, AVRational c);
|
||||
|
||||
/**
|
||||
* Adds two rationals.
|
||||
* @param b first rational.
|
||||
* @param c second rational.
|
||||
* @return b+c.
|
||||
*/
|
||||
AVRational av_add_q(AVRational b, AVRational c);
|
||||
|
||||
/**
|
||||
* Subtracts one rational from another.
|
||||
* @param b first rational.
|
||||
* @param c second rational.
|
||||
* returns b-c.
|
||||
*/
|
||||
AVRational av_sub_q(AVRational b, AVRational c);
|
||||
|
||||
/**
|
||||
* Converts a double precision floating point number to a rational.
|
||||
* @param d double to convert
|
||||
* @param max the maximum allowed numerator and denominator
|
||||
* @return (AVRational) d.
|
||||
*/
|
||||
AVRational av_d2q(double d, int max);
|
||||
|
||||
#endif // RATIONAL_H
|
||||
|
||||
+127
-127
@@ -1,127 +1,127 @@
|
||||
/*
|
||||
* RTP definitions
|
||||
* Copyright (c) 2002 Fabrice Bellard.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef RTP_H
|
||||
#define RTP_H
|
||||
|
||||
#define RTP_MIN_PACKET_LENGTH 12
|
||||
#define RTP_MAX_PACKET_LENGTH 1500 /* XXX: suppress this define */
|
||||
|
||||
int rtp_init(void);
|
||||
int rtp_get_codec_info(AVCodecContext *codec, int payload_type);
|
||||
|
||||
/** return < 0 if unknown payload type */
|
||||
int rtp_get_payload_type(AVCodecContext *codec);
|
||||
|
||||
typedef struct RTPDemuxContext RTPDemuxContext;
|
||||
typedef struct rtp_payload_data_s rtp_payload_data_s;
|
||||
RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, rtp_payload_data_s *rtp_payload_data);
|
||||
int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
|
||||
const uint8_t *buf, int len);
|
||||
void rtp_parse_close(RTPDemuxContext *s);
|
||||
|
||||
extern AVOutputFormat rtp_muxer;
|
||||
extern AVInputFormat rtp_demuxer;
|
||||
|
||||
int rtp_get_local_port(URLContext *h);
|
||||
int rtp_set_remote_url(URLContext *h, const char *uri);
|
||||
void rtp_get_file_handles(URLContext *h, int *prtp_fd, int *prtcp_fd);
|
||||
|
||||
/**
|
||||
* some rtp servers assume client is dead if they don't hear from them...
|
||||
* so we send a Receiver Report to the provided ByteIO context
|
||||
* (we don't have access to the rtcp handle from here)
|
||||
*/
|
||||
int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count);
|
||||
|
||||
extern URLProtocol rtp_protocol;
|
||||
|
||||
#define RTP_PT_PRIVATE 96
|
||||
#define RTP_VERSION 2
|
||||
#define RTP_MAX_SDES 256 /**< maximum text length for SDES */
|
||||
|
||||
/* RTCP paquets use 0.5 % of the bandwidth */
|
||||
#define RTCP_TX_RATIO_NUM 5
|
||||
#define RTCP_TX_RATIO_DEN 1000
|
||||
|
||||
/** Structure listing useful vars to parse RTP packet payload*/
|
||||
typedef struct rtp_payload_data_s
|
||||
{
|
||||
int sizelength;
|
||||
int indexlength;
|
||||
int indexdeltalength;
|
||||
int profile_level_id;
|
||||
int streamtype;
|
||||
int objecttype;
|
||||
char *mode;
|
||||
|
||||
/** mpeg 4 AU headers */
|
||||
struct AUHeaders {
|
||||
int size;
|
||||
int index;
|
||||
int cts_flag;
|
||||
int cts;
|
||||
int dts_flag;
|
||||
int dts;
|
||||
int rap_flag;
|
||||
int streamstate;
|
||||
} *au_headers;
|
||||
int nb_au_headers;
|
||||
int au_headers_length_bytes;
|
||||
int cur_au_index;
|
||||
} rtp_payload_data_t;
|
||||
|
||||
typedef struct AVRtpPayloadType_s
|
||||
{
|
||||
int pt;
|
||||
const char enc_name[50]; /* XXX: why 50 ? */
|
||||
enum CodecType codec_type;
|
||||
enum CodecID codec_id;
|
||||
int clock_rate;
|
||||
int audio_channels;
|
||||
} AVRtpPayloadType_t;
|
||||
|
||||
#if 0
|
||||
typedef enum {
|
||||
RTCP_SR = 200,
|
||||
RTCP_RR = 201,
|
||||
RTCP_SDES = 202,
|
||||
RTCP_BYE = 203,
|
||||
RTCP_APP = 204
|
||||
} rtcp_type_t;
|
||||
|
||||
typedef enum {
|
||||
RTCP_SDES_END = 0,
|
||||
RTCP_SDES_CNAME = 1,
|
||||
RTCP_SDES_NAME = 2,
|
||||
RTCP_SDES_EMAIL = 3,
|
||||
RTCP_SDES_PHONE = 4,
|
||||
RTCP_SDES_LOC = 5,
|
||||
RTCP_SDES_TOOL = 6,
|
||||
RTCP_SDES_NOTE = 7,
|
||||
RTCP_SDES_PRIV = 8,
|
||||
RTCP_SDES_IMG = 9,
|
||||
RTCP_SDES_DOOR = 10,
|
||||
RTCP_SDES_SOURCE = 11
|
||||
} rtcp_sdes_type_t;
|
||||
#endif
|
||||
|
||||
extern AVRtpPayloadType_t AVRtpPayloadTypes[];
|
||||
#endif /* RTP_H */
|
||||
/*
|
||||
* RTP definitions
|
||||
* Copyright (c) 2002 Fabrice Bellard.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef RTP_H
|
||||
#define RTP_H
|
||||
|
||||
#define RTP_MIN_PACKET_LENGTH 12
|
||||
#define RTP_MAX_PACKET_LENGTH 1500 /* XXX: suppress this define */
|
||||
|
||||
int rtp_init(void);
|
||||
int rtp_get_codec_info(AVCodecContext *codec, int payload_type);
|
||||
|
||||
/** return < 0 if unknown payload type */
|
||||
int rtp_get_payload_type(AVCodecContext *codec);
|
||||
|
||||
typedef struct RTPDemuxContext RTPDemuxContext;
|
||||
typedef struct rtp_payload_data_s rtp_payload_data_s;
|
||||
RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, rtp_payload_data_s *rtp_payload_data);
|
||||
int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
|
||||
const uint8_t *buf, int len);
|
||||
void rtp_parse_close(RTPDemuxContext *s);
|
||||
|
||||
extern AVOutputFormat rtp_muxer;
|
||||
extern AVInputFormat rtp_demuxer;
|
||||
|
||||
int rtp_get_local_port(URLContext *h);
|
||||
int rtp_set_remote_url(URLContext *h, const char *uri);
|
||||
void rtp_get_file_handles(URLContext *h, int *prtp_fd, int *prtcp_fd);
|
||||
|
||||
/**
|
||||
* some rtp servers assume client is dead if they don't hear from them...
|
||||
* so we send a Receiver Report to the provided ByteIO context
|
||||
* (we don't have access to the rtcp handle from here)
|
||||
*/
|
||||
int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count);
|
||||
|
||||
extern URLProtocol rtp_protocol;
|
||||
|
||||
#define RTP_PT_PRIVATE 96
|
||||
#define RTP_VERSION 2
|
||||
#define RTP_MAX_SDES 256 /**< maximum text length for SDES */
|
||||
|
||||
/* RTCP paquets use 0.5 % of the bandwidth */
|
||||
#define RTCP_TX_RATIO_NUM 5
|
||||
#define RTCP_TX_RATIO_DEN 1000
|
||||
|
||||
/** Structure listing useful vars to parse RTP packet payload*/
|
||||
typedef struct rtp_payload_data_s
|
||||
{
|
||||
int sizelength;
|
||||
int indexlength;
|
||||
int indexdeltalength;
|
||||
int profile_level_id;
|
||||
int streamtype;
|
||||
int objecttype;
|
||||
char *mode;
|
||||
|
||||
/** mpeg 4 AU headers */
|
||||
struct AUHeaders {
|
||||
int size;
|
||||
int index;
|
||||
int cts_flag;
|
||||
int cts;
|
||||
int dts_flag;
|
||||
int dts;
|
||||
int rap_flag;
|
||||
int streamstate;
|
||||
} *au_headers;
|
||||
int nb_au_headers;
|
||||
int au_headers_length_bytes;
|
||||
int cur_au_index;
|
||||
} rtp_payload_data_t;
|
||||
|
||||
typedef struct AVRtpPayloadType_s
|
||||
{
|
||||
int pt;
|
||||
const char enc_name[50]; /* XXX: why 50 ? */
|
||||
enum CodecType codec_type;
|
||||
enum CodecID codec_id;
|
||||
int clock_rate;
|
||||
int audio_channels;
|
||||
} AVRtpPayloadType_t;
|
||||
|
||||
#if 0
|
||||
typedef enum {
|
||||
RTCP_SR = 200,
|
||||
RTCP_RR = 201,
|
||||
RTCP_SDES = 202,
|
||||
RTCP_BYE = 203,
|
||||
RTCP_APP = 204
|
||||
} rtcp_type_t;
|
||||
|
||||
typedef enum {
|
||||
RTCP_SDES_END = 0,
|
||||
RTCP_SDES_CNAME = 1,
|
||||
RTCP_SDES_NAME = 2,
|
||||
RTCP_SDES_EMAIL = 3,
|
||||
RTCP_SDES_PHONE = 4,
|
||||
RTCP_SDES_LOC = 5,
|
||||
RTCP_SDES_TOOL = 6,
|
||||
RTCP_SDES_NOTE = 7,
|
||||
RTCP_SDES_PRIV = 8,
|
||||
RTCP_SDES_IMG = 9,
|
||||
RTCP_SDES_DOOR = 10,
|
||||
RTCP_SDES_SOURCE = 11
|
||||
} rtcp_sdes_type_t;
|
||||
#endif
|
||||
|
||||
extern AVRtpPayloadType_t AVRtpPayloadTypes[];
|
||||
#endif /* RTP_H */
|
||||
|
||||
@@ -1,94 +1,94 @@
|
||||
/*
|
||||
* RTSP definitions
|
||||
* Copyright (c) 2002 Fabrice Bellard.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef RTSP_H
|
||||
#define RTSP_H
|
||||
|
||||
#include "rtspcodes.h"
|
||||
|
||||
enum RTSPProtocol {
|
||||
RTSP_PROTOCOL_RTP_UDP = 0,
|
||||
RTSP_PROTOCOL_RTP_TCP = 1,
|
||||
RTSP_PROTOCOL_RTP_UDP_MULTICAST = 2,
|
||||
};
|
||||
|
||||
#define RTSP_DEFAULT_PORT 554
|
||||
#define RTSP_MAX_TRANSPORTS 8
|
||||
#define RTSP_TCP_MAX_PACKET_SIZE 1472
|
||||
#define RTSP_DEFAULT_NB_AUDIO_CHANNELS 2
|
||||
#define RTSP_DEFAULT_AUDIO_SAMPLERATE 44100
|
||||
#define RTSP_RTP_PORT_MIN 5000
|
||||
#define RTSP_RTP_PORT_MAX 10000
|
||||
|
||||
typedef struct RTSPTransportField {
|
||||
int interleaved_min, interleaved_max; /**< interleave ids, if TCP transport */
|
||||
int port_min, port_max; /**< RTP ports */
|
||||
int client_port_min, client_port_max; /**< RTP ports */
|
||||
int server_port_min, server_port_max; /**< RTP ports */
|
||||
int ttl; /**< ttl value */
|
||||
uint32_t destination; /**< destination IP address */
|
||||
enum RTSPProtocol protocol;
|
||||
} RTSPTransportField;
|
||||
|
||||
typedef struct RTSPHeader {
|
||||
int content_length;
|
||||
enum RTSPStatusCode status_code; /**< response code from server */
|
||||
int nb_transports;
|
||||
/** in AV_TIME_BASE unit, AV_NOPTS_VALUE if not used */
|
||||
int64_t range_start, range_end;
|
||||
RTSPTransportField transports[RTSP_MAX_TRANSPORTS];
|
||||
int seq; /**< sequence number */
|
||||
char session_id[512];
|
||||
} RTSPHeader;
|
||||
|
||||
/** the callback can be used to extend the connection setup/teardown step */
|
||||
enum RTSPCallbackAction {
|
||||
RTSP_ACTION_SERVER_SETUP,
|
||||
RTSP_ACTION_SERVER_TEARDOWN,
|
||||
RTSP_ACTION_CLIENT_SETUP,
|
||||
RTSP_ACTION_CLIENT_TEARDOWN,
|
||||
};
|
||||
|
||||
typedef struct RTSPActionServerSetup {
|
||||
uint32_t ipaddr;
|
||||
char transport_option[512];
|
||||
} RTSPActionServerSetup;
|
||||
|
||||
typedef int FFRTSPCallback(enum RTSPCallbackAction action,
|
||||
const char *session_id,
|
||||
char *buf, int buf_size,
|
||||
void *arg);
|
||||
|
||||
/** useful for modules: set RTSP callback function */
|
||||
void rtsp_set_callback(FFRTSPCallback *rtsp_cb);
|
||||
|
||||
int rtsp_init(void);
|
||||
void rtsp_parse_line(RTSPHeader *reply, const char *buf);
|
||||
|
||||
extern int rtsp_default_protocols;
|
||||
extern int rtsp_rtp_port_min;
|
||||
extern int rtsp_rtp_port_max;
|
||||
extern FFRTSPCallback *ff_rtsp_callback;
|
||||
extern AVInputFormat rtsp_demuxer;
|
||||
|
||||
int rtsp_pause(AVFormatContext *s);
|
||||
int rtsp_resume(AVFormatContext *s);
|
||||
|
||||
#endif /* RTSP_H */
|
||||
/*
|
||||
* RTSP definitions
|
||||
* Copyright (c) 2002 Fabrice Bellard.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef RTSP_H
|
||||
#define RTSP_H
|
||||
|
||||
#include "rtspcodes.h"
|
||||
|
||||
enum RTSPProtocol {
|
||||
RTSP_PROTOCOL_RTP_UDP = 0,
|
||||
RTSP_PROTOCOL_RTP_TCP = 1,
|
||||
RTSP_PROTOCOL_RTP_UDP_MULTICAST = 2,
|
||||
};
|
||||
|
||||
#define RTSP_DEFAULT_PORT 554
|
||||
#define RTSP_MAX_TRANSPORTS 8
|
||||
#define RTSP_TCP_MAX_PACKET_SIZE 1472
|
||||
#define RTSP_DEFAULT_NB_AUDIO_CHANNELS 2
|
||||
#define RTSP_DEFAULT_AUDIO_SAMPLERATE 44100
|
||||
#define RTSP_RTP_PORT_MIN 5000
|
||||
#define RTSP_RTP_PORT_MAX 10000
|
||||
|
||||
typedef struct RTSPTransportField {
|
||||
int interleaved_min, interleaved_max; /**< interleave ids, if TCP transport */
|
||||
int port_min, port_max; /**< RTP ports */
|
||||
int client_port_min, client_port_max; /**< RTP ports */
|
||||
int server_port_min, server_port_max; /**< RTP ports */
|
||||
int ttl; /**< ttl value */
|
||||
uint32_t destination; /**< destination IP address */
|
||||
enum RTSPProtocol protocol;
|
||||
} RTSPTransportField;
|
||||
|
||||
typedef struct RTSPHeader {
|
||||
int content_length;
|
||||
enum RTSPStatusCode status_code; /**< response code from server */
|
||||
int nb_transports;
|
||||
/** in AV_TIME_BASE unit, AV_NOPTS_VALUE if not used */
|
||||
int64_t range_start, range_end;
|
||||
RTSPTransportField transports[RTSP_MAX_TRANSPORTS];
|
||||
int seq; /**< sequence number */
|
||||
char session_id[512];
|
||||
} RTSPHeader;
|
||||
|
||||
/** the callback can be used to extend the connection setup/teardown step */
|
||||
enum RTSPCallbackAction {
|
||||
RTSP_ACTION_SERVER_SETUP,
|
||||
RTSP_ACTION_SERVER_TEARDOWN,
|
||||
RTSP_ACTION_CLIENT_SETUP,
|
||||
RTSP_ACTION_CLIENT_TEARDOWN,
|
||||
};
|
||||
|
||||
typedef struct RTSPActionServerSetup {
|
||||
uint32_t ipaddr;
|
||||
char transport_option[512];
|
||||
} RTSPActionServerSetup;
|
||||
|
||||
typedef int FFRTSPCallback(enum RTSPCallbackAction action,
|
||||
const char *session_id,
|
||||
char *buf, int buf_size,
|
||||
void *arg);
|
||||
|
||||
/** useful for modules: set RTSP callback function */
|
||||
void rtsp_set_callback(FFRTSPCallback *rtsp_cb);
|
||||
|
||||
int rtsp_init(void);
|
||||
void rtsp_parse_line(RTSPHeader *reply, const char *buf);
|
||||
|
||||
extern int rtsp_default_protocols;
|
||||
extern int rtsp_rtp_port_min;
|
||||
extern int rtsp_rtp_port_max;
|
||||
extern FFRTSPCallback *ff_rtsp_callback;
|
||||
extern AVInputFormat rtsp_demuxer;
|
||||
|
||||
int rtsp_pause(AVFormatContext *s);
|
||||
int rtsp_resume(AVFormatContext *s);
|
||||
|
||||
#endif /* RTSP_H */
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
/*
|
||||
* RTSP definitions
|
||||
* copyright (c) 2002 Fabrice Bellard
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/** RTSP handling */
|
||||
enum RTSPStatusCode {
|
||||
RTSP_STATUS_OK =200, /**< OK */
|
||||
RTSP_STATUS_METHOD =405, /**< Method Not Allowed */
|
||||
RTSP_STATUS_BANDWIDTH =453, /**< Not Enough Bandwidth */
|
||||
RTSP_STATUS_SESSION =454, /**< Session Not Found */
|
||||
RTSP_STATUS_STATE =455, /**< Method Not Valid in This State */
|
||||
RTSP_STATUS_AGGREGATE =459, /**< Aggregate operation not allowed */
|
||||
RTSP_STATUS_ONLY_AGGREGATE =460, /**< Only aggregate operation allowed */
|
||||
RTSP_STATUS_TRANSPORT =461, /**< Unsupported transport */
|
||||
RTSP_STATUS_INTERNAL =500, /**< Internal Server Error */
|
||||
RTSP_STATUS_SERVICE =503, /**< Service Unavailable */
|
||||
RTSP_STATUS_VERSION =505, /**< RTSP Version not supported */
|
||||
};
|
||||
|
||||
/*
|
||||
* RTSP definitions
|
||||
* copyright (c) 2002 Fabrice Bellard
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/** RTSP handling */
|
||||
enum RTSPStatusCode {
|
||||
RTSP_STATUS_OK =200, /**< OK */
|
||||
RTSP_STATUS_METHOD =405, /**< Method Not Allowed */
|
||||
RTSP_STATUS_BANDWIDTH =453, /**< Not Enough Bandwidth */
|
||||
RTSP_STATUS_SESSION =454, /**< Session Not Found */
|
||||
RTSP_STATUS_STATE =455, /**< Method Not Valid in This State */
|
||||
RTSP_STATUS_AGGREGATE =459, /**< Aggregate operation not allowed */
|
||||
RTSP_STATUS_ONLY_AGGREGATE =460, /**< Only aggregate operation allowed */
|
||||
RTSP_STATUS_TRANSPORT =461, /**< Unsupported transport */
|
||||
RTSP_STATUS_INTERNAL =500, /**< Internal Server Error */
|
||||
RTSP_STATUS_SERVICE =503, /**< Service Unavailable */
|
||||
RTSP_STATUS_VERSION =505, /**< RTSP Version not supported */
|
||||
};
|
||||
|
||||
|
||||
+117
-117
@@ -1,117 +1,117 @@
|
||||
* Introduction:
|
||||
=============
|
||||
|
||||
JSON (JavaScript Object Notation) is a lightweight data-interchange format.
|
||||
It can represent integer, real number, string, an ordered sequence of
|
||||
value, and a collection of name/value pairs.
|
||||
|
||||
JsonCpp is a simple API to manipulate JSON value, handle serialization
|
||||
and unserialization to string.
|
||||
|
||||
It can also preserve existing comment in unserialization/serialization steps,
|
||||
making it a convenient format to store user input files.
|
||||
|
||||
Unserialization parsing is user friendly and provides precise error reports.
|
||||
|
||||
|
||||
* Building/Testing:
|
||||
=================
|
||||
|
||||
JsonCpp uses Scons (http://www.scons.org) as a build system. Scons requires
|
||||
python to be installed (http://www.python.org).
|
||||
|
||||
You download scons-local distribution from the following url:
|
||||
http://sourceforge.net/project/showfiles.php?group_id=30337&package_id=67375
|
||||
|
||||
Unzip it in the directory where you found this README file. scons.py Should be
|
||||
at the same level as README.
|
||||
|
||||
python scons.py platform=PLTFRM [TARGET]
|
||||
where PLTFRM may be one of:
|
||||
suncc Sun C++ (Solaris)
|
||||
vacpp Visual Age C++ (AIX)
|
||||
mingw
|
||||
msvc6 Microsoft Visual Studio 6 service pack 5-6
|
||||
msvc70 Microsoft Visual Studio 2002
|
||||
msvc71 Microsoft Visual Studio 2003
|
||||
msvc80 Microsoft Visual Studio 2005
|
||||
linux-gcc Gnu C++ (linux, also reported to work for Mac OS X)
|
||||
|
||||
adding platform is fairly simple. You need to change the Sconstruct file
|
||||
to do so.
|
||||
|
||||
and TARGET may be:
|
||||
check: build library and run unit tests.
|
||||
|
||||
|
||||
* Running the test manually:
|
||||
==========================
|
||||
|
||||
cd test
|
||||
# This will run the Reader/Writer tests
|
||||
python runjsontests.py "path to jsontest.exe"
|
||||
|
||||
# This will run the Reader/Writer tests, using JSONChecker test suite
|
||||
# (http://www.json.org/JSON_checker/).
|
||||
# Notes: not all tests pass: JsonCpp is too lenient (for example,
|
||||
# it allows an integer to start with '0'). The goal is to improve
|
||||
# strict mode parsing to get all tests to pass.
|
||||
python runjsontests.py --with-json-checker "path to jsontest.exe"
|
||||
|
||||
# This will run the unit tests (mostly Value)
|
||||
python rununittests.py "path to test_lib_json.exe"
|
||||
|
||||
You can run the tests using valgrind:
|
||||
python rununittests.py --valgrind "path to test_lib_json.exe"
|
||||
|
||||
|
||||
* Building the documentation:
|
||||
===========================
|
||||
|
||||
Run the python script doxybuild.py from the top directory:
|
||||
|
||||
python doxybuild.py --open --with-dot
|
||||
|
||||
See doxybuild.py --help for options.
|
||||
|
||||
|
||||
* Adding a reader/writer test:
|
||||
============================
|
||||
|
||||
To add a test, you need to create two files in test/data:
|
||||
- a TESTNAME.json file, that contains the input document in JSON format.
|
||||
- a TESTNAME.expected file, that contains a flatened representation of
|
||||
the input document.
|
||||
|
||||
TESTNAME.expected file format:
|
||||
- each line represents a JSON element of the element tree represented
|
||||
by the input document.
|
||||
- each line has two parts: the path to access the element separated from
|
||||
the element value by '='. Array and object values are always empty
|
||||
(e.g. represented by either [] or {}).
|
||||
- element path: '.' represented the root element, and is used to separate
|
||||
object members. [N] is used to specify the value of an array element
|
||||
at index N.
|
||||
See test_complex_01.json and test_complex_01.expected to better understand
|
||||
element path.
|
||||
|
||||
|
||||
* Understanding reader/writer test output:
|
||||
========================================
|
||||
|
||||
When a test is run, output files are generated aside the input test files.
|
||||
Below is a short description of the content of each file:
|
||||
|
||||
- test_complex_01.json: input JSON document
|
||||
- test_complex_01.expected: flattened JSON element tree used to check if
|
||||
parsing was corrected.
|
||||
|
||||
- test_complex_01.actual: flattened JSON element tree produced by
|
||||
jsontest.exe from reading test_complex_01.json
|
||||
- test_complex_01.rewrite: JSON document written by jsontest.exe using the
|
||||
Json::Value parsed from test_complex_01.json and serialized using
|
||||
Json::StyledWritter.
|
||||
- test_complex_01.actual-rewrite: flattened JSON element tree produced by
|
||||
jsontest.exe from reading test_complex_01.rewrite.
|
||||
test_complex_01.process-output: jsontest.exe output, typically useful to
|
||||
understand parsing error.
|
||||
* Introduction:
|
||||
=============
|
||||
|
||||
JSON (JavaScript Object Notation) is a lightweight data-interchange format.
|
||||
It can represent integer, real number, string, an ordered sequence of
|
||||
value, and a collection of name/value pairs.
|
||||
|
||||
JsonCpp is a simple API to manipulate JSON value, handle serialization
|
||||
and unserialization to string.
|
||||
|
||||
It can also preserve existing comment in unserialization/serialization steps,
|
||||
making it a convenient format to store user input files.
|
||||
|
||||
Unserialization parsing is user friendly and provides precise error reports.
|
||||
|
||||
|
||||
* Building/Testing:
|
||||
=================
|
||||
|
||||
JsonCpp uses Scons (http://www.scons.org) as a build system. Scons requires
|
||||
python to be installed (http://www.python.org).
|
||||
|
||||
You download scons-local distribution from the following url:
|
||||
http://sourceforge.net/project/showfiles.php?group_id=30337&package_id=67375
|
||||
|
||||
Unzip it in the directory where you found this README file. scons.py Should be
|
||||
at the same level as README.
|
||||
|
||||
python scons.py platform=PLTFRM [TARGET]
|
||||
where PLTFRM may be one of:
|
||||
suncc Sun C++ (Solaris)
|
||||
vacpp Visual Age C++ (AIX)
|
||||
mingw
|
||||
msvc6 Microsoft Visual Studio 6 service pack 5-6
|
||||
msvc70 Microsoft Visual Studio 2002
|
||||
msvc71 Microsoft Visual Studio 2003
|
||||
msvc80 Microsoft Visual Studio 2005
|
||||
linux-gcc Gnu C++ (linux, also reported to work for Mac OS X)
|
||||
|
||||
adding platform is fairly simple. You need to change the Sconstruct file
|
||||
to do so.
|
||||
|
||||
and TARGET may be:
|
||||
check: build library and run unit tests.
|
||||
|
||||
|
||||
* Running the test manually:
|
||||
==========================
|
||||
|
||||
cd test
|
||||
# This will run the Reader/Writer tests
|
||||
python runjsontests.py "path to jsontest.exe"
|
||||
|
||||
# This will run the Reader/Writer tests, using JSONChecker test suite
|
||||
# (http://www.json.org/JSON_checker/).
|
||||
# Notes: not all tests pass: JsonCpp is too lenient (for example,
|
||||
# it allows an integer to start with '0'). The goal is to improve
|
||||
# strict mode parsing to get all tests to pass.
|
||||
python runjsontests.py --with-json-checker "path to jsontest.exe"
|
||||
|
||||
# This will run the unit tests (mostly Value)
|
||||
python rununittests.py "path to test_lib_json.exe"
|
||||
|
||||
You can run the tests using valgrind:
|
||||
python rununittests.py --valgrind "path to test_lib_json.exe"
|
||||
|
||||
|
||||
* Building the documentation:
|
||||
===========================
|
||||
|
||||
Run the python script doxybuild.py from the top directory:
|
||||
|
||||
python doxybuild.py --open --with-dot
|
||||
|
||||
See doxybuild.py --help for options.
|
||||
|
||||
|
||||
* Adding a reader/writer test:
|
||||
============================
|
||||
|
||||
To add a test, you need to create two files in test/data:
|
||||
- a TESTNAME.json file, that contains the input document in JSON format.
|
||||
- a TESTNAME.expected file, that contains a flatened representation of
|
||||
the input document.
|
||||
|
||||
TESTNAME.expected file format:
|
||||
- each line represents a JSON element of the element tree represented
|
||||
by the input document.
|
||||
- each line has two parts: the path to access the element separated from
|
||||
the element value by '='. Array and object values are always empty
|
||||
(e.g. represented by either [] or {}).
|
||||
- element path: '.' represented the root element, and is used to separate
|
||||
object members. [N] is used to specify the value of an array element
|
||||
at index N.
|
||||
See test_complex_01.json and test_complex_01.expected to better understand
|
||||
element path.
|
||||
|
||||
|
||||
* Understanding reader/writer test output:
|
||||
========================================
|
||||
|
||||
When a test is run, output files are generated aside the input test files.
|
||||
Below is a short description of the content of each file:
|
||||
|
||||
- test_complex_01.json: input JSON document
|
||||
- test_complex_01.expected: flattened JSON element tree used to check if
|
||||
parsing was corrected.
|
||||
|
||||
- test_complex_01.actual: flattened JSON element tree produced by
|
||||
jsontest.exe from reading test_complex_01.json
|
||||
- test_complex_01.rewrite: JSON document written by jsontest.exe using the
|
||||
Json::Value parsed from test_complex_01.json and serialized using
|
||||
Json::StyledWritter.
|
||||
- test_complex_01.actual-rewrite: flattened JSON element tree produced by
|
||||
jsontest.exe from reading test_complex_01.rewrite.
|
||||
test_complex_01.process-output: jsontest.exe output, typically useful to
|
||||
understand parsing error.
|
||||
|
||||
@@ -1 +1 @@
|
||||
The documentation is generated using doxygen (http://www.doxygen.org).
|
||||
The documentation is generated using doxygen (http://www.doxygen.org).
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#ifndef JSON_AUTOLINK_H_INCLUDED
|
||||
# define JSON_AUTOLINK_H_INCLUDED
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# ifdef JSON_IN_CPPTL
|
||||
# include <cpptl/cpptl_autolink.h>
|
||||
# endif
|
||||
|
||||
# if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && !defined(JSON_IN_CPPTL)
|
||||
# define CPPTL_AUTOLINK_NAME "json"
|
||||
# undef CPPTL_AUTOLINK_DLL
|
||||
# ifdef JSON_DLL
|
||||
# define CPPTL_AUTOLINK_DLL
|
||||
# endif
|
||||
# include "autolink.h"
|
||||
# endif
|
||||
|
||||
#endif // JSON_AUTOLINK_H_INCLUDED
|
||||
#ifndef JSON_AUTOLINK_H_INCLUDED
|
||||
# define JSON_AUTOLINK_H_INCLUDED
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# ifdef JSON_IN_CPPTL
|
||||
# include <cpptl/cpptl_autolink.h>
|
||||
# endif
|
||||
|
||||
# if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && !defined(JSON_IN_CPPTL)
|
||||
# define CPPTL_AUTOLINK_NAME "json"
|
||||
# undef CPPTL_AUTOLINK_DLL
|
||||
# ifdef JSON_DLL
|
||||
# define CPPTL_AUTOLINK_DLL
|
||||
# endif
|
||||
# include "autolink.h"
|
||||
# endif
|
||||
|
||||
#endif // JSON_AUTOLINK_H_INCLUDED
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
#ifndef JSON_CONFIG_H_INCLUDED
|
||||
# define JSON_CONFIG_H_INCLUDED
|
||||
|
||||
/// If defined, indicates that json library is embedded in CppTL library.
|
||||
//# define JSON_IN_CPPTL 1
|
||||
|
||||
/// If defined, indicates that json may leverage CppTL library
|
||||
//# define JSON_USE_CPPTL 1
|
||||
/// If defined, indicates that cpptl vector based map should be used instead of std::map
|
||||
/// as Value container.
|
||||
//# define JSON_USE_CPPTL_SMALLMAP 1
|
||||
/// If defined, indicates that Json specific container should be used
|
||||
/// (hash table & simple deque container with customizable allocator).
|
||||
/// THIS FEATURE IS STILL EXPERIMENTAL!
|
||||
//# define JSON_VALUE_USE_INTERNAL_MAP 1
|
||||
/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
|
||||
/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
|
||||
/// as if it was a POD) that may cause some validation tool to report errors.
|
||||
/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
|
||||
//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
|
||||
|
||||
/// If defined, indicates that Json use exception to report invalid type manipulation
|
||||
/// instead of C assert macro.
|
||||
# define JSON_USE_EXCEPTION 1
|
||||
|
||||
# ifdef JSON_IN_CPPTL
|
||||
# include <cpptl/config.h>
|
||||
# ifndef JSON_USE_CPPTL
|
||||
# define JSON_USE_CPPTL 1
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef JSON_IN_CPPTL
|
||||
# define JSON_API CPPTL_API
|
||||
# elif defined(JSON_DLL_BUILD)
|
||||
# define JSON_API __declspec(dllexport)
|
||||
# elif defined(JSON_DLL)
|
||||
# define JSON_API __declspec(dllimport)
|
||||
# else
|
||||
# define JSON_API
|
||||
# endif
|
||||
|
||||
#endif // JSON_CONFIG_H_INCLUDED
|
||||
#ifndef JSON_CONFIG_H_INCLUDED
|
||||
# define JSON_CONFIG_H_INCLUDED
|
||||
|
||||
/// If defined, indicates that json library is embedded in CppTL library.
|
||||
//# define JSON_IN_CPPTL 1
|
||||
|
||||
/// If defined, indicates that json may leverage CppTL library
|
||||
//# define JSON_USE_CPPTL 1
|
||||
/// If defined, indicates that cpptl vector based map should be used instead of std::map
|
||||
/// as Value container.
|
||||
//# define JSON_USE_CPPTL_SMALLMAP 1
|
||||
/// If defined, indicates that Json specific container should be used
|
||||
/// (hash table & simple deque container with customizable allocator).
|
||||
/// THIS FEATURE IS STILL EXPERIMENTAL!
|
||||
//# define JSON_VALUE_USE_INTERNAL_MAP 1
|
||||
/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
|
||||
/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
|
||||
/// as if it was a POD) that may cause some validation tool to report errors.
|
||||
/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
|
||||
//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
|
||||
|
||||
/// If defined, indicates that Json use exception to report invalid type manipulation
|
||||
/// instead of C assert macro.
|
||||
# define JSON_USE_EXCEPTION 1
|
||||
|
||||
# ifdef JSON_IN_CPPTL
|
||||
# include <cpptl/config.h>
|
||||
# ifndef JSON_USE_CPPTL
|
||||
# define JSON_USE_CPPTL 1
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef JSON_IN_CPPTL
|
||||
# define JSON_API CPPTL_API
|
||||
# elif defined(JSON_DLL_BUILD)
|
||||
# define JSON_API __declspec(dllexport)
|
||||
# elif defined(JSON_DLL)
|
||||
# define JSON_API __declspec(dllimport)
|
||||
# else
|
||||
# define JSON_API
|
||||
# endif
|
||||
|
||||
#endif // JSON_CONFIG_H_INCLUDED
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
|
||||
# define CPPTL_JSON_FEATURES_H_INCLUDED
|
||||
|
||||
# include "forwards.h"
|
||||
|
||||
namespace Json {
|
||||
|
||||
/** \brief Configuration passed to reader and writer.
|
||||
* This configuration object can be used to force the Reader or Writer
|
||||
* to behave in a standard conforming way.
|
||||
*/
|
||||
class JSON_API Features
|
||||
{
|
||||
public:
|
||||
/** \brief A configuration that allows all features and assumes all strings are UTF-8.
|
||||
* - C & C++ comments are allowed
|
||||
* - Root object can be any JSON value
|
||||
* - Assumes Value strings are encoded in UTF-8
|
||||
*/
|
||||
static Features all();
|
||||
|
||||
/** \brief A configuration that is strictly compatible with the JSON specification.
|
||||
* - Comments are forbidden.
|
||||
* - Root object must be either an array or an object value.
|
||||
* - Assumes Value strings are encoded in UTF-8
|
||||
*/
|
||||
static Features strictMode();
|
||||
|
||||
/** \brief Initialize the configuration like JsonConfig::allFeatures;
|
||||
*/
|
||||
Features();
|
||||
|
||||
/// \c true if comments are allowed. Default: \c true.
|
||||
bool allowComments_;
|
||||
|
||||
/// \c true if root must be either an array or an object value. Default: \c false.
|
||||
bool strictRoot_;
|
||||
};
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
|
||||
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
|
||||
# define CPPTL_JSON_FEATURES_H_INCLUDED
|
||||
|
||||
# include "forwards.h"
|
||||
|
||||
namespace Json {
|
||||
|
||||
/** \brief Configuration passed to reader and writer.
|
||||
* This configuration object can be used to force the Reader or Writer
|
||||
* to behave in a standard conforming way.
|
||||
*/
|
||||
class JSON_API Features
|
||||
{
|
||||
public:
|
||||
/** \brief A configuration that allows all features and assumes all strings are UTF-8.
|
||||
* - C & C++ comments are allowed
|
||||
* - Root object can be any JSON value
|
||||
* - Assumes Value strings are encoded in UTF-8
|
||||
*/
|
||||
static Features all();
|
||||
|
||||
/** \brief A configuration that is strictly compatible with the JSON specification.
|
||||
* - Comments are forbidden.
|
||||
* - Root object must be either an array or an object value.
|
||||
* - Assumes Value strings are encoded in UTF-8
|
||||
*/
|
||||
static Features strictMode();
|
||||
|
||||
/** \brief Initialize the configuration like JsonConfig::allFeatures;
|
||||
*/
|
||||
Features();
|
||||
|
||||
/// \c true if comments are allowed. Default: \c true.
|
||||
bool allowComments_;
|
||||
|
||||
/// \c true if root must be either an array or an object value. Default: \c false.
|
||||
bool strictRoot_;
|
||||
};
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
#ifndef JSON_FORWARDS_H_INCLUDED
|
||||
# define JSON_FORWARDS_H_INCLUDED
|
||||
|
||||
# include "config.h"
|
||||
|
||||
namespace Json {
|
||||
|
||||
// writer.h
|
||||
class FastWriter;
|
||||
class StyledWriter;
|
||||
|
||||
// reader.h
|
||||
class Reader;
|
||||
|
||||
// features.h
|
||||
class Features;
|
||||
|
||||
// value.h
|
||||
typedef int Int;
|
||||
typedef unsigned int UInt;
|
||||
class StaticString;
|
||||
class Path;
|
||||
class PathArgument;
|
||||
class Value;
|
||||
class ValueIteratorBase;
|
||||
class ValueIterator;
|
||||
class ValueConstIterator;
|
||||
#ifdef JSON_VALUE_USE_INTERNAL_MAP
|
||||
class ValueAllocator;
|
||||
class ValueMapAllocator;
|
||||
class ValueInternalLink;
|
||||
class ValueInternalArray;
|
||||
class ValueInternalMap;
|
||||
#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
|
||||
|
||||
} // namespace Json
|
||||
|
||||
|
||||
#endif // JSON_FORWARDS_H_INCLUDED
|
||||
#ifndef JSON_FORWARDS_H_INCLUDED
|
||||
# define JSON_FORWARDS_H_INCLUDED
|
||||
|
||||
# include "config.h"
|
||||
|
||||
namespace Json {
|
||||
|
||||
// writer.h
|
||||
class FastWriter;
|
||||
class StyledWriter;
|
||||
|
||||
// reader.h
|
||||
class Reader;
|
||||
|
||||
// features.h
|
||||
class Features;
|
||||
|
||||
// value.h
|
||||
typedef int Int;
|
||||
typedef unsigned int UInt;
|
||||
class StaticString;
|
||||
class Path;
|
||||
class PathArgument;
|
||||
class Value;
|
||||
class ValueIteratorBase;
|
||||
class ValueIterator;
|
||||
class ValueConstIterator;
|
||||
#ifdef JSON_VALUE_USE_INTERNAL_MAP
|
||||
class ValueAllocator;
|
||||
class ValueMapAllocator;
|
||||
class ValueInternalLink;
|
||||
class ValueInternalArray;
|
||||
class ValueInternalMap;
|
||||
#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
|
||||
|
||||
} // namespace Json
|
||||
|
||||
|
||||
#endif // JSON_FORWARDS_H_INCLUDED
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef JSON_JSON_H_INCLUDED
|
||||
# define JSON_JSON_H_INCLUDED
|
||||
|
||||
# include "autolink.h"
|
||||
# include "value.h"
|
||||
# include "reader.h"
|
||||
# include "writer.h"
|
||||
# include "features.h"
|
||||
|
||||
#endif // JSON_JSON_H_INCLUDED
|
||||
#ifndef JSON_JSON_H_INCLUDED
|
||||
# define JSON_JSON_H_INCLUDED
|
||||
|
||||
# include "autolink.h"
|
||||
# include "value.h"
|
||||
# include "reader.h"
|
||||
# include "writer.h"
|
||||
# include "features.h"
|
||||
|
||||
#endif // JSON_JSON_H_INCLUDED
|
||||
|
||||
+196
-196
@@ -1,196 +1,196 @@
|
||||
#ifndef CPPTL_JSON_READER_H_INCLUDED
|
||||
# define CPPTL_JSON_READER_H_INCLUDED
|
||||
|
||||
# include "features.h"
|
||||
# include "value.h"
|
||||
# include <deque>
|
||||
# include <stack>
|
||||
# include <string>
|
||||
# include <iostream>
|
||||
|
||||
namespace Json {
|
||||
|
||||
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
|
||||
*
|
||||
*/
|
||||
class JSON_API Reader
|
||||
{
|
||||
public:
|
||||
typedef char Char;
|
||||
typedef const Char *Location;
|
||||
|
||||
/** \brief Constructs a Reader allowing all features
|
||||
* for parsing.
|
||||
*/
|
||||
Reader();
|
||||
|
||||
/** \brief Constructs a Reader allowing the specified feature set
|
||||
* for parsing.
|
||||
*/
|
||||
Reader( const Features &features );
|
||||
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
|
||||
* \param document UTF-8 encoded string containing the document to read.
|
||||
* \param root [out] Contains the root value of the document if it was
|
||||
* successfully parsed.
|
||||
* \param collectComments \c true to collect comment and allow writing them back during
|
||||
* serialization, \c false to discard comments.
|
||||
* This parameter is ignored if Features::allowComments_
|
||||
* is \c false.
|
||||
* \return \c true if the document was successfully parsed, \c false if an error occurred.
|
||||
*/
|
||||
bool parse( const std::string &document,
|
||||
Value &root,
|
||||
bool collectComments = true );
|
||||
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
|
||||
* \param document UTF-8 encoded string containing the document to read.
|
||||
* \param root [out] Contains the root value of the document if it was
|
||||
* successfully parsed.
|
||||
* \param collectComments \c true to collect comment and allow writing them back during
|
||||
* serialization, \c false to discard comments.
|
||||
* This parameter is ignored if Features::allowComments_
|
||||
* is \c false.
|
||||
* \return \c true if the document was successfully parsed, \c false if an error occurred.
|
||||
*/
|
||||
bool parse( const char *beginDoc, const char *endDoc,
|
||||
Value &root,
|
||||
bool collectComments = true );
|
||||
|
||||
/// \brief Parse from input stream.
|
||||
/// \see Json::operator>>(std::istream&, Json::Value&).
|
||||
bool parse( std::istream &is,
|
||||
Value &root,
|
||||
bool collectComments = true );
|
||||
|
||||
/** \brief Returns a user friendly string that list errors in the parsed document.
|
||||
* \return Formatted error message with the list of errors with their location in
|
||||
* the parsed document. An empty string is returned if no error occurred
|
||||
* during parsing.
|
||||
*/
|
||||
std::string getFormatedErrorMessages() const;
|
||||
|
||||
private:
|
||||
enum TokenType
|
||||
{
|
||||
tokenEndOfStream = 0,
|
||||
tokenObjectBegin,
|
||||
tokenObjectEnd,
|
||||
tokenArrayBegin,
|
||||
tokenArrayEnd,
|
||||
tokenString,
|
||||
tokenNumber,
|
||||
tokenTrue,
|
||||
tokenFalse,
|
||||
tokenNull,
|
||||
tokenArraySeparator,
|
||||
tokenMemberSeparator,
|
||||
tokenComment,
|
||||
tokenError
|
||||
};
|
||||
|
||||
class Token
|
||||
{
|
||||
public:
|
||||
TokenType type_;
|
||||
Location start_;
|
||||
Location end_;
|
||||
};
|
||||
|
||||
class ErrorInfo
|
||||
{
|
||||
public:
|
||||
Token token_;
|
||||
std::string message_;
|
||||
Location extra_;
|
||||
};
|
||||
|
||||
typedef std::deque<ErrorInfo> Errors;
|
||||
|
||||
bool expectToken( TokenType type, Token &token, const char *message );
|
||||
bool readToken( Token &token );
|
||||
void skipSpaces();
|
||||
bool match( Location pattern,
|
||||
int patternLength );
|
||||
bool readComment();
|
||||
bool readCStyleComment();
|
||||
bool readCppStyleComment();
|
||||
bool readString();
|
||||
void readNumber();
|
||||
bool readValue();
|
||||
bool readObject( Token &token );
|
||||
bool readArray( Token &token );
|
||||
bool decodeNumber( Token &token );
|
||||
bool decodeString( Token &token );
|
||||
bool decodeString( Token &token, std::string &decoded );
|
||||
bool decodeDouble( Token &token );
|
||||
bool decodeUnicodeCodePoint( Token &token,
|
||||
Location ¤t,
|
||||
Location end,
|
||||
unsigned int &unicode );
|
||||
bool decodeUnicodeEscapeSequence( Token &token,
|
||||
Location ¤t,
|
||||
Location end,
|
||||
unsigned int &unicode );
|
||||
bool addError( const std::string &message,
|
||||
Token &token,
|
||||
Location extra = 0 );
|
||||
bool recoverFromError( TokenType skipUntilToken );
|
||||
bool addErrorAndRecover( const std::string &message,
|
||||
Token &token,
|
||||
TokenType skipUntilToken );
|
||||
void skipUntilSpace();
|
||||
Value ¤tValue();
|
||||
Char getNextChar();
|
||||
void getLocationLineAndColumn( Location location,
|
||||
int &line,
|
||||
int &column ) const;
|
||||
std::string getLocationLineAndColumn( Location location ) const;
|
||||
void addComment( Location begin,
|
||||
Location end,
|
||||
CommentPlacement placement );
|
||||
void skipCommentTokens( Token &token );
|
||||
|
||||
typedef std::stack<Value *> Nodes;
|
||||
Nodes nodes_;
|
||||
Errors errors_;
|
||||
std::string document_;
|
||||
Location begin_;
|
||||
Location end_;
|
||||
Location current_;
|
||||
Location lastValueEnd_;
|
||||
Value *lastValue_;
|
||||
std::string commentsBefore_;
|
||||
Features features_;
|
||||
bool collectComments_;
|
||||
};
|
||||
|
||||
/** \brief Read from 'sin' into 'root'.
|
||||
|
||||
Always keep comments from the input JSON.
|
||||
|
||||
This can be used to read a file into a particular sub-object.
|
||||
For example:
|
||||
\code
|
||||
Json::Value root;
|
||||
cin >> root["dir"]["file"];
|
||||
cout << root;
|
||||
\endcode
|
||||
Result:
|
||||
\verbatim
|
||||
{
|
||||
"dir": {
|
||||
"file": {
|
||||
// The input stream JSON would be nested here.
|
||||
}
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
\throw std::exception on parse error.
|
||||
\see Json::operator<<()
|
||||
*/
|
||||
std::istream& operator>>( std::istream&, Value& );
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#endif // CPPTL_JSON_READER_H_INCLUDED
|
||||
#ifndef CPPTL_JSON_READER_H_INCLUDED
|
||||
# define CPPTL_JSON_READER_H_INCLUDED
|
||||
|
||||
# include "features.h"
|
||||
# include "value.h"
|
||||
# include <deque>
|
||||
# include <stack>
|
||||
# include <string>
|
||||
# include <iostream>
|
||||
|
||||
namespace Json {
|
||||
|
||||
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
|
||||
*
|
||||
*/
|
||||
class JSON_API Reader
|
||||
{
|
||||
public:
|
||||
typedef char Char;
|
||||
typedef const Char *Location;
|
||||
|
||||
/** \brief Constructs a Reader allowing all features
|
||||
* for parsing.
|
||||
*/
|
||||
Reader();
|
||||
|
||||
/** \brief Constructs a Reader allowing the specified feature set
|
||||
* for parsing.
|
||||
*/
|
||||
Reader( const Features &features );
|
||||
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
|
||||
* \param document UTF-8 encoded string containing the document to read.
|
||||
* \param root [out] Contains the root value of the document if it was
|
||||
* successfully parsed.
|
||||
* \param collectComments \c true to collect comment and allow writing them back during
|
||||
* serialization, \c false to discard comments.
|
||||
* This parameter is ignored if Features::allowComments_
|
||||
* is \c false.
|
||||
* \return \c true if the document was successfully parsed, \c false if an error occurred.
|
||||
*/
|
||||
bool parse( const std::string &document,
|
||||
Value &root,
|
||||
bool collectComments = true );
|
||||
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
|
||||
* \param document UTF-8 encoded string containing the document to read.
|
||||
* \param root [out] Contains the root value of the document if it was
|
||||
* successfully parsed.
|
||||
* \param collectComments \c true to collect comment and allow writing them back during
|
||||
* serialization, \c false to discard comments.
|
||||
* This parameter is ignored if Features::allowComments_
|
||||
* is \c false.
|
||||
* \return \c true if the document was successfully parsed, \c false if an error occurred.
|
||||
*/
|
||||
bool parse( const char *beginDoc, const char *endDoc,
|
||||
Value &root,
|
||||
bool collectComments = true );
|
||||
|
||||
/// \brief Parse from input stream.
|
||||
/// \see Json::operator>>(std::istream&, Json::Value&).
|
||||
bool parse( std::istream &is,
|
||||
Value &root,
|
||||
bool collectComments = true );
|
||||
|
||||
/** \brief Returns a user friendly string that list errors in the parsed document.
|
||||
* \return Formatted error message with the list of errors with their location in
|
||||
* the parsed document. An empty string is returned if no error occurred
|
||||
* during parsing.
|
||||
*/
|
||||
std::string getFormatedErrorMessages() const;
|
||||
|
||||
private:
|
||||
enum TokenType
|
||||
{
|
||||
tokenEndOfStream = 0,
|
||||
tokenObjectBegin,
|
||||
tokenObjectEnd,
|
||||
tokenArrayBegin,
|
||||
tokenArrayEnd,
|
||||
tokenString,
|
||||
tokenNumber,
|
||||
tokenTrue,
|
||||
tokenFalse,
|
||||
tokenNull,
|
||||
tokenArraySeparator,
|
||||
tokenMemberSeparator,
|
||||
tokenComment,
|
||||
tokenError
|
||||
};
|
||||
|
||||
class Token
|
||||
{
|
||||
public:
|
||||
TokenType type_;
|
||||
Location start_;
|
||||
Location end_;
|
||||
};
|
||||
|
||||
class ErrorInfo
|
||||
{
|
||||
public:
|
||||
Token token_;
|
||||
std::string message_;
|
||||
Location extra_;
|
||||
};
|
||||
|
||||
typedef std::deque<ErrorInfo> Errors;
|
||||
|
||||
bool expectToken( TokenType type, Token &token, const char *message );
|
||||
bool readToken( Token &token );
|
||||
void skipSpaces();
|
||||
bool match( Location pattern,
|
||||
int patternLength );
|
||||
bool readComment();
|
||||
bool readCStyleComment();
|
||||
bool readCppStyleComment();
|
||||
bool readString();
|
||||
void readNumber();
|
||||
bool readValue();
|
||||
bool readObject( Token &token );
|
||||
bool readArray( Token &token );
|
||||
bool decodeNumber( Token &token );
|
||||
bool decodeString( Token &token );
|
||||
bool decodeString( Token &token, std::string &decoded );
|
||||
bool decodeDouble( Token &token );
|
||||
bool decodeUnicodeCodePoint( Token &token,
|
||||
Location ¤t,
|
||||
Location end,
|
||||
unsigned int &unicode );
|
||||
bool decodeUnicodeEscapeSequence( Token &token,
|
||||
Location ¤t,
|
||||
Location end,
|
||||
unsigned int &unicode );
|
||||
bool addError( const std::string &message,
|
||||
Token &token,
|
||||
Location extra = 0 );
|
||||
bool recoverFromError( TokenType skipUntilToken );
|
||||
bool addErrorAndRecover( const std::string &message,
|
||||
Token &token,
|
||||
TokenType skipUntilToken );
|
||||
void skipUntilSpace();
|
||||
Value ¤tValue();
|
||||
Char getNextChar();
|
||||
void getLocationLineAndColumn( Location location,
|
||||
int &line,
|
||||
int &column ) const;
|
||||
std::string getLocationLineAndColumn( Location location ) const;
|
||||
void addComment( Location begin,
|
||||
Location end,
|
||||
CommentPlacement placement );
|
||||
void skipCommentTokens( Token &token );
|
||||
|
||||
typedef std::stack<Value *> Nodes;
|
||||
Nodes nodes_;
|
||||
Errors errors_;
|
||||
std::string document_;
|
||||
Location begin_;
|
||||
Location end_;
|
||||
Location current_;
|
||||
Location lastValueEnd_;
|
||||
Value *lastValue_;
|
||||
std::string commentsBefore_;
|
||||
Features features_;
|
||||
bool collectComments_;
|
||||
};
|
||||
|
||||
/** \brief Read from 'sin' into 'root'.
|
||||
|
||||
Always keep comments from the input JSON.
|
||||
|
||||
This can be used to read a file into a particular sub-object.
|
||||
For example:
|
||||
\code
|
||||
Json::Value root;
|
||||
cin >> root["dir"]["file"];
|
||||
cout << root;
|
||||
\endcode
|
||||
Result:
|
||||
\verbatim
|
||||
{
|
||||
"dir": {
|
||||
"file": {
|
||||
// The input stream JSON would be nested here.
|
||||
}
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
\throw std::exception on parse error.
|
||||
\see Json::operator<<()
|
||||
*/
|
||||
std::istream& operator>>( std::istream&, Value& );
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#endif // CPPTL_JSON_READER_H_INCLUDED
|
||||
|
||||
+1069
-1069
File diff suppressed because it is too large
Load Diff
+174
-174
@@ -1,174 +1,174 @@
|
||||
#ifndef JSON_WRITER_H_INCLUDED
|
||||
# define JSON_WRITER_H_INCLUDED
|
||||
|
||||
# include "value.h"
|
||||
# include <vector>
|
||||
# include <string>
|
||||
# include <iostream>
|
||||
|
||||
namespace Json {
|
||||
|
||||
class Value;
|
||||
|
||||
/** \brief Abstract class for writers.
|
||||
*/
|
||||
class JSON_API Writer
|
||||
{
|
||||
public:
|
||||
virtual ~Writer();
|
||||
|
||||
virtual std::string write( const Value &root ) = 0;
|
||||
};
|
||||
|
||||
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
|
||||
*
|
||||
* The JSON document is written in a single line. It is not intended for 'human' consumption,
|
||||
* but may be usefull to support feature such as RPC where bandwith is limited.
|
||||
* \sa Reader, Value
|
||||
*/
|
||||
class JSON_API FastWriter : public Writer
|
||||
{
|
||||
public:
|
||||
FastWriter();
|
||||
virtual ~FastWriter(){}
|
||||
|
||||
void enableYAMLCompatibility();
|
||||
|
||||
public: // overridden from Writer
|
||||
virtual std::string write( const Value &root );
|
||||
|
||||
private:
|
||||
void writeValue( const Value &value );
|
||||
|
||||
std::string document_;
|
||||
bool yamlCompatiblityEnabled_;
|
||||
};
|
||||
|
||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
|
||||
*
|
||||
* The rules for line break and indent are as follow:
|
||||
* - Object value:
|
||||
* - if empty then print {} without indent and line break
|
||||
* - if not empty the print '{', line break & indent, print one value per line
|
||||
* and then unindent and line break and print '}'.
|
||||
* - Array value:
|
||||
* - if empty then print [] without indent and line break
|
||||
* - if the array contains no object value, empty array or some other value types,
|
||||
* and all the values fit on one lines, then print the array on a single line.
|
||||
* - otherwise, it the values do not fit on one line, or the array contains
|
||||
* object or non empty array, then print one value per line.
|
||||
*
|
||||
* If the Value have comments then they are outputed according to their #CommentPlacement.
|
||||
*
|
||||
* \sa Reader, Value, Value::setComment()
|
||||
*/
|
||||
class JSON_API StyledWriter: public Writer
|
||||
{
|
||||
public:
|
||||
StyledWriter();
|
||||
virtual ~StyledWriter(){}
|
||||
|
||||
public: // overridden from Writer
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||
* \param root Value to serialize.
|
||||
* \return String containing the JSON document that represents the root value.
|
||||
*/
|
||||
virtual std::string write( const Value &root );
|
||||
|
||||
private:
|
||||
void writeValue( const Value &value );
|
||||
void writeArrayValue( const Value &value );
|
||||
bool isMultineArray( const Value &value );
|
||||
void pushValue( const std::string &value );
|
||||
void writeIndent();
|
||||
void writeWithIndent( const std::string &value );
|
||||
void indent();
|
||||
void unindent();
|
||||
void writeCommentBeforeValue( const Value &root );
|
||||
void writeCommentAfterValueOnSameLine( const Value &root );
|
||||
bool hasCommentForValue( const Value &value );
|
||||
static std::string normalizeEOL( const std::string &text );
|
||||
|
||||
typedef std::vector<std::string> ChildValues;
|
||||
|
||||
ChildValues childValues_;
|
||||
std::string document_;
|
||||
std::string indentString_;
|
||||
int rightMargin_;
|
||||
int indentSize_;
|
||||
bool addChildValues_;
|
||||
};
|
||||
|
||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
|
||||
to a stream rather than to a string.
|
||||
*
|
||||
* The rules for line break and indent are as follow:
|
||||
* - Object value:
|
||||
* - if empty then print {} without indent and line break
|
||||
* - if not empty the print '{', line break & indent, print one value per line
|
||||
* and then unindent and line break and print '}'.
|
||||
* - Array value:
|
||||
* - if empty then print [] without indent and line break
|
||||
* - if the array contains no object value, empty array or some other value types,
|
||||
* and all the values fit on one lines, then print the array on a single line.
|
||||
* - otherwise, it the values do not fit on one line, or the array contains
|
||||
* object or non empty array, then print one value per line.
|
||||
*
|
||||
* If the Value have comments then they are outputed according to their #CommentPlacement.
|
||||
*
|
||||
* \param indentation Each level will be indented by this amount extra.
|
||||
* \sa Reader, Value, Value::setComment()
|
||||
*/
|
||||
class JSON_API StyledStreamWriter
|
||||
{
|
||||
public:
|
||||
StyledStreamWriter( std::string indentation="\t" );
|
||||
~StyledStreamWriter(){}
|
||||
|
||||
public:
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||
* \param out Stream to write to. (Can be ostringstream, e.g.)
|
||||
* \param root Value to serialize.
|
||||
* \note There is no point in deriving from Writer, since write() should not return a value.
|
||||
*/
|
||||
void write( std::ostream &out, const Value &root );
|
||||
|
||||
private:
|
||||
void writeValue( const Value &value );
|
||||
void writeArrayValue( const Value &value );
|
||||
bool isMultineArray( const Value &value );
|
||||
void pushValue( const std::string &value );
|
||||
void writeIndent();
|
||||
void writeWithIndent( const std::string &value );
|
||||
void indent();
|
||||
void unindent();
|
||||
void writeCommentBeforeValue( const Value &root );
|
||||
void writeCommentAfterValueOnSameLine( const Value &root );
|
||||
bool hasCommentForValue( const Value &value );
|
||||
static std::string normalizeEOL( const std::string &text );
|
||||
|
||||
typedef std::vector<std::string> ChildValues;
|
||||
|
||||
ChildValues childValues_;
|
||||
std::ostream* document_;
|
||||
std::string indentString_;
|
||||
int rightMargin_;
|
||||
std::string indentation_;
|
||||
bool addChildValues_;
|
||||
};
|
||||
|
||||
std::string JSON_API valueToString( Int value );
|
||||
std::string JSON_API valueToString( UInt value );
|
||||
std::string JSON_API valueToString( double value );
|
||||
std::string JSON_API valueToString( bool value );
|
||||
std::string JSON_API valueToQuotedString( const char *value );
|
||||
|
||||
/// \brief Output using the StyledStreamWriter.
|
||||
/// \see Json::operator>>()
|
||||
std::ostream& operator<<( std::ostream&, const Value &root );
|
||||
|
||||
} // namespace Json
|
||||
|
||||
|
||||
|
||||
#endif // JSON_WRITER_H_INCLUDED
|
||||
#ifndef JSON_WRITER_H_INCLUDED
|
||||
# define JSON_WRITER_H_INCLUDED
|
||||
|
||||
# include "value.h"
|
||||
# include <vector>
|
||||
# include <string>
|
||||
# include <iostream>
|
||||
|
||||
namespace Json {
|
||||
|
||||
class Value;
|
||||
|
||||
/** \brief Abstract class for writers.
|
||||
*/
|
||||
class JSON_API Writer
|
||||
{
|
||||
public:
|
||||
virtual ~Writer();
|
||||
|
||||
virtual std::string write( const Value &root ) = 0;
|
||||
};
|
||||
|
||||
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
|
||||
*
|
||||
* The JSON document is written in a single line. It is not intended for 'human' consumption,
|
||||
* but may be usefull to support feature such as RPC where bandwith is limited.
|
||||
* \sa Reader, Value
|
||||
*/
|
||||
class JSON_API FastWriter : public Writer
|
||||
{
|
||||
public:
|
||||
FastWriter();
|
||||
virtual ~FastWriter(){}
|
||||
|
||||
void enableYAMLCompatibility();
|
||||
|
||||
public: // overridden from Writer
|
||||
virtual std::string write( const Value &root );
|
||||
|
||||
private:
|
||||
void writeValue( const Value &value );
|
||||
|
||||
std::string document_;
|
||||
bool yamlCompatiblityEnabled_;
|
||||
};
|
||||
|
||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
|
||||
*
|
||||
* The rules for line break and indent are as follow:
|
||||
* - Object value:
|
||||
* - if empty then print {} without indent and line break
|
||||
* - if not empty the print '{', line break & indent, print one value per line
|
||||
* and then unindent and line break and print '}'.
|
||||
* - Array value:
|
||||
* - if empty then print [] without indent and line break
|
||||
* - if the array contains no object value, empty array or some other value types,
|
||||
* and all the values fit on one lines, then print the array on a single line.
|
||||
* - otherwise, it the values do not fit on one line, or the array contains
|
||||
* object or non empty array, then print one value per line.
|
||||
*
|
||||
* If the Value have comments then they are outputed according to their #CommentPlacement.
|
||||
*
|
||||
* \sa Reader, Value, Value::setComment()
|
||||
*/
|
||||
class JSON_API StyledWriter: public Writer
|
||||
{
|
||||
public:
|
||||
StyledWriter();
|
||||
virtual ~StyledWriter(){}
|
||||
|
||||
public: // overridden from Writer
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||
* \param root Value to serialize.
|
||||
* \return String containing the JSON document that represents the root value.
|
||||
*/
|
||||
virtual std::string write( const Value &root );
|
||||
|
||||
private:
|
||||
void writeValue( const Value &value );
|
||||
void writeArrayValue( const Value &value );
|
||||
bool isMultineArray( const Value &value );
|
||||
void pushValue( const std::string &value );
|
||||
void writeIndent();
|
||||
void writeWithIndent( const std::string &value );
|
||||
void indent();
|
||||
void unindent();
|
||||
void writeCommentBeforeValue( const Value &root );
|
||||
void writeCommentAfterValueOnSameLine( const Value &root );
|
||||
bool hasCommentForValue( const Value &value );
|
||||
static std::string normalizeEOL( const std::string &text );
|
||||
|
||||
typedef std::vector<std::string> ChildValues;
|
||||
|
||||
ChildValues childValues_;
|
||||
std::string document_;
|
||||
std::string indentString_;
|
||||
int rightMargin_;
|
||||
int indentSize_;
|
||||
bool addChildValues_;
|
||||
};
|
||||
|
||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
|
||||
to a stream rather than to a string.
|
||||
*
|
||||
* The rules for line break and indent are as follow:
|
||||
* - Object value:
|
||||
* - if empty then print {} without indent and line break
|
||||
* - if not empty the print '{', line break & indent, print one value per line
|
||||
* and then unindent and line break and print '}'.
|
||||
* - Array value:
|
||||
* - if empty then print [] without indent and line break
|
||||
* - if the array contains no object value, empty array or some other value types,
|
||||
* and all the values fit on one lines, then print the array on a single line.
|
||||
* - otherwise, it the values do not fit on one line, or the array contains
|
||||
* object or non empty array, then print one value per line.
|
||||
*
|
||||
* If the Value have comments then they are outputed according to their #CommentPlacement.
|
||||
*
|
||||
* \param indentation Each level will be indented by this amount extra.
|
||||
* \sa Reader, Value, Value::setComment()
|
||||
*/
|
||||
class JSON_API StyledStreamWriter
|
||||
{
|
||||
public:
|
||||
StyledStreamWriter( std::string indentation="\t" );
|
||||
~StyledStreamWriter(){}
|
||||
|
||||
public:
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||
* \param out Stream to write to. (Can be ostringstream, e.g.)
|
||||
* \param root Value to serialize.
|
||||
* \note There is no point in deriving from Writer, since write() should not return a value.
|
||||
*/
|
||||
void write( std::ostream &out, const Value &root );
|
||||
|
||||
private:
|
||||
void writeValue( const Value &value );
|
||||
void writeArrayValue( const Value &value );
|
||||
bool isMultineArray( const Value &value );
|
||||
void pushValue( const std::string &value );
|
||||
void writeIndent();
|
||||
void writeWithIndent( const std::string &value );
|
||||
void indent();
|
||||
void unindent();
|
||||
void writeCommentBeforeValue( const Value &root );
|
||||
void writeCommentAfterValueOnSameLine( const Value &root );
|
||||
bool hasCommentForValue( const Value &value );
|
||||
static std::string normalizeEOL( const std::string &text );
|
||||
|
||||
typedef std::vector<std::string> ChildValues;
|
||||
|
||||
ChildValues childValues_;
|
||||
std::ostream* document_;
|
||||
std::string indentString_;
|
||||
int rightMargin_;
|
||||
std::string indentation_;
|
||||
bool addChildValues_;
|
||||
};
|
||||
|
||||
std::string JSON_API valueToString( Int value );
|
||||
std::string JSON_API valueToString( UInt value );
|
||||
std::string JSON_API valueToString( double value );
|
||||
std::string JSON_API valueToString( bool value );
|
||||
std::string JSON_API valueToQuotedString( const char *value );
|
||||
|
||||
/// \brief Output using the StyledStreamWriter.
|
||||
/// \see Json::operator>>()
|
||||
std::ostream& operator<<( std::ostream&, const Value &root );
|
||||
|
||||
} // namespace Json
|
||||
|
||||
|
||||
|
||||
#endif // JSON_WRITER_H_INCLUDED
|
||||
|
||||
@@ -1,125 +1,125 @@
|
||||
#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
||||
# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
||||
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
||||
|
||||
namespace Json {
|
||||
|
||||
/* Fast memory allocator.
|
||||
*
|
||||
* This memory allocator allocates memory for a batch of object (specified by
|
||||
* the page size, the number of object in each page).
|
||||
*
|
||||
* It does not allow the destruction of a single object. All the allocated objects
|
||||
* can be destroyed at once. The memory can be either released or reused for future
|
||||
* allocation.
|
||||
*
|
||||
* The in-place new operator must be used to construct the object using the pointer
|
||||
* returned by allocate.
|
||||
*/
|
||||
template<typename AllocatedType
|
||||
,const unsigned int objectPerAllocation>
|
||||
class BatchAllocator
|
||||
{
|
||||
public:
|
||||
typedef AllocatedType Type;
|
||||
|
||||
BatchAllocator( unsigned int objectsPerPage = 255 )
|
||||
: freeHead_( 0 )
|
||||
, objectsPerPage_( objectsPerPage )
|
||||
{
|
||||
// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
|
||||
assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
|
||||
assert( objectsPerPage >= 16 );
|
||||
batches_ = allocateBatch( 0 ); // allocated a dummy page
|
||||
currentBatch_ = batches_;
|
||||
}
|
||||
|
||||
~BatchAllocator()
|
||||
{
|
||||
for ( BatchInfo *batch = batches_; batch; )
|
||||
{
|
||||
BatchInfo *nextBatch = batch->next_;
|
||||
free( batch );
|
||||
batch = nextBatch;
|
||||
}
|
||||
}
|
||||
|
||||
/// allocate space for an array of objectPerAllocation object.
|
||||
/// @warning it is the responsability of the caller to call objects constructors.
|
||||
AllocatedType *allocate()
|
||||
{
|
||||
if ( freeHead_ ) // returns node from free list.
|
||||
{
|
||||
AllocatedType *object = freeHead_;
|
||||
freeHead_ = *(AllocatedType **)object;
|
||||
return object;
|
||||
}
|
||||
if ( currentBatch_->used_ == currentBatch_->end_ )
|
||||
{
|
||||
currentBatch_ = currentBatch_->next_;
|
||||
while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
|
||||
currentBatch_ = currentBatch_->next_;
|
||||
|
||||
if ( !currentBatch_ ) // no free batch found, allocate a new one
|
||||
{
|
||||
currentBatch_ = allocateBatch( objectsPerPage_ );
|
||||
currentBatch_->next_ = batches_; // insert at the head of the list
|
||||
batches_ = currentBatch_;
|
||||
}
|
||||
}
|
||||
AllocatedType *allocated = currentBatch_->used_;
|
||||
currentBatch_->used_ += objectPerAllocation;
|
||||
return allocated;
|
||||
}
|
||||
|
||||
/// Release the object.
|
||||
/// @warning it is the responsability of the caller to actually destruct the object.
|
||||
void release( AllocatedType *object )
|
||||
{
|
||||
assert( object != 0 );
|
||||
*(AllocatedType **)object = freeHead_;
|
||||
freeHead_ = object;
|
||||
}
|
||||
|
||||
private:
|
||||
struct BatchInfo
|
||||
{
|
||||
BatchInfo *next_;
|
||||
AllocatedType *used_;
|
||||
AllocatedType *end_;
|
||||
AllocatedType buffer_[objectPerAllocation];
|
||||
};
|
||||
|
||||
// disabled copy constructor and assignement operator.
|
||||
BatchAllocator( const BatchAllocator & );
|
||||
void operator =( const BatchAllocator &);
|
||||
|
||||
static BatchInfo *allocateBatch( unsigned int objectsPerPage )
|
||||
{
|
||||
const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
|
||||
+ sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
|
||||
BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
|
||||
batch->next_ = 0;
|
||||
batch->used_ = batch->buffer_;
|
||||
batch->end_ = batch->buffer_ + objectsPerPage;
|
||||
return batch;
|
||||
}
|
||||
|
||||
BatchInfo *batches_;
|
||||
BatchInfo *currentBatch_;
|
||||
/// Head of a single linked list within the allocated space of freeed object
|
||||
AllocatedType *freeHead_;
|
||||
unsigned int objectsPerPage_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Json
|
||||
|
||||
# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
|
||||
|
||||
#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
||||
|
||||
#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
||||
# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
||||
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
||||
|
||||
namespace Json {
|
||||
|
||||
/* Fast memory allocator.
|
||||
*
|
||||
* This memory allocator allocates memory for a batch of object (specified by
|
||||
* the page size, the number of object in each page).
|
||||
*
|
||||
* It does not allow the destruction of a single object. All the allocated objects
|
||||
* can be destroyed at once. The memory can be either released or reused for future
|
||||
* allocation.
|
||||
*
|
||||
* The in-place new operator must be used to construct the object using the pointer
|
||||
* returned by allocate.
|
||||
*/
|
||||
template<typename AllocatedType
|
||||
,const unsigned int objectPerAllocation>
|
||||
class BatchAllocator
|
||||
{
|
||||
public:
|
||||
typedef AllocatedType Type;
|
||||
|
||||
BatchAllocator( unsigned int objectsPerPage = 255 )
|
||||
: freeHead_( 0 )
|
||||
, objectsPerPage_( objectsPerPage )
|
||||
{
|
||||
// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
|
||||
assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
|
||||
assert( objectsPerPage >= 16 );
|
||||
batches_ = allocateBatch( 0 ); // allocated a dummy page
|
||||
currentBatch_ = batches_;
|
||||
}
|
||||
|
||||
~BatchAllocator()
|
||||
{
|
||||
for ( BatchInfo *batch = batches_; batch; )
|
||||
{
|
||||
BatchInfo *nextBatch = batch->next_;
|
||||
free( batch );
|
||||
batch = nextBatch;
|
||||
}
|
||||
}
|
||||
|
||||
/// allocate space for an array of objectPerAllocation object.
|
||||
/// @warning it is the responsability of the caller to call objects constructors.
|
||||
AllocatedType *allocate()
|
||||
{
|
||||
if ( freeHead_ ) // returns node from free list.
|
||||
{
|
||||
AllocatedType *object = freeHead_;
|
||||
freeHead_ = *(AllocatedType **)object;
|
||||
return object;
|
||||
}
|
||||
if ( currentBatch_->used_ == currentBatch_->end_ )
|
||||
{
|
||||
currentBatch_ = currentBatch_->next_;
|
||||
while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
|
||||
currentBatch_ = currentBatch_->next_;
|
||||
|
||||
if ( !currentBatch_ ) // no free batch found, allocate a new one
|
||||
{
|
||||
currentBatch_ = allocateBatch( objectsPerPage_ );
|
||||
currentBatch_->next_ = batches_; // insert at the head of the list
|
||||
batches_ = currentBatch_;
|
||||
}
|
||||
}
|
||||
AllocatedType *allocated = currentBatch_->used_;
|
||||
currentBatch_->used_ += objectPerAllocation;
|
||||
return allocated;
|
||||
}
|
||||
|
||||
/// Release the object.
|
||||
/// @warning it is the responsability of the caller to actually destruct the object.
|
||||
void release( AllocatedType *object )
|
||||
{
|
||||
assert( object != 0 );
|
||||
*(AllocatedType **)object = freeHead_;
|
||||
freeHead_ = object;
|
||||
}
|
||||
|
||||
private:
|
||||
struct BatchInfo
|
||||
{
|
||||
BatchInfo *next_;
|
||||
AllocatedType *used_;
|
||||
AllocatedType *end_;
|
||||
AllocatedType buffer_[objectPerAllocation];
|
||||
};
|
||||
|
||||
// disabled copy constructor and assignement operator.
|
||||
BatchAllocator( const BatchAllocator & );
|
||||
void operator =( const BatchAllocator &);
|
||||
|
||||
static BatchInfo *allocateBatch( unsigned int objectsPerPage )
|
||||
{
|
||||
const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
|
||||
+ sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
|
||||
BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
|
||||
batch->next_ = 0;
|
||||
batch->used_ = batch->buffer_;
|
||||
batch->end_ = batch->buffer_ + objectsPerPage;
|
||||
return batch;
|
||||
}
|
||||
|
||||
BatchInfo *batches_;
|
||||
BatchInfo *currentBatch_;
|
||||
/// Head of a single linked list within the allocated space of freeed object
|
||||
AllocatedType *freeHead_;
|
||||
unsigned int objectsPerPage_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Json
|
||||
|
||||
# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
|
||||
|
||||
#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+1718
-1718
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+6398
-6398
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user