<commit_before>/*
 *  Copyright (C) 2010 Stephen F. Booth <me@sbooth.org>
 *  All Rights Reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *    - Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    - Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    - Neither the name of Stephen F. Booth nor the names of its
 *      contributors may be used to endorse or promote products derived
 *      from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <taglib/vorbisfile.h>
#include <taglib/xiphcomment.h>

#include "AudioEngineDefines.h"
#include "OggVorbisMetadata.h"
#include "CreateDisplayNameForURL.h"

#pragma mark Static Methods

CFArrayRef OggVorbisMetadata::CreateSupportedFileExtensions()
{
	CFStringRef supportedExtensions [] = { CFSTR("ogg"), CFSTR("oga") };
	return CFArrayCreate(kCFAllocatorDefault, reinterpret_cast<const void **>(supportedExtensions), 2, &kCFTypeArrayCallBacks);
}

CFArrayRef OggVorbisMetadata::CreateSupportedMIMETypes()
{
	CFStringRef supportedMIMETypes [] = { CFSTR("audio/ogg") };
	return CFArrayCreate(kCFAllocatorDefault, reinterpret_cast<const void **>(supportedMIMETypes), 1, &kCFTypeArrayCallBacks);
}

bool OggVorbisMetadata::HandlesFilesWithExtension(CFStringRef extension)
{
	assert(NULL != extension);

	if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("ogg"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("oga"), kCFCompareCaseInsensitive))
		return true;

	return false;
}

bool OggVorbisMetadata::HandlesMIMEType(CFStringRef mimeType)
{
	assert(NULL != mimeType);

	if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/ogg"), kCFCompareCaseInsensitive))
		return true;

	return false;
}

#pragma mark Creation and Destruction

OggVorbisMetadata::OggVorbisMetadata(CFURLRef url)
	: AudioMetadata(url)
{}

OggVorbisMetadata::~OggVorbisMetadata()
{}

#pragma mark Functionality

bool OggVorbisMetadata::ReadMetadata(CFErrorRef *error)
{
	// Start from scratch
	CFDictionaryRemoveAllValues(mMetadata);

	UInt8 buf [PATH_MAX];
	if(false == CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;

	TagLib::Ogg::Vorbis::File file(reinterpret_cast<const char *>(buf), false);

	if(!file.isValid()) {
		if(NULL != error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault,
																			   32,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);

			CFStringRef displayName = CreateDisplayNameForURL(mURL);
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault,
															   NULL,
															   CFCopyLocalizedString(CFSTR("The file \"%@\" is not a valid Ogg Vorbis file."), ""),
															   displayName);

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedDescriptionKey,
								 errorString);

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedFailureReasonKey,
								 CFCopyLocalizedString(CFSTR("Not an Ogg Vorbis file"), ""));

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedRecoverySuggestionKey,
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;

			*error = CFErrorCreate(kCFAllocatorDefault,
								   AudioMetadataErrorDomain,
								   AudioMetadataInputOutputError,
								   errorDictionary);

			CFRelease(errorDictionary), errorDictionary = NULL;
		}

		return false;
	}

	if(file.tag()) {
		CFMutableDictionaryRef additionalMetadata = CFDictionaryCreateMutable(kCFAllocatorDefault,
																			  32,
																			  &kCFTypeDictionaryKeyCallBacks,
																			  &kCFTypeDictionaryValueCallBacks);

		// A map <String, StringList>
		TagLib::Ogg::FieldListMap fieldList = file.tag()->fieldListMap();

		for(TagLib::Ogg::FieldListMap::ConstIterator it = fieldList.begin(); it != fieldList.end(); ++it) {
			CFStringRef key = CFStringCreateWithCString(kCFAllocatorDefault,
														it->first.toCString(true),
														kCFStringEncodingUTF8);

			// Vorbis allows multiple comments with the same key, but this isn't supported by AudioMetadata
			CFStringRef value = CFStringCreateWithCString(kCFAllocatorDefault,
														  it->second.front().toCString(true),
														  kCFStringEncodingUTF8);

			if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ALBUM"), kCFCompareCaseInsensitive))
				SetAlbumTitle(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ARTIST"), kCFCompareCaseInsensitive))
				SetArtist(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ALBUMARTIST"), kCFCompareCaseInsensitive))
				SetAlbumArtist(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("COMPOSER"), kCFCompareCaseInsensitive))
				SetComposer(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("GENRE"), kCFCompareCaseInsensitive))
				SetGenre(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DATE"), kCFCompareCaseInsensitive))
				SetReleaseDate(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DESCRIPTION"), kCFCompareCaseInsensitive))
				SetComment(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("TITLE"), kCFCompareCaseInsensitive))
				SetTitle(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("TRACKNUMBER"), kCFCompareCaseInsensitive)) {
				int num = CFStringGetIntValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
				SetTrackNumber(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("TRACKTOTAL"), kCFCompareCaseInsensitive)) {
				int num = CFStringGetIntValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
				SetTrackTotal(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("COMPILATION"), kCFCompareCaseInsensitive))
				SetCompilation(CFStringGetIntValue(value) ? kCFBooleanTrue : kCFBooleanFalse);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DISCNUMBER"), kCFCompareCaseInsensitive)) {
				int num = CFStringGetIntValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
				SetDiscNumber(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DISCTOTAL"), kCFCompareCaseInsensitive)) {
				int num = CFStringGetIntValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
				SetDiscTotal(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ISRC"), kCFCompareCaseInsensitive))
				SetISRC(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("MCN"), kCFCompareCaseInsensitive))
				SetMCN(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_REFERENCE_LOUDNESS"), kCFCompareCaseInsensitive)) {
				double num = CFStringGetDoubleValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
				SetReplayGainReferenceLoudness(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_TRACK_GAIN"), kCFCompareCaseInsensitive)) {
				double num = CFStringGetDoubleValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
				SetReplayGainTrackGain(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_TRACK_PEAK"), kCFCompareCaseInsensitive)) {
				double num = CFStringGetDoubleValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
				SetReplayGainTrackPeak(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_ALBUM_GAIN"), kCFCompareCaseInsensitive)) {
				double num = CFStringGetDoubleValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
				SetReplayGainAlbumGain(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_ALBUM_PEAK"), kCFCompareCaseInsensitive)) {
				double num = CFStringGetDoubleValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
				SetReplayGainAlbumPeak(number);
				CFRelease(number), number = NULL;
			}
			// Put all unknown tags into the additional metadata
			else
				CFDictionarySetValue(additionalMetadata, key, value);

			CFRelease(key), key = NULL;
			CFRelease(value), value = NULL;
		}

		if(CFDictionaryGetCount(additionalMetadata))
			SetAdditionalMetadata(additionalMetadata);

		CFRelease(additionalMetadata), additionalMetadata = NULL;

	}

	return true;
}

bool OggVorbisMetadata::WriteMetadata(CFErrorRef *error)
{
	UInt8 buf [PATH_MAX];
	if(false == CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;

	TagLib::Ogg::Vorbis::File file(reinterpret_cast<const char *>(buf), false);

	if(!file.isValid()) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault,
																			   32,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);

			CFStringRef displayName = CreateDisplayNameForURL(mURL);
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault,
															   NULL,
															   CFCopyLocalizedString(CFSTR("The file \"%@\" is not a valid Ogg Vorbis file."), ""),
															   displayName);

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedDescriptionKey,
								 errorString);

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedFailureReasonKey,
								 CFCopyLocalizedString(CFSTR("Not an Ogg Vorbis file"), ""));

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedRecoverySuggestionKey,
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;

			*error = CFErrorCreate(kCFAllocatorDefault,
								   AudioMetadataErrorDomain,
								   AudioMetadataInputOutputError,
								   errorDictionary);

			CFRelease(errorDictionary), errorDictionary = NULL;
		}

		return false;
	}

	if(!file.save()) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault,
																			   32,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);

			CFStringRef displayName = CreateDisplayNameForURL(mURL);
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault,
															   NULL,
															   CFCopyLocalizedString(CFSTR("The file \"%@\" is not a valid Ogg Vorbis file."), ""),
															   displayName);

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedDescriptionKey,
								 errorString);

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedFailureReasonKey,
								 CFCopyLocalizedString(CFSTR("Unable to write metadata"), ""));

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedRecoverySuggestionKey,
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;

			*error = CFErrorCreate(kCFAllocatorDefault,
								   AudioMetadataErrorDomain,
								   AudioMetadataInputOutputError,
								   errorDictionary);

			CFRelease(errorDictionary), errorDictionary = NULL;
		}

		return false;
	}

	return true;
}
<commit_msg>Rewritten to handle Ogg Vorbis and Ogg FLAC files<commit_after>/*
 *  Copyright (C) 2010 Stephen F. Booth <me@sbooth.org>
 *  All Rights Reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *    - Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    - Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    - Neither the name of Stephen F. Booth nor the names of its
 *      contributors may be used to endorse or promote products derived
 *      from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <taglib/vorbisfile.h>
#include <taglib/oggflacfile.h>
#include <taglib/xiphcomment.h>

#include "AudioEngineDefines.h"
#include "OggVorbisMetadata.h"
#include "CreateDisplayNameForURL.h"

#pragma mark Static Methods

CFArrayRef OggVorbisMetadata::CreateSupportedFileExtensions()
{
	CFStringRef supportedExtensions [] = { CFSTR("ogg"), CFSTR("oga") };
	return CFArrayCreate(kCFAllocatorDefault, reinterpret_cast<const void **>(supportedExtensions), 2, &kCFTypeArrayCallBacks);
}

CFArrayRef OggVorbisMetadata::CreateSupportedMIMETypes()
{
	CFStringRef supportedMIMETypes [] = { CFSTR("audio/ogg") };
	return CFArrayCreate(kCFAllocatorDefault, reinterpret_cast<const void **>(supportedMIMETypes), 1, &kCFTypeArrayCallBacks);
}

bool OggVorbisMetadata::HandlesFilesWithExtension(CFStringRef extension)
{
	assert(NULL != extension);

	if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("ogg"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("oga"), kCFCompareCaseInsensitive))
		return true;

	return false;
}

bool OggVorbisMetadata::HandlesMIMEType(CFStringRef mimeType)
{
	assert(NULL != mimeType);

	if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/ogg"), kCFCompareCaseInsensitive))
		return true;

	return false;
}

#pragma mark Creation and Destruction

OggVorbisMetadata::OggVorbisMetadata(CFURLRef url)
	: AudioMetadata(url)
{}

OggVorbisMetadata::~OggVorbisMetadata()
{}

#pragma mark Functionality

bool OggVorbisMetadata::ReadMetadata(CFErrorRef *error)
{
	// Start from scratch
	CFDictionaryRemoveAllValues(mMetadata);

	UInt8 buf [PATH_MAX];
	if(false == CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;

	// Attempt to open the file as an Ogg Vorbis file, and if it fails, as an Ogg FLAC file
	TagLib::Ogg::File *file = new TagLib::Ogg::Vorbis::File(reinterpret_cast<const char *>(buf), false);

	if(!file->isValid()) {
		delete file, file = NULL;

		file = new TagLib::Ogg::FLAC::File(reinterpret_cast<const char *>(buf), false);
	}

	if(!file->isValid()) {
		if(NULL != error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault,
																			   32,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);

			CFStringRef displayName = CreateDisplayNameForURL(mURL);
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault,
															   NULL,
															   CFCopyLocalizedString(CFSTR("The file \"%@\" is not a valid Ogg file."), ""),
															   displayName);

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedDescriptionKey,
								 errorString);

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedFailureReasonKey,
								 CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedRecoverySuggestionKey,
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;

			*error = CFErrorCreate(kCFAllocatorDefault,
								   AudioMetadataErrorDomain,
								   AudioMetadataInputOutputError,
								   errorDictionary);

			CFRelease(errorDictionary), errorDictionary = NULL;
		}

		delete file, file = NULL;

		return false;
	}

	if(file->tag()) {
		CFMutableDictionaryRef additionalMetadata = CFDictionaryCreateMutable(kCFAllocatorDefault,
																			  32,
																			  &kCFTypeDictionaryKeyCallBacks,
																			  &kCFTypeDictionaryValueCallBacks);

		// A map <String, StringList>
		TagLib::Ogg::XiphComment *xiphComment = dynamic_cast<TagLib::Ogg::XiphComment *>(file->tag());

		// This shouldn't happen
		if(!xiphComment) {
			delete file, file = NULL;
			return false;
		}

		TagLib::Ogg::FieldListMap fieldList = xiphComment->fieldListMap();

		for(TagLib::Ogg::FieldListMap::ConstIterator it = fieldList.begin(); it != fieldList.end(); ++it) {
			CFStringRef key = CFStringCreateWithCString(kCFAllocatorDefault,
														it->first.toCString(true),
														kCFStringEncodingUTF8);

			// Vorbis allows multiple comments with the same key, but this isn't supported by AudioMetadata
			CFStringRef value = CFStringCreateWithCString(kCFAllocatorDefault,
														  it->second.front().toCString(true),
														  kCFStringEncodingUTF8);

			if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ALBUM"), kCFCompareCaseInsensitive))
				SetAlbumTitle(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ARTIST"), kCFCompareCaseInsensitive))
				SetArtist(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ALBUMARTIST"), kCFCompareCaseInsensitive))
				SetAlbumArtist(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("COMPOSER"), kCFCompareCaseInsensitive))
				SetComposer(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("GENRE"), kCFCompareCaseInsensitive))
				SetGenre(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DATE"), kCFCompareCaseInsensitive))
				SetReleaseDate(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DESCRIPTION"), kCFCompareCaseInsensitive))
				SetComment(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("TITLE"), kCFCompareCaseInsensitive))
				SetTitle(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("TRACKNUMBER"), kCFCompareCaseInsensitive)) {
				int num = CFStringGetIntValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
				SetTrackNumber(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("TRACKTOTAL"), kCFCompareCaseInsensitive)) {
				int num = CFStringGetIntValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
				SetTrackTotal(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("COMPILATION"), kCFCompareCaseInsensitive))
				SetCompilation(CFStringGetIntValue(value) ? kCFBooleanTrue : kCFBooleanFalse);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DISCNUMBER"), kCFCompareCaseInsensitive)) {
				int num = CFStringGetIntValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
				SetDiscNumber(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DISCTOTAL"), kCFCompareCaseInsensitive)) {
				int num = CFStringGetIntValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num);
				SetDiscTotal(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ISRC"), kCFCompareCaseInsensitive))
				SetISRC(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("MCN"), kCFCompareCaseInsensitive))
				SetMCN(value);
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_REFERENCE_LOUDNESS"), kCFCompareCaseInsensitive)) {
				double num = CFStringGetDoubleValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
				SetReplayGainReferenceLoudness(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_TRACK_GAIN"), kCFCompareCaseInsensitive)) {
				double num = CFStringGetDoubleValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
				SetReplayGainTrackGain(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_TRACK_PEAK"), kCFCompareCaseInsensitive)) {
				double num = CFStringGetDoubleValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
				SetReplayGainTrackPeak(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_ALBUM_GAIN"), kCFCompareCaseInsensitive)) {
				double num = CFStringGetDoubleValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
				SetReplayGainAlbumGain(number);
				CFRelease(number), number = NULL;
			}
			else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_ALBUM_PEAK"), kCFCompareCaseInsensitive)) {
				double num = CFStringGetDoubleValue(value);
				CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &num);
				SetReplayGainAlbumPeak(number);
				CFRelease(number), number = NULL;
			}
			// Put all unknown tags into the additional metadata
			else
				CFDictionarySetValue(additionalMetadata, key, value);

			CFRelease(key), key = NULL;
			CFRelease(value), value = NULL;
		}

		if(CFDictionaryGetCount(additionalMetadata))
			SetAdditionalMetadata(additionalMetadata);

		CFRelease(additionalMetadata), additionalMetadata = NULL;

	}

	delete file, file = NULL;

	return true;
}

bool OggVorbisMetadata::WriteMetadata(CFErrorRef *error)
{
	UInt8 buf [PATH_MAX];
	if(false == CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;

	// Attempt to open the file as an Ogg Vorbis file, and if it fails, as an Ogg FLAC file
	TagLib::Ogg::File *file = new TagLib::Ogg::Vorbis::File(reinterpret_cast<const char *>(buf), false);

	if(!file->isValid()) {
		delete file, file = NULL;

		file = new TagLib::Ogg::FLAC::File(reinterpret_cast<const char *>(buf), false);
	}

	if(!file->isValid()) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault,
																			   32,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);

			CFStringRef displayName = CreateDisplayNameForURL(mURL);
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault,
															   NULL,
															   CFCopyLocalizedString(CFSTR("The file \"%@\" is not a valid Ogg file."), ""),
															   displayName);

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedDescriptionKey,
								 errorString);

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedFailureReasonKey,
								 CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedRecoverySuggestionKey,
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;

			*error = CFErrorCreate(kCFAllocatorDefault,
								   AudioMetadataErrorDomain,
								   AudioMetadataInputOutputError,
								   errorDictionary);

			CFRelease(errorDictionary), errorDictionary = NULL;
		}

		delete file, file = NULL;

		return false;
	}

	if(!file->save()) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault,
																			   32,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);

			CFStringRef displayName = CreateDisplayNameForURL(mURL);
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault,
															   NULL,
															   CFCopyLocalizedString(CFSTR("The file \"%@\" is not a valid Ogg file."), ""),
															   displayName);

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedDescriptionKey,
								 errorString);

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedFailureReasonKey,
								 CFCopyLocalizedString(CFSTR("Unable to write metadata"), ""));

			CFDictionarySetValue(errorDictionary,
								 kCFErrorLocalizedRecoverySuggestionKey,
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;

			*error = CFErrorCreate(kCFAllocatorDefault,
								   AudioMetadataErrorDomain,
								   AudioMetadataInputOutputError,
								   errorDictionary);

			CFRelease(errorDictionary), errorDictionary = NULL;
		}

		return false;
	}

	delete file, file = NULL;

	return true;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: layerimp.hxx,v $
 *
 *  $Revision: 1.1 $
 *
 *  last change: $Author: cl $ $Date: 2001-01-19 16:33:27 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XMLOFF_LAYERIMP_HXX
#define _XMLOFF_LAYERIMP_HXX

#ifndef _XMLOFF_XMLICTXT_HXX
#include "xmlictxt.hxx"
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif

class AnimImpImpl;

//////////////////////////////////////////////////////////////////////////////
// presentations:animations

class SdXMLLayerSetContext : public SvXMLImportContext
{
private:
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > mxLayerManager;

public:
    TYPEINFO();

    SdXMLLayerSetContext( SvXMLImport& rImport,
        sal_uInt16 nPrfx,
        const rtl::OUString& rLocalName,
        const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList);
    virtual ~SdXMLLayerSetContext();

    virtual SvXMLImportContext * CreateChildContext( USHORT nPrefix, const ::rtl::OUString& rLocalName,
        const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList );
};

#endif  //  _XMLOFF_ANIMIMP_HXX

<commit_msg>INTEGRATION: CWS ooo19126 (1.1.646); FILE MERGED 2005/09/05 14:38:44 rt 1.1.646.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: layerimp.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 13:45:57 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XMLOFF_LAYERIMP_HXX
#define _XMLOFF_LAYERIMP_HXX

#ifndef _XMLOFF_XMLICTXT_HXX
#include "xmlictxt.hxx"
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif

class AnimImpImpl;

//////////////////////////////////////////////////////////////////////////////
// presentations:animations

class SdXMLLayerSetContext : public SvXMLImportContext
{
private:
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > mxLayerManager;

public:
    TYPEINFO();

    SdXMLLayerSetContext( SvXMLImport& rImport,
        sal_uInt16 nPrfx,
        const rtl::OUString& rLocalName,
        const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList);
    virtual ~SdXMLLayerSetContext();

    virtual SvXMLImportContext * CreateChildContext( USHORT nPrefix, const ::rtl::OUString& rLocalName,
        const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList );
};

#endif  //  _XMLOFF_ANIMIMP_HXX

<|endoftext|>


<commit_before>//
// Copyright (c) 2014 CNRS
// Authors: Florent Lamiraux
//
// This file is part of hpp-core
// hpp-core 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
// 3 of the License, or (at your option) any later version.
//
// hpp-core is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-core  If not, see
// <http://www.gnu.org/licenses/>.

#include <hpp/core/continuous-collision-checking/dichotomy.hh>

#include <deque>
#include <pinocchio/multibody/geometry.hpp>
#include <hpp/util/debug.hh>
#include <hpp/core/collision-path-validation-report.hh>
#include <hpp/core/straight-path.hh>
#include <hpp/core/path-vector.hh>

#include "continuous-collision-checking/dichotomy/body-pair-collision.hh"

namespace hpp {
  namespace core {
    namespace continuousCollisionChecking {

      using dichotomy::BodyPairCollision;
      using dichotomy::BodyPairCollisionPtr_t;
      using dichotomy::BodyPairCollisions_t;

      bool compareBodyPairCol (const BodyPairCollisionPtr_t& bodyPair1,
			       const BodyPairCollisionPtr_t& bodyPair2)
      {
	assert (!bodyPair1->validSubset ().list ().empty ());
	assert (!bodyPair2->validSubset ().list ().empty ());
	return bodyPair1->validSubset ().list ().begin ()->second <
	  bodyPair2->validSubset ().list ().begin ()->second;
      }

      bool compareReverseBodyPairCol (const BodyPairCollisionPtr_t& bodyPair1,
				      const BodyPairCollisionPtr_t& bodyPair2)
      {
	assert (!bodyPair1->validSubset ().list ().empty ());
	assert (!bodyPair2->validSubset ().list ().empty ());
	return bodyPair1->validSubset ().list ().rbegin ()->first >
	  bodyPair2->validSubset ().list ().rbegin ()->first;
      }

      // Partially sort a list where only the first element is not sorted
      template <typename Compare>
      void partialSort (BodyPairCollisions_t& list, Compare comp)
      {
	BodyPairCollisions_t::iterator it1 = list.begin ();
	if (it1 == list.end ()) return;
	BodyPairCollisions_t::iterator it2 = it1; ++it2;
	while (it2 != list.end ()) {
	  if (comp (*it2, *it1))
	    std::iter_swap (it1, it2);
	  else
	    return;
	  it1 = it2;
	  ++it2;
	}
      }
      DichotomyPtr_t
      Dichotomy::create (const DevicePtr_t& robot, const value_type& tolerance)
      {
	Dichotomy* ptr =
	  new Dichotomy (robot, tolerance);
	DichotomyPtr_t shPtr (ptr);
	return shPtr;
      }

      bool Dichotomy::validate (const PathPtr_t& path, bool reverse,
				PathPtr_t& validPart,
				PathValidationReportPtr_t& report)
      {
	CollisionValidationReportPtr_t collisionReport
	  (new CollisionValidationReport);
	if (PathVectorPtr_t pv = HPP_DYNAMIC_PTR_CAST (PathVector, path)) {
	  PathVectorPtr_t validPathVector = PathVector::create
	    (path->outputSize (), path->outputDerivativeSize ());
	  validPart = validPathVector;
	  PathPtr_t localValidPart;
	  if (reverse) {
	    value_type param = path->length ();
	    std::deque <PathPtr_t> paths;
	    for (std::size_t i=pv->numberPaths () + 1; i != 0 ; --i) {
	      PathPtr_t localPath (pv->pathAtRank (i-1));
	      if (validate (localPath, reverse, localValidPart, report)) {
		paths.push_front (localPath->copy ());
		param -= localPath->length ();
	      } else {
		report->parameter += param - localPath->length ();
		paths.push_front (localValidPart->copy ());
		for (std::deque <PathPtr_t>::const_iterator it = paths.begin ();
		     it != paths.end (); ++it) {
		  validPathVector->appendPath (*it);
		}
		return false;
	      }
	    }
	    return true;
	  } else {
	    value_type param = 0;
	    for (std::size_t i=0; i < pv->numberPaths (); ++i) {
	      PathPtr_t localPath (pv->pathAtRank (i));
	      if (validate (localPath, reverse, localValidPart, report)) {
		validPathVector->appendPath (localPath->copy ());
		param += localPath->length ();
	      } else {
		report->parameter += param;
		validPathVector->appendPath (localValidPart->copy ());
		return false;
	      }
	    }
	    return true;
	  }
	}
	StraightPathPtr_t straightPath = HPP_DYNAMIC_PTR_CAST
	  (StraightPath, path);
	// for each BodyPairCollision
	//   - set path,
	//   - compute valid interval at start (end if reverse)
	value_type t0 = path->timeRange ().first;
	value_type t1 = path->timeRange ().second;
	if (reverse) {
	  for (BodyPairCollisions_t::iterator itPair =
		 bodyPairCollisions_.begin ();
	       itPair != bodyPairCollisions_.end (); ++itPair) {
	    (*itPair)->path (straightPath);
	    // If collision at end point, return false
	    if (!(*itPair)->validateInterval (t1, *collisionReport)) {
	      report = CollisionPathValidationReportPtr_t
		(new CollisionPathValidationReport (t1, collisionReport));
	      validPart = path->extract (interval_t (t1, t1));
	      return false;
	    }
	    assert ((*itPair)->validSubset ().contains (t1));
	  }
	  // Sort collision pairs
	  bodyPairCollisions_.sort (compareReverseBodyPairCol);

	  BodyPairCollisionPtr_t first = *(bodyPairCollisions_.begin ());
	  while (!first->validSubset ().contains (t0, true)) {
	    // find middle of first non valid interval
	    const std::list <interval_t>& intervals =
	      first->validSubset ().list ();
	    std::list <interval_t>::const_reverse_iterator lastInterval =
	      intervals.rbegin ();
	    std::list <interval_t>::const_reverse_iterator beforeLastInterval =
	      lastInterval; ++beforeLastInterval;
	    value_type upper = lastInterval->first;
	    value_type lower;
	    if (beforeLastInterval != intervals.rend ()) {
	      lower = beforeLastInterval->second;
	    } else {
	      lower = t0;
	    }
	    value_type middle = .5 * (lower + upper);
	    if (first->validateInterval (middle, *collisionReport)) {
	      partialSort (bodyPairCollisions_, compareReverseBodyPairCol);
	    } else {
	      report = CollisionPathValidationReportPtr_t
		(new CollisionPathValidationReport (middle, collisionReport));
	      validPart = path->extract (interval_t (upper, t1));
	      return false;
	    }
	    first = *(bodyPairCollisions_.begin ());
	  }
	} else {
	  for (BodyPairCollisions_t::iterator itPair =
		 bodyPairCollisions_.begin ();
	       itPair != bodyPairCollisions_.end (); ++itPair) {
	    (*itPair)->path (straightPath);
	    // If collision at start point, return false
	    bool valid = (*itPair)->validateInterval (t0, *collisionReport);
	    if (!valid) {
	      report = CollisionPathValidationReportPtr_t
		(new CollisionPathValidationReport (t0, collisionReport));
	      validPart = path->extract (interval_t (t0, t0));
	      hppDout (error, "Initial position in collision.");
	      return false;
	    }
	    assert ((*itPair)->validSubset ().contains (t0));
	  }
	  // Sort collision pairs
	  bodyPairCollisions_.sort (compareBodyPairCol);
	  BodyPairCollisionPtr_t first = *(bodyPairCollisions_.begin ());
	  while (!first->validSubset ().contains (t1)) {
	    // find middle of first non valid interval
	    const std::list <interval_t>& intervals =
	      first->validSubset ().list ();
	    std::list <interval_t>::const_iterator firstInterval =
	      intervals.begin ();
	    std::list <interval_t>::const_iterator secondInterval =
	      firstInterval;
	    ++secondInterval;
	    value_type lower = firstInterval->second;
	    value_type upper;
	    if (secondInterval != intervals.end ()) {
	      upper = secondInterval->first;
	    } else {
	      upper = t1;
	    }
	    value_type middle = .5 * (lower + upper);
	    if (first->validateInterval (middle, *collisionReport)) {
	      partialSort (bodyPairCollisions_, compareBodyPairCol);
	    } else {
	      report = CollisionPathValidationReportPtr_t
		(new CollisionPathValidationReport (middle, collisionReport));
	      validPart = path->extract (interval_t (t0, lower));
	      return false;
	    }
	    first = *(bodyPairCollisions_.begin ());
	  }
	}
	validPart = path;
	return true;
      }

      void Dichotomy::addObstacle
      (const CollisionObjectConstPtr_t& object)
      {
	pinocchio::JointVector_t& jv = robot_->getJointVector ();
	for (size_type idx = 0; idx < jv.size (); ++idx) {
          JointPtr_t j = jv[idx];
	  BodyPtr_t body = j->linkedBody ();
	  bool foundPair = false;
	  if (body) {
	    for (BodyPairCollisions_t::iterator itPair =
		   bodyPairCollisions_.begin ();
		 itPair != bodyPairCollisions_.end (); ++itPair) {
	      if (((*itPair)->joint_a () == j) &&
		  (!(*itPair)->joint_b ())) {
		(*itPair)->addObjectTo_b (object);
		foundPair = true;
	      }
	    }
	    if (!foundPair) {
	      ConstObjectStdVector_t objects;
	      objects.push_back (object);
	      bodyPairCollisions_.push_back
		(BodyPairCollision::create (j, objects, tolerance_));
	    }
	  }
	}
      }

      void Dichotomy::removeObstacleFromJoint
      (const JointPtr_t& joint, const CollisionObjectConstPtr_t& obstacle)
      {
	bool removed = false;
	for (BodyPairCollisions_t::iterator itPair =
	       bodyPairCollisions_.begin ();
	     itPair != bodyPairCollisions_.end (); ++itPair) {
	  if (!(*itPair)->joint_b () && (*itPair)->joint_a () == joint) {
	    if ((*itPair)->removeObjectTo_b (obstacle)) {
	      removed = true;
	      if ((*itPair)->objects_b ().empty ()) {
		bodyPairCollisions_.erase (itPair);
	      }
	    }
	  }
	}
	if (!removed) {
	  std::ostringstream oss;
	  oss << "Dichotomy::removeObstacleFromJoint: obstacle \""
	      << obstacle->name () <<
	    "\" is not registered as obstacle for joint \"" << joint->name ()
	      << "\".";
	  throw std::runtime_error (oss.str ());
	}
      }

      Dichotomy::~Dichotomy ()
      {
      }

      Dichotomy::Dichotomy
      (const DevicePtr_t& robot, const value_type& tolerance) :
	robot_ (robot), tolerance_ (tolerance),
	bodyPairCollisions_ ()
      {
        // Tolerance should be equal to 0, otherwise end of valid
        // sub-path might be in collision.
        if (tolerance != 0) {
          throw std::runtime_error ("Dichotomy path validation method does not"
              "support penetration.");
        }
        // Build body pairs for collision checking
        // First auto-collision
        // FIXME The pairs of joint are duplicated
        const se3::GeometryModel& gmodel = robot->geomModel ();
        JointPtr_t joint1, joint2;
        for (std::size_t i = 0; i < gmodel.collisionPairs.size(); ++i)
        {
          const se3::CollisionPair& cp = gmodel.collisionPairs[i];
          joint1 = JointPtr_t(new Joint(robot_,
                gmodel.geometryObjects[cp.first].parentJoint));
          joint2 = JointPtr_t(new Joint(robot_,
                gmodel.geometryObjects[cp.second].parentJoint));
          bodyPairCollisions_.push_back (BodyPairCollision::create
              (joint1, joint2, tolerance_));
        }
      }
    } // namespace continuousCollisionChecking
  } // namespace core
} // namespace hpp
<commit_msg>ccc::Dichotomy avoid duplicated joint pairs<commit_after>//
// Copyright (c) 2014 CNRS
// Authors: Florent Lamiraux
//
// This file is part of hpp-core
// hpp-core 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
// 3 of the License, or (at your option) any later version.
//
// hpp-core is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-core  If not, see
// <http://www.gnu.org/licenses/>.

#include <hpp/core/continuous-collision-checking/dichotomy.hh>

#include <deque>
#include <pinocchio/multibody/geometry.hpp>
#include <hpp/util/debug.hh>
#include <hpp/core/collision-path-validation-report.hh>
#include <hpp/core/straight-path.hh>
#include <hpp/core/path-vector.hh>

#include "continuous-collision-checking/dichotomy/body-pair-collision.hh"

namespace hpp {
  namespace core {
    namespace continuousCollisionChecking {
      namespace {
        typedef std::pair<se3::JointIndex, se3::JointIndex> JointIndexPair_t;

        struct JointIndexPairCompare_t {
          bool operator() (const JointIndexPair_t& p0, const JointIndexPair_t& p1) const
          {
            if (p0.first < p1.first) return true;
            if (p0.first > p1.first) return false;
            return (p0.second < p1.second);
          }
        };

        typedef std::set<JointIndexPair_t, JointIndexPairCompare_t> JointIndexPairSet_t;
      }

      using dichotomy::BodyPairCollision;
      using dichotomy::BodyPairCollisionPtr_t;
      using dichotomy::BodyPairCollisions_t;

      bool compareBodyPairCol (const BodyPairCollisionPtr_t& bodyPair1,
			       const BodyPairCollisionPtr_t& bodyPair2)
      {
	assert (!bodyPair1->validSubset ().list ().empty ());
	assert (!bodyPair2->validSubset ().list ().empty ());
	return bodyPair1->validSubset ().list ().begin ()->second <
	  bodyPair2->validSubset ().list ().begin ()->second;
      }

      bool compareReverseBodyPairCol (const BodyPairCollisionPtr_t& bodyPair1,
				      const BodyPairCollisionPtr_t& bodyPair2)
      {
	assert (!bodyPair1->validSubset ().list ().empty ());
	assert (!bodyPair2->validSubset ().list ().empty ());
	return bodyPair1->validSubset ().list ().rbegin ()->first >
	  bodyPair2->validSubset ().list ().rbegin ()->first;
      }

      // Partially sort a list where only the first element is not sorted
      template <typename Compare>
      void partialSort (BodyPairCollisions_t& list, Compare comp)
      {
	BodyPairCollisions_t::iterator it1 = list.begin ();
	if (it1 == list.end ()) return;
	BodyPairCollisions_t::iterator it2 = it1; ++it2;
	while (it2 != list.end ()) {
	  if (comp (*it2, *it1))
	    std::iter_swap (it1, it2);
	  else
	    return;
	  it1 = it2;
	  ++it2;
	}
      }
      DichotomyPtr_t
      Dichotomy::create (const DevicePtr_t& robot, const value_type& tolerance)
      {
	Dichotomy* ptr =
	  new Dichotomy (robot, tolerance);
	DichotomyPtr_t shPtr (ptr);
	return shPtr;
      }

      bool Dichotomy::validate (const PathPtr_t& path, bool reverse,
				PathPtr_t& validPart,
				PathValidationReportPtr_t& report)
      {
	CollisionValidationReportPtr_t collisionReport
	  (new CollisionValidationReport);
	if (PathVectorPtr_t pv = HPP_DYNAMIC_PTR_CAST (PathVector, path)) {
	  PathVectorPtr_t validPathVector = PathVector::create
	    (path->outputSize (), path->outputDerivativeSize ());
	  validPart = validPathVector;
	  PathPtr_t localValidPart;
	  if (reverse) {
	    value_type param = path->length ();
	    std::deque <PathPtr_t> paths;
	    for (std::size_t i=pv->numberPaths () + 1; i != 0 ; --i) {
	      PathPtr_t localPath (pv->pathAtRank (i-1));
	      if (validate (localPath, reverse, localValidPart, report)) {
		paths.push_front (localPath->copy ());
		param -= localPath->length ();
	      } else {
		report->parameter += param - localPath->length ();
		paths.push_front (localValidPart->copy ());
		for (std::deque <PathPtr_t>::const_iterator it = paths.begin ();
		     it != paths.end (); ++it) {
		  validPathVector->appendPath (*it);
		}
		return false;
	      }
	    }
	    return true;
	  } else {
	    value_type param = 0;
	    for (std::size_t i=0; i < pv->numberPaths (); ++i) {
	      PathPtr_t localPath (pv->pathAtRank (i));
	      if (validate (localPath, reverse, localValidPart, report)) {
		validPathVector->appendPath (localPath->copy ());
		param += localPath->length ();
	      } else {
		report->parameter += param;
		validPathVector->appendPath (localValidPart->copy ());
		return false;
	      }
	    }
	    return true;
	  }
	}
	StraightPathPtr_t straightPath = HPP_DYNAMIC_PTR_CAST
	  (StraightPath, path);
	// for each BodyPairCollision
	//   - set path,
	//   - compute valid interval at start (end if reverse)
	value_type t0 = path->timeRange ().first;
	value_type t1 = path->timeRange ().second;
	if (reverse) {
	  for (BodyPairCollisions_t::iterator itPair =
		 bodyPairCollisions_.begin ();
	       itPair != bodyPairCollisions_.end (); ++itPair) {
	    (*itPair)->path (straightPath);
	    // If collision at end point, return false
	    if (!(*itPair)->validateInterval (t1, *collisionReport)) {
	      report = CollisionPathValidationReportPtr_t
		(new CollisionPathValidationReport (t1, collisionReport));
	      validPart = path->extract (interval_t (t1, t1));
	      return false;
	    }
	    assert ((*itPair)->validSubset ().contains (t1));
	  }
	  // Sort collision pairs
	  bodyPairCollisions_.sort (compareReverseBodyPairCol);

	  BodyPairCollisionPtr_t first = *(bodyPairCollisions_.begin ());
	  while (!first->validSubset ().contains (t0, true)) {
	    // find middle of first non valid interval
	    const std::list <interval_t>& intervals =
	      first->validSubset ().list ();
	    std::list <interval_t>::const_reverse_iterator lastInterval =
	      intervals.rbegin ();
	    std::list <interval_t>::const_reverse_iterator beforeLastInterval =
	      lastInterval; ++beforeLastInterval;
	    value_type upper = lastInterval->first;
	    value_type lower;
	    if (beforeLastInterval != intervals.rend ()) {
	      lower = beforeLastInterval->second;
	    } else {
	      lower = t0;
	    }
	    value_type middle = .5 * (lower + upper);
	    if (first->validateInterval (middle, *collisionReport)) {
	      partialSort (bodyPairCollisions_, compareReverseBodyPairCol);
	    } else {
	      report = CollisionPathValidationReportPtr_t
		(new CollisionPathValidationReport (middle, collisionReport));
	      validPart = path->extract (interval_t (upper, t1));
	      return false;
	    }
	    first = *(bodyPairCollisions_.begin ());
	  }
	} else {
	  for (BodyPairCollisions_t::iterator itPair =
		 bodyPairCollisions_.begin ();
	       itPair != bodyPairCollisions_.end (); ++itPair) {
	    (*itPair)->path (straightPath);
	    // If collision at start point, return false
	    bool valid = (*itPair)->validateInterval (t0, *collisionReport);
	    if (!valid) {
	      report = CollisionPathValidationReportPtr_t
		(new CollisionPathValidationReport (t0, collisionReport));
	      validPart = path->extract (interval_t (t0, t0));
	      hppDout (error, "Initial position in collision.");
	      return false;
	    }
	    assert ((*itPair)->validSubset ().contains (t0));
	  }
	  // Sort collision pairs
	  bodyPairCollisions_.sort (compareBodyPairCol);
	  BodyPairCollisionPtr_t first = *(bodyPairCollisions_.begin ());
	  while (!first->validSubset ().contains (t1)) {
	    // find middle of first non valid interval
	    const std::list <interval_t>& intervals =
	      first->validSubset ().list ();
	    std::list <interval_t>::const_iterator firstInterval =
	      intervals.begin ();
	    std::list <interval_t>::const_iterator secondInterval =
	      firstInterval;
	    ++secondInterval;
	    value_type lower = firstInterval->second;
	    value_type upper;
	    if (secondInterval != intervals.end ()) {
	      upper = secondInterval->first;
	    } else {
	      upper = t1;
	    }
	    value_type middle = .5 * (lower + upper);
	    if (first->validateInterval (middle, *collisionReport)) {
	      partialSort (bodyPairCollisions_, compareBodyPairCol);
	    } else {
	      report = CollisionPathValidationReportPtr_t
		(new CollisionPathValidationReport (middle, collisionReport));
	      validPart = path->extract (interval_t (t0, lower));
	      return false;
	    }
	    first = *(bodyPairCollisions_.begin ());
	  }
	}
	validPart = path;
	return true;
      }

      void Dichotomy::addObstacle
      (const CollisionObjectConstPtr_t& object)
      {
	pinocchio::JointVector_t& jv = robot_->getJointVector ();
	for (size_type idx = 0; idx < jv.size (); ++idx) {
          JointPtr_t j = jv[idx];
	  BodyPtr_t body = j->linkedBody ();
	  bool foundPair = false;
	  if (body) {
	    for (BodyPairCollisions_t::iterator itPair =
		   bodyPairCollisions_.begin ();
		 itPair != bodyPairCollisions_.end (); ++itPair) {
	      if (((*itPair)->joint_a () == j) &&
		  (!(*itPair)->joint_b ())) {
		(*itPair)->addObjectTo_b (object);
		foundPair = true;
	      }
	    }
	    if (!foundPair) {
	      ConstObjectStdVector_t objects;
	      objects.push_back (object);
	      bodyPairCollisions_.push_back
		(BodyPairCollision::create (j, objects, tolerance_));
	    }
	  }
	}
      }

      void Dichotomy::removeObstacleFromJoint
      (const JointPtr_t& joint, const CollisionObjectConstPtr_t& obstacle)
      {
	bool removed = false;
	for (BodyPairCollisions_t::iterator itPair =
	       bodyPairCollisions_.begin ();
	     itPair != bodyPairCollisions_.end (); ++itPair) {
	  if (!(*itPair)->joint_b () && (*itPair)->joint_a () == joint) {
	    if ((*itPair)->removeObjectTo_b (obstacle)) {
	      removed = true;
	      if ((*itPair)->objects_b ().empty ()) {
		bodyPairCollisions_.erase (itPair);
	      }
	    }
	  }
	}
	if (!removed) {
	  std::ostringstream oss;
	  oss << "Dichotomy::removeObstacleFromJoint: obstacle \""
	      << obstacle->name () <<
	    "\" is not registered as obstacle for joint \"" << joint->name ()
	      << "\".";
	  throw std::runtime_error (oss.str ());
	}
      }

      Dichotomy::~Dichotomy ()
      {
      }

      Dichotomy::Dichotomy
      (const DevicePtr_t& robot, const value_type& tolerance) :
	robot_ (robot), tolerance_ (tolerance),
	bodyPairCollisions_ ()
      {
        // Tolerance should be equal to 0, otherwise end of valid
        // sub-path might be in collision.
        if (tolerance != 0) {
          throw std::runtime_error ("Dichotomy path validation method does not"
              "support penetration.");
        }
        // Build body pairs for collision checking
        // First auto-collision
        // FIXME The pairs of joint are duplicated
        const se3::GeometryModel& gmodel = robot->geomModel ();
        JointPtr_t joint1, joint2;
        JointIndexPairSet_t jointPairs;
        std::size_t duplicates = 0;
        for (std::size_t i = 0; i < gmodel.collisionPairs.size(); ++i)
        {
          const se3::CollisionPair& cp = gmodel.collisionPairs[i];
          JointIndexPair_t jp (
              gmodel.geometryObjects[cp.first].parentJoint,
              gmodel.geometryObjects[cp.second].parentJoint);
          if (jointPairs.count(jp) == 0) {
            jointPairs.insert(jp);
            joint1 = JointPtr_t(new Joint(robot_, jp.first));
            joint2 = JointPtr_t(new Joint(robot_, jp.second));
            bodyPairCollisions_.push_back (BodyPairCollision::create
                (joint1, joint2, tolerance_));
            hppDout(info, *bodyPairCollisions_.back());
          } else duplicates++;
        }
        hppDout(info, "Dichotomy continuous collision checking: Inserted "
            << jointPairs.size() << " and filtered " << duplicates <<
            " duplicates." <<  std::endl);
      }
    } // namespace continuousCollisionChecking
  } // namespace core
} // namespace hpp
<|endoftext|>


<commit_before>#pragma once

#include "constants.hpp"
#include "grabber_client.hpp"
#include "hid_system_client.hpp"
#include "local_datagram_server.hpp"
#include "logger.hpp"
#include "types.hpp"
#include <vector>

class receiver final {
public:
  receiver(const receiver&) = delete;

  receiver(void) : exit_loop_(false),
                   hid_system_client_(logger::get_logger()) {
    // Ensure that grabber is running.
    grabber_client_ = std::make_unique<grabber_client>();
    grabber_client_->connect(krbn::connect_from::event_dispatcher);

    const size_t buffer_length = 8 * 1024;
    buffer_.resize(buffer_length);

    mkdir(constants::get_tmp_directory(), 0755);
    const char* path = constants::get_event_dispatcher_socket_file_path();
    unlink(path);
    server_ = std::make_unique<local_datagram_server>(path);
    chmod(path, 0600);

    exit_loop_ = false;
    thread_ = std::thread([this] { this->worker(); });

    logger::get_logger().info("receiver is started");
  }

  ~receiver(void) {
    unlink(constants::get_event_dispatcher_socket_file_path());

    exit_loop_ = true;
    if (thread_.joinable()) {
      thread_.join();
    }

    grabber_client_ = nullptr;
    server_ = nullptr;

    logger::get_logger().info("receiver is stopped");
  }

private:
  void worker(void) {
    if (!server_) {
      return;
    }

    while (!exit_loop_) {
      boost::system::error_code ec;
      std::size_t n = server_->receive(boost::asio::buffer(buffer_), boost::posix_time::seconds(1), ec);

      if (!ec && n > 0) {
        switch (krbn::operation_type(buffer_[0])) {
        case krbn::operation_type::set_caps_lock_state:
          if (n != sizeof(krbn::operation_type_set_caps_lock_state_struct)) {
            logger::get_logger().error("invalid size for krbn::operation_type::set_caps_lock_state");
          } else {
            auto p = reinterpret_cast<krbn::operation_type_set_caps_lock_state_struct*>(&(buffer_[0]));
            hid_system_client_.set_caps_lock_state(p->state);
            if (grabber_client_) {
              grabber_client_->set_caps_lock_led_state(p->state ? krbn::led_state::on : krbn::led_state::off);
            }
          }
          break;

        case krbn::operation_type::refresh_caps_lock_led:
          if (n != sizeof(krbn::operation_type_refresh_caps_lock_led_struct)) {
            logger::get_logger().error("invalid size for krbn::operation_type::refresh_caps_lock_led");
          } else {
            auto state = hid_system_client_.get_caps_lock_state();
            if (!state) {
              logger::get_logger().error("hid_system_client_.get_caps_lock_state error @ {0}", __PRETTY_FUNCTION__);
            } else {
              if (grabber_client_) {
                grabber_client_->set_caps_lock_led_state(*state ? krbn::led_state::on : krbn::led_state::off);
              }
            }
          }
          break;

        case krbn::operation_type::post_modifier_flags:
          if (n != sizeof(krbn::operation_type_post_modifier_flags_struct)) {
            logger::get_logger().error("invalid size for krbn::operation_type::post_modifier_flags");
          } else {
            auto p = reinterpret_cast<krbn::operation_type_post_modifier_flags_struct*>(&(buffer_[0]));
            hid_system_client_.post_modifier_flags(p->key_code, p->flags, p->keyboard_type);
          }
          break;

        case krbn::operation_type::post_key:
          if (n != sizeof(krbn::operation_type_post_key_struct)) {
            logger::get_logger().error("invalid size for krbn::operation_type::post_key");
          } else {
            auto p = reinterpret_cast<krbn::operation_type_post_key_struct*>(&(buffer_[0]));
            hid_system_client_.post_key(p->key_code, p->event_type, p->flags, p->repeat, p->keyboard_type);
          }
          break;

        default:
          break;
        }
      }
    }
  }

  std::vector<uint8_t> buffer_;
  std::unique_ptr<local_datagram_server> server_;
  std::unique_ptr<grabber_client> grabber_client_;
  std::thread thread_;
  std::atomic<bool> exit_loop_;

  hid_system_client hid_system_client_;
};
<commit_msg>update arguments order<commit_after>#pragma once

#include "constants.hpp"
#include "grabber_client.hpp"
#include "hid_system_client.hpp"
#include "local_datagram_server.hpp"
#include "logger.hpp"
#include "types.hpp"
#include <vector>

class receiver final {
public:
  receiver(const receiver&) = delete;

  receiver(void) : exit_loop_(false),
                   hid_system_client_(logger::get_logger()) {
    // Ensure that grabber is running.
    grabber_client_ = std::make_unique<grabber_client>();
    grabber_client_->connect(krbn::connect_from::event_dispatcher);

    const size_t buffer_length = 8 * 1024;
    buffer_.resize(buffer_length);

    mkdir(constants::get_tmp_directory(), 0755);
    const char* path = constants::get_event_dispatcher_socket_file_path();
    unlink(path);
    server_ = std::make_unique<local_datagram_server>(path);
    chmod(path, 0600);

    exit_loop_ = false;
    thread_ = std::thread([this] { this->worker(); });

    logger::get_logger().info("receiver is started");
  }

  ~receiver(void) {
    unlink(constants::get_event_dispatcher_socket_file_path());

    exit_loop_ = true;
    if (thread_.joinable()) {
      thread_.join();
    }

    grabber_client_ = nullptr;
    server_ = nullptr;

    logger::get_logger().info("receiver is stopped");
  }

private:
  void worker(void) {
    if (!server_) {
      return;
    }

    while (!exit_loop_) {
      boost::system::error_code ec;
      std::size_t n = server_->receive(boost::asio::buffer(buffer_), boost::posix_time::seconds(1), ec);

      if (!ec && n > 0) {
        switch (krbn::operation_type(buffer_[0])) {
        case krbn::operation_type::set_caps_lock_state:
          if (n != sizeof(krbn::operation_type_set_caps_lock_state_struct)) {
            logger::get_logger().error("invalid size for krbn::operation_type::set_caps_lock_state");
          } else {
            auto p = reinterpret_cast<krbn::operation_type_set_caps_lock_state_struct*>(&(buffer_[0]));
            hid_system_client_.set_caps_lock_state(p->state);
            if (grabber_client_) {
              grabber_client_->set_caps_lock_led_state(p->state ? krbn::led_state::on : krbn::led_state::off);
            }
          }
          break;

        case krbn::operation_type::refresh_caps_lock_led:
          if (n != sizeof(krbn::operation_type_refresh_caps_lock_led_struct)) {
            logger::get_logger().error("invalid size for krbn::operation_type::refresh_caps_lock_led");
          } else {
            auto state = hid_system_client_.get_caps_lock_state();
            if (!state) {
              logger::get_logger().error("hid_system_client_.get_caps_lock_state error @ {0}", __PRETTY_FUNCTION__);
            } else {
              if (grabber_client_) {
                grabber_client_->set_caps_lock_led_state(*state ? krbn::led_state::on : krbn::led_state::off);
              }
            }
          }
          break;

        case krbn::operation_type::post_modifier_flags:
          if (n != sizeof(krbn::operation_type_post_modifier_flags_struct)) {
            logger::get_logger().error("invalid size for krbn::operation_type::post_modifier_flags");
          } else {
            auto p = reinterpret_cast<krbn::operation_type_post_modifier_flags_struct*>(&(buffer_[0]));
            hid_system_client_.post_modifier_flags(p->key_code, p->flags, p->keyboard_type);
          }
          break;

        case krbn::operation_type::post_key:
          if (n != sizeof(krbn::operation_type_post_key_struct)) {
            logger::get_logger().error("invalid size for krbn::operation_type::post_key");
          } else {
            auto p = reinterpret_cast<krbn::operation_type_post_key_struct*>(&(buffer_[0]));
            hid_system_client_.post_key(p->key_code, p->event_type, p->flags, p->keyboard_type, p->repeat);
          }
          break;

        default:
          break;
        }
      }
    }
  }

  std::vector<uint8_t> buffer_;
  std::unique_ptr<local_datagram_server> server_;
  std::unique_ptr<grabber_client> grabber_client_;
  std::thread thread_;
  std::atomic<bool> exit_loop_;

  hid_system_client hid_system_client_;
};
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

#ifndef __PROCESS_SYSTEM_HPP__
#define __PROCESS_SYSTEM_HPP__

#include <string>

#include <process/future.hpp>
#include <process/help.hpp>
#include <process/http.hpp>
#include <process/process.hpp>

#include <process/metrics/gauge.hpp>
#include <process/metrics/metrics.hpp>

#include <stout/os.hpp>

namespace process {

// The System process provides HTTP endpoints for retrieving system metrics,
// such as CPU load and memory usage. This is started by default during the
// initialization of libprocess.
class System : public Process<System>
{
public:
  System()
    : ProcessBase("system"),
      load_1min(
          self().id + "/load_1min",
          defer(self(), &System::_load_1min)),
      load_5min(
          self().id + "/load_5min",
          defer(self(), &System::_load_5min)),
      load_15min(
          self().id + "/load_15min",
          defer(self(), &System::_load_15min)),
      cpus_total(
          self().id + "/cpus_total",
          defer(self(), &System::_cpus_total)),
      mem_total_bytes(
          self().id + "/mem_total_bytes",
          defer(self(), &System::_mem_total_bytes)),
      mem_free_bytes(
          self().id + "/mem_free_bytes",
          defer(self(), &System::_mem_free_bytes)) {}

  virtual ~System() {}

protected:
  virtual void initialize()
  {
    // TODO(dhamon): Check return values.
    metrics::add(load_1min);
    metrics::add(load_5min);
    metrics::add(load_15min);
    metrics::add(cpus_total);
    metrics::add(mem_total_bytes);
    metrics::add(mem_free_bytes);

    route("/stats.json", statsHelp(), &System::stats);
  }

  virtual void finalize()
  {
    metrics::remove(load_1min);
    metrics::remove(load_5min);
    metrics::remove(load_15min);
    metrics::remove(cpus_total);
    metrics::remove(mem_total_bytes);
    metrics::remove(mem_free_bytes);
  }

private:
  static std::string statsHelp()
  {
    return HELP(
      TLDR(
          "Shows local system metrics."),
      DESCRIPTION(
          ">        cpus_total          Total number of available CPUs",
          ">        load_1min           Average system load for last"
          " minute in uptime(1) style",
          ">        load_5min           Average system load for last"
          " 5 minutes in uptime(1) style",
          ">        load_15min          Average system load for last"
          " 15 minutes in uptime(1) style",
          ">        memory_total_bytes  Total system memory in bytes",
          ">        memory_free_bytes   Free system memory in bytes"));
  }

  // Gauge handlers.
  Future<double> _load_1min()
  {
    Try<os::Load> load = os::loadavg();
    if (load.isSome()) {
      return load.get().one;
    }
    return Failure("Failed to get loadavg: " + load.error());
  }

  Future<double> _load_5min()
  {
    Try<os::Load> load = os::loadavg();
    if (load.isSome()) {
      return load.get().five;
    }
    return Failure("Failed to get loadavg: " + load.error());
  }

  Future<double> _load_15min()
  {
    Try<os::Load> load = os::loadavg();
    if (load.isSome()) {
      return load.get().fifteen;
    }
    return Failure("Failed to get loadavg: " + load.error());
  }

  Future<double> _cpus_total()
  {
    Try<long> cpus = os::cpus();
    if (cpus.isSome()) {
      return cpus.get();
    }
    return Failure("Failed to get cpus: " + cpus.error());
  }

  Future<double> _mem_total_bytes()
  {
    Try<os::Memory> memory = os::memory();
    if (memory.isSome()) {
      return memory.get().total.bytes();
    }
    return Failure("Failed to get memory: " + memory.error());
  }

  Future<double> _mem_free_bytes()
  {
    Try<os::Memory> memory = os::memory();
    if (memory.isSome()) {
      return memory.get().free.bytes();
    }
    return Failure("Failed to get memory: " + memory.error());
  }

  // HTTP endpoints.
  Future<http::Response> stats(const http::Request& request)
  {
    JSON::Object object;
    Try<os::Load> load = os::loadavg();
    if (load.isSome()) {
      object.values["avg_load_1min"] = load.get().one;
      object.values["avg_load_5min"] = load.get().five;
      object.values["avg_load_15min"] = load.get().fifteen;
    }

    Try<long> cpus = os::cpus();
    if (cpus.isSome()) {
      object.values["cpus_total"] = cpus.get();
    }

    Try<os::Memory> memory = os::memory();
    if (memory.isSome()) {
      object.values["mem_total_bytes"] = memory.get().total.bytes();
      object.values["mem_free_bytes"] = memory.get().free.bytes();
    }

    return http::OK(object, request.url.query.get("jsonp"));
  }

  metrics::Gauge load_1min;
  metrics::Gauge load_5min;
  metrics::Gauge load_15min;

  metrics::Gauge cpus_total;

  metrics::Gauge mem_total_bytes;
  metrics::Gauge mem_free_bytes;
};

} // namespace process {

#endif // __PROCESS_SYSTEM_HPP__
<commit_msg>Fixed warnings in `process/system.hpp`.<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

#ifndef __PROCESS_SYSTEM_HPP__
#define __PROCESS_SYSTEM_HPP__

#include <string>

#include <process/future.hpp>
#include <process/help.hpp>
#include <process/http.hpp>
#include <process/process.hpp>

#include <process/metrics/gauge.hpp>
#include <process/metrics/metrics.hpp>

#include <stout/os.hpp>

namespace process {

// The System process provides HTTP endpoints for retrieving system metrics,
// such as CPU load and memory usage. This is started by default during the
// initialization of libprocess.
class System : public Process<System>
{
public:
  System()
    : ProcessBase("system"),
      load_1min(
          self().id + "/load_1min",
          defer(self(), &System::_load_1min)),
      load_5min(
          self().id + "/load_5min",
          defer(self(), &System::_load_5min)),
      load_15min(
          self().id + "/load_15min",
          defer(self(), &System::_load_15min)),
      cpus_total(
          self().id + "/cpus_total",
          defer(self(), &System::_cpus_total)),
      mem_total_bytes(
          self().id + "/mem_total_bytes",
          defer(self(), &System::_mem_total_bytes)),
      mem_free_bytes(
          self().id + "/mem_free_bytes",
          defer(self(), &System::_mem_free_bytes)) {}

  virtual ~System() {}

protected:
  virtual void initialize()
  {
    // TODO(dhamon): Check return values.
    metrics::add(load_1min);
    metrics::add(load_5min);
    metrics::add(load_15min);
    metrics::add(cpus_total);
    metrics::add(mem_total_bytes);
    metrics::add(mem_free_bytes);

    route("/stats.json", statsHelp(), &System::stats);
  }

  virtual void finalize()
  {
    metrics::remove(load_1min);
    metrics::remove(load_5min);
    metrics::remove(load_15min);
    metrics::remove(cpus_total);
    metrics::remove(mem_total_bytes);
    metrics::remove(mem_free_bytes);
  }

private:
  static std::string statsHelp()
  {
    return HELP(
      TLDR(
          "Shows local system metrics."),
      DESCRIPTION(
          ">        cpus_total          Total number of available CPUs",
          ">        load_1min           Average system load for last"
          " minute in uptime(1) style",
          ">        load_5min           Average system load for last"
          " 5 minutes in uptime(1) style",
          ">        load_15min          Average system load for last"
          " 15 minutes in uptime(1) style",
          ">        memory_total_bytes  Total system memory in bytes",
          ">        memory_free_bytes   Free system memory in bytes"));
  }

  // Gauge handlers.
  Future<double> _load_1min()
  {
    Try<os::Load> load = os::loadavg();
    if (load.isSome()) {
      return load.get().one;
    }
    return Failure("Failed to get loadavg: " + load.error());
  }

  Future<double> _load_5min()
  {
    Try<os::Load> load = os::loadavg();
    if (load.isSome()) {
      return load.get().five;
    }
    return Failure("Failed to get loadavg: " + load.error());
  }

  Future<double> _load_15min()
  {
    Try<os::Load> load = os::loadavg();
    if (load.isSome()) {
      return load.get().fifteen;
    }
    return Failure("Failed to get loadavg: " + load.error());
  }

  Future<double> _cpus_total()
  {
    Try<long> cpus = os::cpus();
    if (cpus.isSome()) {
      return cpus.get();
    }
    return Failure("Failed to get cpus: " + cpus.error());
  }

  Future<double> _mem_total_bytes()
  {
    Try<os::Memory> memory = os::memory();
    if (memory.isSome()) {
      return static_cast<double>(memory.get().total.bytes());
    }
    return Failure("Failed to get memory: " + memory.error());
  }

  Future<double> _mem_free_bytes()
  {
    Try<os::Memory> memory = os::memory();
    if (memory.isSome()) {
      return static_cast<double>(memory.get().free.bytes());
    }
    return Failure("Failed to get memory: " + memory.error());
  }

  // HTTP endpoints.
  Future<http::Response> stats(const http::Request& request)
  {
    JSON::Object object;
    Try<os::Load> load = os::loadavg();
    if (load.isSome()) {
      object.values["avg_load_1min"] = load.get().one;
      object.values["avg_load_5min"] = load.get().five;
      object.values["avg_load_15min"] = load.get().fifteen;
    }

    Try<long> cpus = os::cpus();
    if (cpus.isSome()) {
      object.values["cpus_total"] = cpus.get();
    }

    Try<os::Memory> memory = os::memory();
    if (memory.isSome()) {
      object.values["mem_total_bytes"] = memory.get().total.bytes();
      object.values["mem_free_bytes"] = memory.get().free.bytes();
    }

    return http::OK(object, request.url.query.get("jsonp"));
  }

  metrics::Gauge load_1min;
  metrics::Gauge load_5min;
  metrics::Gauge load_15min;

  metrics::Gauge cpus_total;

  metrics::Gauge mem_total_bytes;
  metrics::Gauge mem_free_bytes;
};

} // namespace process {

#endif // __PROCESS_SYSTEM_HPP__
<|endoftext|>


<commit_before>/*
gpe_editor_aboutpage.cpp
This file is part of:
GAME PENCIL ENGINE
https://create.pawbyte.com
Copyright (c) 2014-2020 Nathan Hurde, Chase Lee.

Copyright (c) 2014-2020 PawByte LLC.
Copyright (c) 2014-2020 Game Pencil Engine contributors ( Contributors Page )

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, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

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. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

-Game Pencil Engine <https://create.pawbyte.com>

*/

#include "gpe_editor_aboutpage.h"

gamePencilAboutPageResource * MAIN_ABOUT_PAGE = NULL;

gamePencilAboutPageResource::gamePencilAboutPageResource()
{
    isFullScreenResource = true;
    resourceFileName = "";
    resourceName = "About Page";
    parentProjectName = "";
    parentProjectDirectory = "";
    //GPE_Animation * mainMenuanimation = guiRCM->animation_add(APP_DIRECTORY_NAME+"resources/gfx/animations/gpe_main_icons_big.png",70,true,0,0,false);

    sideAreaPanel = new GPE_SelectBoxBasic("Mode");
    sideAreaPanel->set_width(256);
    sideAreaPanel->set_option_height(64);
    sideAreaPanel->add_option("Credits",-1,guiRCM->texture_add(APP_DIRECTORY_NAME+"resources/gfx/iconpacks/fontawesome/heart.png"),NULL,2, false, false);
    sideAreaPanel->add_option("License",-1,guiRCM->texture_add(APP_DIRECTORY_NAME+"resources/gfx/iconpacks/fontawesome/file-text.png"),NULL,2, false, false);
    sideAreaPanel->add_option("3rd Party Licenses",-1,guiRCM->texture_add(APP_DIRECTORY_NAME+"resources/gfx/iconpacks/fontawesome/group.png"),NULL,2, false, false);

    sidePanelRect = new GPE_Rect();

    aboutPageList = new GPE_GuiElementList();

    pencilCredits = new GPE_TextAreaInputBasic();
    pencilCredits->isCodeEditor = false;
    pencilCredits->set_read_only();
    pencilCredits->clear_all_lines();
    pencilCredits->add_line("PawByte Development Team");
    pencilCredits->add_line("-----------------------------------");
    pencilCredits->add_line("Nathan Hurde:               Lead IDE & Engine Developer");
    pencilCredits->add_line("Chase Lee:                  Lead Web Developer & Color Theme Author");
    pencilCredits->add_line("Karl Cons:                  Alpha testing of Version 0.2");

    pencilCredits->add_line("");
    pencilCredits->add_line("");
    pencilCredits->add_line("Community Contributors (Ordered Alphabetically):");
    pencilCredits->add_line("-----------------------------------");
    pencilCredits->add_line("Anthony Manetti:            Private Alpha testing of Version 0.2");
    pencilCredits->add_line("Clint R Bellenger:          Technical advising and help with input systems");
    pencilCredits->add_line("Daniel Gump:                Technical advising and help with HTML5 engine optimizations");
    pencilCredits->add_line("@deadda7a:                  Helped with creation of new color theming for Version 1.0.1 and beyond.");
    pencilCredits->add_line("@GTMalachiasV:              Critical feedback and testing for improving Project Browser");
    pencilCredits->add_line("@JeZxLee:                   Located Launcher error for files with spaces/symbols in their file name.");
    pencilCredits->add_line("Mac Carter:                 Usage of Mac to create & test OSX build.");
    pencilCredits->add_line("Russell Johnston:           Technical advising and help with syntax highlighting system");
    pencilCredits->add_line("Tim C( timchoh585):         Updated README.md to a professional level");
    pencilCredits->add_line("Toyam Cox( Vaelatern):      Created initial makefile");
    pencilCredits->add_line("YellowAfterLife:            Technical advising and help with collision systems");

    pencilCredits->add_line("");
    pencilCredits->add_line("");
    pencilCredits->add_line("Artwork (Ordered Alphabetically):");
    pencilCredits->add_line("-----------------------------------");
    pencilCredits->add_line("David Gandy:               Creator of Font Aesome [ https://twitter.com/davegandy ]");
    pencilCredits->add_line("Damian Kaczmarek           Font-Awesome-SVG-PNG Author [ rush@rushbase.net @Rush ]");
    pencilCredits->add_line("Dominykas Blyžė            Font-Awesome-SVG-PNG Author [ hello@dominykas.com @dominykas]");
    pencilCredits->add_line("@deadda7a:                 Created 'Game Pencil' logo");
    pencilCredits->add_line("Font Awesome:              Icons and Buttons [ http://fontawesome.io/ ]");
    pencilCredits->add_line("The Font Awesome font is licensed under the SIL OFL 1.1:");
    pencilCredits->add_line("http://scripts.sil.org/OFL  ");
    pencilCredits->add_line("Font-Awesome-SVG-PNG is licensed under the MIT license  ");

    pencilCredits->add_line("");
    pencilCredits->add_line("");
    pencilCredits->add_line("Technologies (Ordered Alphabetically):");
    pencilCredits->add_line("-----------------------------------");
    pencilCredits->add_line("Electron[Used for Desktop Exports]:            http://electron.atom.io/");
    pencilCredits->add_line("IsImageOk:                                     http://blog.sajithmr.me/javascript-check-an-image-is-loaded-or-not/");
    pencilCredits->add_line("JavaScript FileReader:                         http://stackoverflow.com/questions/23331546/how-to-use-javascript-to-read-local-text-file-and-read-line-by-line");
    pencilCredits->add_line("RequestFrameAnimation:                         http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/");
    pencilCredits->add_line("Simple DirectMedia Layer(SDL):                 http://www.libsdl.org");
    pencilCredits->add_line("SDL_GFX:                                       http://www.ferzkopp.net/wordpress/2016/01/02/sdl_gfx-sdl2_gfx/");
    pencilCredits->add_line("FPS_CAP & FPS_Calculator functions:            https://davidgow.net/handmadepenguin/ch18.html/");

    pencilCredits->add_line("");
    pencilCredits->add_line("Patreon Backers (Ordered Alphabetically):");
    pencilCredits->add_line("-----------------------------------");
    pencilCredits->add_line("     Feral Monk");
    pencilCredits->add_line("     James Thomas");
    pencilCredits->add_line("     James Thomas");
    pencilCredits->add_line("     Joseph Yarrow");
    pencilCredits->add_line("     Mark Medrano");
    pencilCredits->add_line("     Keith Thomas");
    pencilCredits->add_line("     Noel Hurde");
    pencilCredits->add_line("     Thomas Ingham");
    pencilCredits->add_line("     Roshin Varghese");

    pencilCredits->add_line("Itch.io Supporters (Ordered Alphabetically):");
    pencilCredits->add_line("-----------------------------------");
    pencilCredits->add_line("     Aisha Halim");
    pencilCredits->add_line("     Alessandro Montoli ( funkygallo)");
    pencilCredits->add_line("     _Auron_");
    pencilCredits->add_line("     bojjenclon");
    pencilCredits->add_line("     CammyGamesYT");
    pencilCredits->add_line("     Chad Davis");
    pencilCredits->add_line("     DarkLightGames");
    pencilCredits->add_line("     Davey13");
    pencilCredits->add_line("     evilemprzurg");
    pencilCredits->add_line("     F. Keitz");
    pencilCredits->add_line("     Florian Zwerina");
    pencilCredits->add_line("     Goldenkitty");
    pencilCredits->add_line("     Goldenxp");
    pencilCredits->add_line("     jarrett9999");
    pencilCredits->add_line("     Mark Henning");
    pencilCredits->add_line("     microrutter");
    pencilCredits->add_line("     M. Moy");
    pencilCredits->add_line("     Kat Leopardess");
    pencilCredits->add_line("     popcade");
    pencilCredits->add_line("     raymond13557");
    pencilCredits->add_line("     RookTKO");
    pencilCredits->add_line("     Samson194");
    pencilCredits->add_line("     TH");
    pencilCredits->add_line("     Veron Hurde Jr.");
    pencilCredits->add_line("     Woody Stanfield");
    pencilCredits->add_line("     Zonemaster");

    pencilCredits->add_line("");
    pencilCredits->add_line("KickStarter Backers (Ordered Alphabetically):");
    pencilCredits->add_line("-----------------------------------");

    pencilCredits->add_line("     Aisha Halim");
    pencilCredits->add_line("     Aleksander Kwitakowski");
    pencilCredits->add_line("     Alex King");
    pencilCredits->add_line("     Alyssia Ashkevron");
    pencilCredits->add_line("     Arturas Norkus");
    pencilCredits->add_line("     Blair Johnson");
    pencilCredits->add_line("     Christopher Murt");
    pencilCredits->add_line("     Christopher Pope");
    pencilCredits->add_line("     Climb Fitness");
    pencilCredits->add_line("     Curtis Hurde");
    pencilCredits->add_line("     Daniel Stempniewicz");
    pencilCredits->add_line("     David Goldsmith");
    pencilCredits->add_line("     Derek Lawson");
    pencilCredits->add_line("     James Donachie");
    pencilCredits->add_line("     Giacomo Russo");
    pencilCredits->add_line("     Trevor Hayes");
    pencilCredits->add_line("     Godewijn Perizonius");
    pencilCredits->add_line("     Greg Polander");
    pencilCredits->add_line("     HBComics");
    pencilCredits->add_line("     Henri Niva");
    pencilCredits->add_line("     Jake Miller");
    pencilCredits->add_line("     James Bowling");
    pencilCredits->add_line("     Jason Mason Pierce");
    pencilCredits->add_line("     Jason Hornbuckle");
    pencilCredits->add_line("     Jeff Hanson");
    pencilCredits->add_line("     Joel A. Luellwitz");
    pencilCredits->add_line("     Johan Brodd");
    pencilCredits->add_line("     John Isakisson");
    pencilCredits->add_line("     John Lerchen");
    pencilCredits->add_line("     John Robertson");
    pencilCredits->add_line("     Johnathon Stevens");
    pencilCredits->add_line("     Jonathan Chang");
    pencilCredits->add_line("     Jose P. Zagal");
    pencilCredits->add_line("     Joshua Boren");
    pencilCredits->add_line("     jwilloug");
    pencilCredits->add_line("     Kelly Samuels");
    pencilCredits->add_line("     kuroiXiru");
    pencilCredits->add_line("     Pawel Sowizral");
    pencilCredits->add_line("     Lukasz Stempniewicz");
    pencilCredits->add_line("     Eden Caldas");
    pencilCredits->add_line("     Markus Løtveit");
    pencilCredits->add_line("     Matthew Schie");
    pencilCredits->add_line("     Matthew Sutherland");
    pencilCredits->add_line("     Max Juchheim");
    pencilCredits->add_line("     Meg Stivison");
    pencilCredits->add_line("     Michael Grenetz");
    pencilCredits->add_line("     Michael Parkin-White");
    pencilCredits->add_line("     Paul Beerkens");
    pencilCredits->add_line("     Paul Broadhurst");
    pencilCredits->add_line("     Roy Mwale");
    pencilCredits->add_line("     Sagi Koren");
    pencilCredits->add_line("     Seumas Cordell Froemke");
    pencilCredits->add_line("     Taran Buford");
    pencilCredits->add_line("     Teresa Ziebarth");
    pencilCredits->add_line("     Toby Hutton");
    pencilCredits->add_line("     Andreas Heldt");
    pencilCredits->add_line("     Zach Underwood");

    pencilCredits->add_line("");
    pencilCredits->add_line("");
    pencilCredits->add_line("Thank you for backing Agriduel aka Fields of Fresh which lead to this IDE and engine being developed.");
    pencilCredits->add_line("");
    pencilCredits->add_line("-----------------------------------");
    pencilCredits->add_line("");
    pencilCredits->add_line("Thank you for using the Game Pencil Engine.");
    pencilCredits->add_line("");
    pencilCredits->add_line("");

    pencilDescription = new GPE_TextAreaInputBasic();
    pencilDescription->set_read_only();
    pencilDescription->isCodeEditor = false;

    pencilDescription->clear_all_lines();
    pencilDescription->import_text(APP_DIRECTORY_NAME+"editor_description.txt");
    pencilDescription->set_height(640);

    pencilMissionStatement = new GPE_TextAreaInputBasic();
    pencilMissionStatement->set_read_only();
    pencilMissionStatement->isCodeEditor = false;

    pencilLicense = new GPE_TextAreaInputBasic();
    pencilLicense->set_read_only();
    pencilLicense->isCodeEditor = false;

    //pencilLicense->set_read_only();
    pencilLicense->add_line("Copyright (c) 2016-2018 PawByte, Nathan Hurde. All rights reserved..");
    pencilLicense->add_line(".");
    pencilLicense->add_line("Redistribution and use in source and binary forms, with or without");
    pencilLicense->add_line("modification, are permitted provided that the following conditions are");
    pencilLicense->add_line("met:.");
    pencilLicense->add_line(".");
    pencilLicense->add_line("* Redistributions of source code must retain the above copyright");
    pencilLicense->add_line("notice, this list of conditions and the following disclaimer.");
    pencilLicense->add_line("   * Redistributions in binary form must reproduce the above");
    pencilLicense->add_line("copyright notice, this list of conditions and the following disclaimer");
    pencilLicense->add_line("in the documentation and/or other materials provided with the");
    pencilLicense->add_line("distribution..");
    pencilLicense->add_line("   * Neither the name of PawByte. nor the names of its");
    pencilLicense->add_line("team nor its contributors may be used to endorse or promote products derived from");
    pencilLicense->add_line("this software without specific prior written permission..");
    pencilLicense->add_line("");
    pencilLicense->add_line("THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS");
    pencilLicense->add_line("'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT");
    pencilLicense->add_line("LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR");
    pencilLicense->add_line("A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT");
    pencilLicense->add_line("OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,");
    pencilLicense->add_line("SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT");
    pencilLicense->add_line("LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,");
    pencilLicense->add_line("DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY.");
    pencilLicense->add_line("THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT");
    pencilLicense->add_line("(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE");
    pencilLicense->add_line("OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.");
    pencilLicense->add_line("");
    pencilLicense->set_height(640);

    thirdPartyLicenses = new GPE_TextAreaInputBasic();
    thirdPartyLicenses->set_read_only();
    thirdPartyLicenses->isCodeEditor = false;
    thirdPartyLicenses->import_text(APP_DIRECTORY_NAME+"third_party_licenses.txt");
    thirdPartyLicenses->set_height(640);

    aboutPageList->barXPadding = GENERAL_GPE_GUI_PADDING;
    aboutPageList->barXMargin = 0;
}

gamePencilAboutPageResource::~gamePencilAboutPageResource()
{
    subViewedSpace.x = GENERAL_GPE_GUI_PADDING;
    subViewedSpace.y = GENERAL_GPE_GUI_PADDING;
    subViewedSpace.w = 400;
    subViewedSpace.h = 400;
    resourceType = -2;
    subResouceId = -2;
    parentProjectName = "";

    if( aboutPageList!=NULL)
    {
        delete aboutPageList;
        aboutPageList = NULL;
    }
    if( pencilCredits!=NULL)
    {
        delete pencilCredits;
        pencilCredits = NULL;
    }
    if( pencilDescription!=NULL)
    {
        delete pencilDescription;
        pencilDescription = NULL;
    }
    if( pencilLicense!=NULL)
    {
        delete pencilLicense;
        pencilLicense = NULL;
    }
    if( thirdPartyLicenses!=NULL)
    {
        delete thirdPartyLicenses;
        thirdPartyLicenses = NULL;
    }
    if( pencilMissionStatement!=NULL)
    {
        delete pencilMissionStatement;
        pencilMissionStatement = NULL;
    }
}

bool gamePencilAboutPageResource::include_local_files( std::string pBuildDir , int buildType )
{

}

void gamePencilAboutPageResource::prerender_self( )
{

}

void gamePencilAboutPageResource::preprocess_self(std::string alternatePath)
{

}

void gamePencilAboutPageResource::process_self(GPE_Rect * viewedSpace, GPE_Rect * cam )
{
    viewedSpace = GPE_find_camera(viewedSpace);
    cam = GPE_find_camera(cam);
    if( viewedSpace!=NULL && aboutPageList!=NULL)
    {
        int prevTab = sideAreaPanel->get_selection();
        if( PANEL_GENERAL_EDITOR!=NULL )
        {
            subViewedSpace.x = 0;
            subViewedSpace.y = 0;
            subViewedSpace.w = viewedSpace->w;
            subViewedSpace.h = viewedSpace->h;
            PANEL_GENERAL_EDITOR->add_gui_element_fullsize( sideAreaPanel );
            PANEL_GENERAL_EDITOR->process_self();

        }
        else
        {
            sideAreaPanel->set_coords(0, 0 );
            sideAreaPanel->set_height( viewedSpace->h );
            sideAreaPanel->process_self( viewedSpace, cam );
            subViewedSpace.x = sideAreaPanel->get_x2pos();
            subViewedSpace.y = 0;
            subViewedSpace.w = viewedSpace->w - sideAreaPanel->get_width();
            subViewedSpace.h = viewedSpace->h;
        }

        if( prevTab!=sideAreaPanel->get_selection() )
        {
            aboutPageList->reset_self();
        }

        aboutPageList->set_coords(subViewedSpace.x,subViewedSpace.y );
        aboutPageList->set_width(subViewedSpace.w);
        aboutPageList->set_height(subViewedSpace.h );
        aboutPageList->barXPadding = GENERAL_GPE_GUI_PADDING;
        aboutPageList->barXMargin = subViewedSpace.w/8;

        aboutPageList->clear_list();
        if( sideAreaPanel->get_selected_name()=="Credits")
        {
            aboutPageList->add_gui_element_fullsize(pencilCredits);
        }
        else if( sideAreaPanel->get_selected_name()=="Description" )
        {
            aboutPageList->add_gui_element_fullsize(pencilDescription);
        }
        else if( sideAreaPanel->get_selected_name()=="License" )
        {
            aboutPageList->add_gui_element_fullsize(pencilLicense);
        }
        else if( sideAreaPanel->get_selected_name()=="3rd Party Licenses" )
        {
            aboutPageList->add_gui_element_fullsize(thirdPartyLicenses);
        }
        aboutPageList->process_self(viewedSpace,cam);
    }
}

void gamePencilAboutPageResource::render_self(GPE_Rect * viewedSpace, GPE_Rect * cam )
{
    viewedSpace = GPE_find_camera(viewedSpace);
    cam = GPE_find_camera(cam);
    if( cam!=NULL && viewedSpace!=NULL)
    {
        if( sideAreaPanel!=NULL && PANEL_GENERAL_EDITOR==NULL )
        {
            sideAreaPanel->render_self( viewedSpace,cam);
        }
        if( aboutPageList!=NULL )
        {
            aboutPageList->render_self( viewedSpace,cam);
        }
    }
}

void gamePencilAboutPageResource::save_resource(std::string alternatePath, int backupId)
{
    bool usingAltSaveSource = false;
    isModified = false;
}

bool gamePencilAboutPageResource::write_data_into_projectfile(std::ofstream * fileTarget, int nestedFoldersIn)
{
    return true;
}
<commit_msg>Delete gpe_editor_aboutpage.cpp<commit_after><|endoftext|>