mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-19 01:05:46 -04:00
Initial community commit
This commit is contained in:
306
Src/replicant/nswasabi/APEv2Metadata.cpp
Normal file
306
Src/replicant/nswasabi/APEv2Metadata.cpp
Normal file
@ -0,0 +1,306 @@
|
||||
#include "APEv2Metadata.h"
|
||||
#include "metadata/MetadataKeys.h"
|
||||
#include "nu/ByteReader.h"
|
||||
#include "nswasabi/ReferenceCounted.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static inline bool TestFlag(int flags, int flag_to_check)
|
||||
{
|
||||
if (flags & flag_to_check)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
api_metadata *APEv2Metadata::metadata_api=0;
|
||||
|
||||
APEv2Metadata::APEv2Metadata()
|
||||
{
|
||||
apev2_tag=0;
|
||||
}
|
||||
|
||||
APEv2Metadata::~APEv2Metadata()
|
||||
{
|
||||
}
|
||||
|
||||
int APEv2Metadata::Initialize(api_metadata *metadata_api)
|
||||
{
|
||||
APEv2Metadata::metadata_api = metadata_api;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int APEv2Metadata::Initialize(nsapev2_tag_t tag)
|
||||
{
|
||||
apev2_tag = tag;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
|
||||
/* ifc_metadata implementation */
|
||||
int APEv2Metadata::Metadata_GetField(int field, unsigned int index, nx_string_t *value)
|
||||
{
|
||||
if (!apev2_tag)
|
||||
return NErr_Unknown;
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case MetadataKeys::TRACK_GAIN:
|
||||
return NSAPEv2_Tag_GetString(apev2_tag, "REPLAYGAIN_TRACK_GAIN", index, value);
|
||||
case MetadataKeys::TRACK_PEAK:
|
||||
return NSAPEv2_Tag_GetString(apev2_tag, "REPLAYGAIN_TRACK_PEAK", index, value);
|
||||
case MetadataKeys::ALBUM_GAIN:
|
||||
return NSAPEv2_Tag_GetString(apev2_tag, "REPLAYGAIN_ALBUM_GAIN", index, value);
|
||||
case MetadataKeys::ALBUM_PEAK:
|
||||
return NSAPEv2_Tag_GetString(apev2_tag, "REPLAYGAIN_ALBUM_PEAK", index, value);
|
||||
}
|
||||
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
int APEv2Metadata::Metadata_GetInteger(int field, unsigned int index, int64_t *value)
|
||||
{
|
||||
if (!apev2_tag)
|
||||
return NErr_Unknown;
|
||||
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
int APEv2Metadata::Metadata_GetReal(int field, unsigned int index, double *value)
|
||||
{
|
||||
if (!apev2_tag)
|
||||
return NErr_Unknown;
|
||||
|
||||
int ret;
|
||||
nx_string_t str;
|
||||
switch (field)
|
||||
{
|
||||
case MetadataKeys::TRACK_GAIN:
|
||||
ret = NSAPEv2_Tag_GetString(apev2_tag, "REPLAYGAIN_TRACK_GAIN", index, &str);
|
||||
if (ret == NErr_Success)
|
||||
{
|
||||
ret = NXStringGetDoubleValue(str, value);
|
||||
NXStringRelease(str);
|
||||
}
|
||||
return ret;
|
||||
case MetadataKeys::TRACK_PEAK:
|
||||
ret = NSAPEv2_Tag_GetString(apev2_tag, "REPLAYGAIN_TRACK_PEAK", index, &str);
|
||||
if (ret == NErr_Success)
|
||||
{
|
||||
ret = NXStringGetDoubleValue(str, value);
|
||||
NXStringRelease(str);
|
||||
}
|
||||
return ret;
|
||||
case MetadataKeys::ALBUM_GAIN:
|
||||
ret = NSAPEv2_Tag_GetString(apev2_tag, "REPLAYGAIN_ALBUM_GAIN", index, &str);
|
||||
if (ret == NErr_Success)
|
||||
{
|
||||
ret = NXStringGetDoubleValue(str, value);
|
||||
NXStringRelease(str);
|
||||
}
|
||||
return ret;
|
||||
case MetadataKeys::ALBUM_PEAK:
|
||||
ret = NSAPEv2_Tag_GetString(apev2_tag, "REPLAYGAIN_ALBUM_PEAK", index, &str);
|
||||
if (ret == NErr_Success)
|
||||
{
|
||||
ret = NXStringGetDoubleValue(str, value);
|
||||
NXStringRelease(str);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
static const char *APEv2_GetMIME(const char *extension)
|
||||
{
|
||||
if (!extension)
|
||||
return 0;
|
||||
|
||||
if (strcasecmp(extension, "JPG") == 0 || strcasecmp(extension, "JPEG") == 0)
|
||||
return "image/jpeg";
|
||||
if (strcasecmp(extension, "PNG") == 0)
|
||||
return "image/png";
|
||||
if (strcasecmp(extension, "GIF") == 0)
|
||||
return "image/gif";
|
||||
if (strcasecmp(extension, "BMP") == 0)
|
||||
return "image/bmp";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int APEv2_ParseArt(const void *bytes, size_t length, artwork_t *out_data, data_flags_t flags)
|
||||
{
|
||||
if (out_data)
|
||||
{
|
||||
nx_data_t data=0;
|
||||
if (flags != DATA_FLAG_NONE)
|
||||
{
|
||||
bytereader_s byte_reader;
|
||||
bytereader_init(&byte_reader, bytes, length);
|
||||
if (bytereader_size(&byte_reader) == 0)
|
||||
return NErr_Insufficient;
|
||||
|
||||
const char *description_start = (const char *)bytereader_pointer(&byte_reader);
|
||||
const char *extension_start=0;
|
||||
uint8_t byte;
|
||||
do
|
||||
{
|
||||
if (bytereader_size(&byte_reader) == 0)
|
||||
return NErr_Insufficient;
|
||||
byte = bytereader_read_u8(&byte_reader);
|
||||
if (byte == '.') // found extension
|
||||
{
|
||||
extension_start = (const char *)bytereader_pointer(&byte_reader);
|
||||
}
|
||||
} while (byte && bytereader_size(&byte_reader));
|
||||
|
||||
size_t length = bytereader_size(&byte_reader);
|
||||
|
||||
if (length == 0)
|
||||
return NErr_Empty;
|
||||
|
||||
if (TestFlag(flags, DATA_FLAG_DATA))
|
||||
{
|
||||
int ret = NXDataCreate(&data, bytereader_pointer(&byte_reader), length);
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
int ret = NXDataCreateEmpty(&data);
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (TestFlag(flags, DATA_FLAG_DESCRIPTION))
|
||||
{
|
||||
ReferenceCountedNXString description;
|
||||
size_t length;
|
||||
if (extension_start)
|
||||
length = (size_t)extension_start - (size_t)description_start - 1;
|
||||
else
|
||||
length = (size_t)bytereader_pointer(&byte_reader) - (size_t)description_start - 1;
|
||||
|
||||
if (length)
|
||||
{
|
||||
int ret = NXStringCreateWithBytes(&description, description_start, length, nx_charset_utf8);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
NXDataRelease(data);
|
||||
return ret;
|
||||
}
|
||||
NXDataSetDescription(data, description);
|
||||
}
|
||||
}
|
||||
|
||||
if (TestFlag(flags, DATA_FLAG_MIME))
|
||||
{
|
||||
ReferenceCountedNXString mime_type;
|
||||
const char *mime_string = APEv2_GetMIME(extension_start);
|
||||
if (mime_string)
|
||||
{
|
||||
int ret = NXStringCreateWithUTF8(&mime_type, mime_string);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
NXDataRelease(data);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out_data->data = data;
|
||||
/* we don't know these */
|
||||
out_data->height=0;
|
||||
out_data->width=0;
|
||||
}
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int APEv2Metadata::Metadata_GetArtwork(int field, unsigned int index, artwork_t *data, data_flags_t flags)
|
||||
{
|
||||
if (!apev2_tag)
|
||||
return NErr_Unknown;
|
||||
|
||||
int ret;
|
||||
const void *bytes;
|
||||
size_t length;
|
||||
switch(field)
|
||||
{
|
||||
case MetadataKeys::ALBUM:
|
||||
ret = NSAPEv2_Tag_GetBinary(apev2_tag, "Cover Art (front)", index, &bytes, &length);
|
||||
if (ret == NErr_Success)
|
||||
return APEv2_ParseArt(bytes, length, data, flags);
|
||||
return ret;
|
||||
}
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
int APEv2Metadata::MetadataEditor_SetField(int field, unsigned int index, nx_string_t value)
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case MetadataKeys::TRACK_GAIN:
|
||||
return NSAPEv2_Tag_SetString(apev2_tag, "REPLAYGAIN_TRACK_GAIN", index, value);
|
||||
case MetadataKeys::TRACK_PEAK:
|
||||
return NSAPEv2_Tag_SetString(apev2_tag, "REPLAYGAIN_TRACK_PEAK", index, value);
|
||||
case MetadataKeys::ALBUM_GAIN:
|
||||
return NSAPEv2_Tag_SetString(apev2_tag, "REPLAYGAIN_ALBUM_GAIN", index, value);
|
||||
case MetadataKeys::ALBUM_PEAK:
|
||||
return NSAPEv2_Tag_SetString(apev2_tag, "REPLAYGAIN_ALBUM_PEAK", index, value);
|
||||
}
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
int APEv2Metadata::MetadataEditor_SetInteger(int field, unsigned int index, int64_t value)
|
||||
{
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
int APEv2Metadata::MetadataEditor_SetReal(int field, unsigned int index, double value)
|
||||
{
|
||||
// TODO: but we need NXStringCreateFromDouble which I don't feel like writing right now
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
static void APEv2_GetFilenameForMIME(char *filename, const char *type, nx_string_t mime_type)
|
||||
{
|
||||
if (mime_type)
|
||||
{
|
||||
if (NXStringKeywordCompareWithCString(mime_type, "image/jpeg") == NErr_True || NXStringKeywordCompareWithCString(mime_type, "image/jpg") == NErr_True)
|
||||
sprintf(filename, "%s.jpeg", type);
|
||||
else if (NXStringKeywordCompareWithCString(mime_type, "image/png") == NErr_True)
|
||||
sprintf(filename, "%s.png", type);
|
||||
if (NXStringKeywordCompareWithCString(mime_type, "image/gif") == NErr_True)
|
||||
sprintf(filename, "%s.gif", type);
|
||||
if (NXStringKeywordCompareWithCString(mime_type, "image/bmp") == NErr_True)
|
||||
sprintf(filename, "%s.bmp", type);
|
||||
else
|
||||
sprintf(filename, "%s.jpg", type); // TODO: perhaps we could use whatever is after image/
|
||||
}
|
||||
else
|
||||
sprintf(filename, "%s.jpg", type); // ehh, just guess
|
||||
}
|
||||
|
||||
int APEv2Metadata::MetadataEditor_SetArtwork(int field, unsigned int index, artwork_t *data, data_flags_t flags)
|
||||
{
|
||||
ReferenceCountedNXString mime_type;
|
||||
const void *bytes = 0;
|
||||
size_t length = 0;
|
||||
switch(field)
|
||||
{
|
||||
case MetadataKeys::ALBUM:
|
||||
if (data && NXDataGet(data->data, &bytes, &length) == NErr_Success)
|
||||
{
|
||||
char filename[256] = {0};
|
||||
NXDataGetMIME(data->data, &mime_type);
|
||||
APEv2_GetFilenameForMIME(filename, "cover", mime_type); /* TODO: perhaps use description, instead? */
|
||||
return NSAPEv2_Tag_SetArtwork(apev2_tag, "Cover Art (front)", index, filename, bytes, length);
|
||||
}
|
||||
else
|
||||
return NSAPEv2_Tag_SetArtwork(apev2_tag, "Cover Art (front)", index, 0, 0, 0);
|
||||
}
|
||||
return NErr_Unknown;
|
||||
}
|
29
Src/replicant/nswasabi/APEv2Metadata.h
Normal file
29
Src/replicant/nswasabi/APEv2Metadata.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "metadata/metadata.h"
|
||||
#include "nsapev2/nsapev2.h"
|
||||
|
||||
/* this class mimics ifc_metadata and ifc_metadata_editor, but doesn't inherit (because it's not given out directly) */
|
||||
class APEv2Metadata
|
||||
{
|
||||
public:
|
||||
APEv2Metadata();
|
||||
~APEv2Metadata();
|
||||
|
||||
static int Initialize(api_metadata *metadata_api);
|
||||
int Initialize(nsapev2_tag_t tag);
|
||||
|
||||
/* ifc_metadata implementation */
|
||||
int WASABICALL Metadata_GetField(int field, unsigned int index, nx_string_t *value);
|
||||
int WASABICALL Metadata_GetInteger(int field, unsigned int index, int64_t *value);
|
||||
int WASABICALL Metadata_GetReal(int field, unsigned int index, double *value);
|
||||
int WASABICALL Metadata_GetArtwork(int field, unsigned int index, artwork_t *artwork, data_flags_t flags);
|
||||
|
||||
/* ifc_metadata_editor implementation */
|
||||
int WASABICALL MetadataEditor_SetField(int field, unsigned int index, nx_string_t value);
|
||||
int WASABICALL MetadataEditor_SetInteger(int field, unsigned int index, int64_t value);
|
||||
int WASABICALL MetadataEditor_SetReal(int field, unsigned int index, double value);
|
||||
int WASABICALL MetadataEditor_SetArtwork(int field, unsigned int index, artwork_t *data, data_flags_t flags);
|
||||
private:
|
||||
nsapev2_tag_t apev2_tag;
|
||||
static api_metadata *metadata_api;
|
||||
};
|
12
Src/replicant/nswasabi/Android.mk
Normal file
12
Src/replicant/nswasabi/Android.mk
Normal file
@ -0,0 +1,12 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := nswasabi
|
||||
LOCAL_ARM_MODE := arm
|
||||
LOCAL_C_INCLUDES := $(ROOT_REPLICANT)
|
||||
LOCAL_CFLAGS := -fvisibility=hidden
|
||||
LOCAL_SRC_FILES := PlaybackBase.cpp XMLString.cpp ID3v2Metadata.cpp ID3v1Metadata.cpp APEv2Metadata.cpp ApplicationBase.cpp
|
||||
LOCAL_STATIC_LIBRARIES := nu
|
||||
LOCAL_EXPORT_LDLIBS := -llog
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
168
Src/replicant/nswasabi/ApplicationBase.cpp
Normal file
168
Src/replicant/nswasabi/ApplicationBase.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
#include "ApplicationBase.h"
|
||||
#include "foundation/error.h"
|
||||
#include "application/features.h"
|
||||
#include <stdio.h> // for sprintf
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
ApplicationBase::ApplicationBase()
|
||||
{
|
||||
data_path = 0;
|
||||
all_permissions_enabled = false;
|
||||
device_id = 0;
|
||||
}
|
||||
|
||||
ApplicationBase::~ApplicationBase()
|
||||
{
|
||||
NXURIRelease(data_path);
|
||||
data_path = 0;
|
||||
NXStringRelease(device_id);
|
||||
device_id = 0;
|
||||
}
|
||||
|
||||
int ApplicationBase::Initialize()
|
||||
{
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
/* and call this after doing your own shutdown */
|
||||
void ApplicationBase::Shutdown()
|
||||
{
|
||||
NXURIRelease(data_path);
|
||||
data_path = 0;
|
||||
}
|
||||
|
||||
void ApplicationBase::SetDataPath(nx_uri_t new_data_path)
|
||||
{
|
||||
nx_uri_t old_path = data_path;
|
||||
data_path = NXURIRetain(new_data_path);
|
||||
NXURIRelease(old_path);
|
||||
}
|
||||
|
||||
void ApplicationBase::SetPermission(GUID feature)
|
||||
{
|
||||
permissions.insert(feature);
|
||||
}
|
||||
|
||||
void ApplicationBase::RemovePermission(GUID permission)
|
||||
{
|
||||
permissions.erase(permission);
|
||||
}
|
||||
|
||||
void ApplicationBase::EnableAllPermissions()
|
||||
{
|
||||
all_permissions_enabled=true;
|
||||
}
|
||||
|
||||
void ApplicationBase::ClearPermissions()
|
||||
{
|
||||
permissions.clear();
|
||||
}
|
||||
|
||||
void ApplicationBase::NotifyPermissions(api_syscb *system_callbacks)
|
||||
{
|
||||
if (system_callbacks)
|
||||
system_callbacks->IssueCallback(Features::event_type, Features::permissions_changed);
|
||||
}
|
||||
|
||||
int ApplicationBase::Application_GetDataPath(nx_uri_t *path)
|
||||
{
|
||||
*path=NXURIRetain(data_path);
|
||||
if (data_path)
|
||||
return NErr_Success;
|
||||
else
|
||||
return NErr_Empty;
|
||||
}
|
||||
|
||||
int ApplicationBase::Application_GetPermission(GUID feature)
|
||||
{
|
||||
if (all_permissions_enabled)
|
||||
return NErr_True;
|
||||
else if (permissions.find(feature) == permissions.end())
|
||||
return NErr_False;
|
||||
else
|
||||
return NErr_True;
|
||||
}
|
||||
|
||||
int ApplicationBase::Application_GetFeature(GUID feature)
|
||||
{
|
||||
if (features.find(feature) == features.end())
|
||||
return NErr_False;
|
||||
else
|
||||
return NErr_True;
|
||||
}
|
||||
|
||||
void ApplicationBase::Application_SetFeature(GUID feature)
|
||||
{
|
||||
features.insert(feature);
|
||||
}
|
||||
|
||||
void ApplicationBase::SetDeviceID(nx_string_t device_id)
|
||||
{
|
||||
nx_string_t old = this->device_id;
|
||||
this->device_id = NXStringRetain(device_id);
|
||||
NXStringRelease(old);
|
||||
}
|
||||
|
||||
static void GUIDtoCString(const GUID &guid, char *target)
|
||||
{
|
||||
//{2E9CE2F8-E26D-4629-A3FF-5DF619136B2C}
|
||||
sprintf(target, "{%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x}",
|
||||
(int)guid.Data1, (int)guid.Data2, (int)guid.Data3,
|
||||
(int)guid.Data4[0], (int)guid.Data4[1],
|
||||
(int)guid.Data4[2], (int)guid.Data4[3],
|
||||
(int)guid.Data4[4], (int)guid.Data4[5],
|
||||
(int)guid.Data4[6], (int)guid.Data4[7] );
|
||||
|
||||
}
|
||||
|
||||
static const char *GetFeatureName(const GUID &guid)
|
||||
{
|
||||
if (guid == Features::aac_playback)
|
||||
return "AAC Playback";
|
||||
else if (guid == Features::gapless)
|
||||
return "Gapless Playback";
|
||||
else if (guid == Features::flac_playback)
|
||||
return "FLAC Playback";
|
||||
else if (guid == Features::gracenote_autotag)
|
||||
return "Gracenote Autotagger";
|
||||
else
|
||||
return 0; /* the lack of of return 0 by default here was why it was crashing */
|
||||
|
||||
}
|
||||
|
||||
void ApplicationBase::DumpPermissions()
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
char guid_string[64];
|
||||
FeatureList::iterator itr;
|
||||
for (itr=features.begin();itr!=features.end();itr++)
|
||||
{
|
||||
GUIDtoCString(*itr, guid_string);
|
||||
const char *feature_name = GetFeatureName(*itr);
|
||||
if (feature_name)
|
||||
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[Feature] %s (%s)", guid_string, feature_name);
|
||||
else
|
||||
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[Feature] %s", guid_string);
|
||||
}
|
||||
|
||||
for (itr=permissions.begin();itr!=permissions.end();itr++)
|
||||
{
|
||||
GUIDtoCString(*itr, guid_string);
|
||||
const char *feature_name = GetFeatureName(*itr);
|
||||
if (feature_name)
|
||||
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[Permission] %s (%s)", guid_string, feature_name);
|
||||
else
|
||||
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[Permission] %s", guid_string);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int ApplicationBase::Application_GetDeviceID(nx_string_t *value)
|
||||
{
|
||||
if (!device_id)
|
||||
return NErr_Empty;
|
||||
*value = NXStringRetain(device_id);
|
||||
return NErr_Success;
|
||||
}
|
44
Src/replicant/nswasabi/ApplicationBase.h
Normal file
44
Src/replicant/nswasabi/ApplicationBase.h
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
#include "application/api_application.h"
|
||||
#include <set>
|
||||
#include "syscb/api_syscb.h"
|
||||
|
||||
/* implements non-platform-specific methods of api_application.
|
||||
You can derive your Application implementation from this to ease your life */
|
||||
class ApplicationBase : public api_application
|
||||
{
|
||||
public:
|
||||
ApplicationBase();
|
||||
~ApplicationBase();
|
||||
|
||||
/* call this (and check the return value) before doing your own initialization */
|
||||
int Initialize();
|
||||
|
||||
/* and call this after doing your own shutdown */
|
||||
void Shutdown();
|
||||
|
||||
void SetDataPath(nx_uri_t data_path);
|
||||
void SetPermission(GUID feature);
|
||||
void RemovePermission(GUID permission);
|
||||
void SetDeviceID(nx_string_t device_id);
|
||||
void EnableAllPermissions();
|
||||
void ClearPermissions();
|
||||
void NotifyPermissions(api_syscb *system_callbacks); /* pass in the syscb API to avoid a dependency */
|
||||
void DumpPermissions(); /* dumps permissions list to the log file */
|
||||
protected:
|
||||
/* api_application implementation */
|
||||
int Application_GetDataPath(nx_uri_t *path);
|
||||
int Application_GetPermission(GUID feature);
|
||||
int Application_GetFeature(GUID feature);
|
||||
void Application_SetFeature(GUID feature);
|
||||
int Application_GetDeviceID(nx_string_t *value);
|
||||
|
||||
private:
|
||||
typedef std::set<GUID> FeatureList;
|
||||
FeatureList features;
|
||||
FeatureList permissions;
|
||||
bool all_permissions_enabled; /* bypass for developer/QA testing */
|
||||
nx_uri_t data_path;
|
||||
nx_string_t device_id;
|
||||
|
||||
};
|
184
Src/replicant/nswasabi/AutoCharNX.h
Normal file
184
Src/replicant/nswasabi/AutoCharNX.h
Normal file
@ -0,0 +1,184 @@
|
||||
#pragma once
|
||||
#include "../nx/nxstring.h"
|
||||
#include "../nx/nxuri.h"
|
||||
#include "../foundation/error.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
template <nx_charset_t charset>
|
||||
class AutoCharNX
|
||||
{
|
||||
public:
|
||||
AutoCharNX()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
AutoCharNX(size_t bytes)
|
||||
{
|
||||
Init();
|
||||
ptr = (char *)malloc(bytes);
|
||||
malloc_size = bytes;
|
||||
}
|
||||
|
||||
AutoCharNX(nx_string_t string)
|
||||
{
|
||||
Init();
|
||||
|
||||
Set(string);
|
||||
}
|
||||
|
||||
AutoCharNX(nx_uri_t filename)
|
||||
{
|
||||
Init();
|
||||
|
||||
Set(filename);
|
||||
}
|
||||
|
||||
~AutoCharNX()
|
||||
{
|
||||
if (owned)
|
||||
free(ptr);
|
||||
if (reference_string)
|
||||
NXStringRelease(reference_string);
|
||||
}
|
||||
|
||||
int Set(nx_string_t string)
|
||||
{
|
||||
if (reference_string == string)
|
||||
return NErr_Success;
|
||||
|
||||
if (reference_string)
|
||||
NXStringRelease(reference_string);
|
||||
reference_string=0;
|
||||
|
||||
size_t byte_count=0;
|
||||
int ret = NXStringGetBytesSize(&byte_count, string, charset, nx_string_get_bytes_size_null_terminate);
|
||||
if(ret == NErr_DirectPointer)
|
||||
{
|
||||
if (owned)
|
||||
{
|
||||
free(ptr);
|
||||
ptr=0;
|
||||
length=0;
|
||||
malloc_size=0;
|
||||
}
|
||||
ret = NXStringGetBytesDirect((const void **)&ptr, &length, string, charset, nx_string_get_bytes_size_null_terminate);
|
||||
reference_string = NXStringRetain(string);
|
||||
owned=false;
|
||||
}
|
||||
else if (ret == NErr_Success)
|
||||
{
|
||||
if (owned)
|
||||
{
|
||||
if (byte_count > malloc_size)
|
||||
{
|
||||
ptr = (char *)realloc(ptr, byte_count);
|
||||
malloc_size = byte_count;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not owned. need to allocate */
|
||||
ptr = (char *)malloc(byte_count);
|
||||
malloc_size = byte_count;
|
||||
owned=true;
|
||||
}
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
ret = NXStringGetBytes(&length, string, ptr, byte_count, charset, nx_string_get_bytes_size_null_terminate);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NErr_OutOfMemory;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Set(nx_uri_t filename)
|
||||
{
|
||||
int ret;
|
||||
nx_string_t string;
|
||||
ret = NXURIGetNXString(&string, filename);
|
||||
if (ret == NErr_Success)
|
||||
{
|
||||
ret = Set(string);
|
||||
NXStringRelease(string);
|
||||
}
|
||||
else
|
||||
{
|
||||
Clear();
|
||||
// failed! we need to clean up
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
operator const char *() const
|
||||
{
|
||||
if (length)
|
||||
return ptr;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this one will never return a NULL, always a valid string */
|
||||
const char *GetValidString() const
|
||||
{
|
||||
if (length)
|
||||
return ptr;
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
/* the Clear function clears the string but doesn't deallocate memory */
|
||||
void Clear()
|
||||
{
|
||||
if (!owned)
|
||||
ptr=0;
|
||||
length=0;
|
||||
|
||||
if (reference_string)
|
||||
NXStringRelease(reference_string);
|
||||
reference_string=0;
|
||||
}
|
||||
|
||||
size_t size()
|
||||
{
|
||||
if (length)
|
||||
return length-1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
private:
|
||||
void Init()
|
||||
{
|
||||
ptr=0;
|
||||
length=0;
|
||||
owned=false;
|
||||
reference_string=0;
|
||||
malloc_size=0;
|
||||
}
|
||||
char *ptr;
|
||||
size_t length;
|
||||
size_t malloc_size;
|
||||
bool owned;
|
||||
nx_string_t reference_string;
|
||||
};
|
||||
|
||||
typedef AutoCharNX<nx_charset_utf8> AutoCharUTF8;
|
||||
#define AutoCharPrintfUTF8(x) (AutoCharUTF8(x).GetValidString())
|
||||
class AutoCharNative
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
class AutoFilename
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
145
Src/replicant/nswasabi/ComponentManagerBase.cpp
Normal file
145
Src/replicant/nswasabi/ComponentManagerBase.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
#include "ComponentManagerBase.h"
|
||||
#include "foundation/error.h"
|
||||
#include "nx/nxuri.h"
|
||||
|
||||
ComponentManagerBase::ComponentManagerBase()
|
||||
{
|
||||
phase=PHASE_INITIALIZE;
|
||||
service_api=0;
|
||||
component_sync=0;
|
||||
}
|
||||
|
||||
int ComponentManagerBase::LateLoad(ifc_component *component)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (phase >= PHASE_REGISTERED)
|
||||
{
|
||||
ret = component->RegisterServices(service_api);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
int ret2 = component->Quit(service_api);
|
||||
if (ret2 == NErr_TryAgain)
|
||||
{
|
||||
component_sync->Wait(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (phase >= PHASE_LOADING)
|
||||
{
|
||||
ret = component->OnLoading(service_api);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
int ret2 = component->Quit(service_api);
|
||||
if (ret2 == NErr_TryAgain)
|
||||
{
|
||||
component_sync->Wait(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (phase >= PHASE_LOADED)
|
||||
{
|
||||
ret = component->OnLoaded(service_api);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
int ret2 = component->Quit(service_api);
|
||||
if (ret2 == NErr_TryAgain)
|
||||
{
|
||||
component_sync->Wait(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
void ComponentManagerBase::SetServiceAPI(api_service *service_api)
|
||||
{
|
||||
this->service_api = service_api;
|
||||
service_api->QueryInterface(&component_sync);
|
||||
}
|
||||
|
||||
int ComponentManagerBase::Load()
|
||||
{
|
||||
if (phase != PHASE_INITIALIZE)
|
||||
return NErr_Error;
|
||||
|
||||
int ret;
|
||||
|
||||
/* RegisterServices phase */
|
||||
for (ComponentList::iterator itr=components.begin();itr!=components.end();)
|
||||
{
|
||||
ifc_component *component = *itr;
|
||||
ComponentList::iterator next=itr;
|
||||
next++;
|
||||
ret = component->RegisterServices(service_api);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
int ret2 = component->Quit(service_api);
|
||||
if (ret2 == NErr_TryAgain)
|
||||
{
|
||||
component_sync->Wait(1);
|
||||
}
|
||||
NXURIRelease(component->component_info.filename);
|
||||
CloseComponent(component);
|
||||
components.erase(component);
|
||||
|
||||
}
|
||||
itr=next;
|
||||
}
|
||||
|
||||
phase = PHASE_REGISTERED;
|
||||
|
||||
/* OnLoading phase */
|
||||
for (ComponentList::iterator itr=components.begin();itr!=components.end();)
|
||||
{
|
||||
ifc_component *component = *itr;
|
||||
ComponentList::iterator next=itr;
|
||||
next++;
|
||||
ret = component->OnLoading(service_api);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
int ret2 = component->Quit(service_api);
|
||||
if (ret2 == NErr_TryAgain)
|
||||
{
|
||||
component_sync->Wait(1);
|
||||
}
|
||||
NXURIRelease(component->component_info.filename);
|
||||
CloseComponent(component);
|
||||
components.erase(component);
|
||||
|
||||
}
|
||||
itr=next;
|
||||
}
|
||||
|
||||
phase = PHASE_LOADING;
|
||||
|
||||
/* OnLoaded phase */
|
||||
for (ComponentList::iterator itr=components.begin();itr!=components.end();)
|
||||
{
|
||||
ifc_component *component = *itr;
|
||||
ComponentList::iterator next=itr;
|
||||
next++;
|
||||
ret = component->OnLoading(service_api);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
int ret2 = component->Quit(service_api);
|
||||
if (ret2 == NErr_TryAgain)
|
||||
{
|
||||
component_sync->Wait(1);
|
||||
}
|
||||
NXURIRelease(component->component_info.filename);
|
||||
CloseComponent(component);
|
||||
components.erase(component);
|
||||
}
|
||||
itr=next;
|
||||
}
|
||||
|
||||
phase = PHASE_LOADED;
|
||||
|
||||
return NErr_Success;
|
||||
}
|
31
Src/replicant/nswasabi/ComponentManagerBase.h
Normal file
31
Src/replicant/nswasabi/ComponentManagerBase.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "nx/nxuri.h"
|
||||
#include "service/api_service.h"
|
||||
#include "component/ifc_component.h"
|
||||
#include "nu/PtrDeque.h"
|
||||
#include "component/ifc_component_sync.h"
|
||||
|
||||
class ComponentManagerBase
|
||||
{
|
||||
public:
|
||||
void SetServiceAPI(api_service *service_api);
|
||||
int Load();
|
||||
protected:
|
||||
ComponentManagerBase();
|
||||
int LateLoad(ifc_component *mod);
|
||||
enum Phase
|
||||
{
|
||||
PHASE_INITIALIZE=0, /* components are still being added */
|
||||
PHASE_REGISTERED=1, /* RegisterServices() has been called on all components */
|
||||
PHASE_LOADING=2, /* OnLoading() has been called on all components */
|
||||
PHASE_LOADED=3, /* OnLoaded() has been called on all components */
|
||||
};
|
||||
Phase phase;
|
||||
typedef nu::PtrDeque<ifc_component> ComponentList;
|
||||
ComponentList components;
|
||||
api_service *service_api;
|
||||
ifc_component_sync *component_sync;
|
||||
private:
|
||||
/* your implementation needs to override this. You should call FreeLibrary(component->component_info.hModule); or dlclose(component->component_info.dl_handle); or similar */
|
||||
virtual void CloseComponent(ifc_component *component)=0;
|
||||
};
|
187
Src/replicant/nswasabi/ID3v1Metadata.cpp
Normal file
187
Src/replicant/nswasabi/ID3v1Metadata.cpp
Normal file
@ -0,0 +1,187 @@
|
||||
#include "ID3v1Metadata.h"
|
||||
#include "metadata/MetadataKeys.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
api_metadata *ID3v1Metadata::metadata_api=0;
|
||||
|
||||
ID3v1Metadata::ID3v1Metadata()
|
||||
{
|
||||
id3v1_tag=0;
|
||||
}
|
||||
|
||||
ID3v1Metadata::~ID3v1Metadata()
|
||||
{
|
||||
}
|
||||
|
||||
int ID3v1Metadata::Initialize(api_metadata *metadata_api)
|
||||
{
|
||||
ID3v1Metadata::metadata_api = metadata_api;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int ID3v1Metadata::Initialize(nsid3v1_tag_t tag)
|
||||
{
|
||||
id3v1_tag = tag;
|
||||
this->metadata_api = metadata_api;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
/* ifc_metadata implementation */
|
||||
int ID3v1Metadata::Metadata_GetField(int field, unsigned int index, nx_string_t *value)
|
||||
{
|
||||
if (!id3v1_tag)
|
||||
return NErr_Unknown;
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case MetadataKeys::TITLE:
|
||||
return index?NErr_EndOfEnumeration:NSID3v1_Get_Title(id3v1_tag, value);
|
||||
case MetadataKeys::ARTIST:
|
||||
return index?NErr_EndOfEnumeration:NSID3v1_Get_Artist(id3v1_tag, value);
|
||||
case MetadataKeys::ALBUM:
|
||||
return index?NErr_EndOfEnumeration:NSID3v1_Get_Album(id3v1_tag, value);
|
||||
case MetadataKeys::YEAR:
|
||||
return index?NErr_EndOfEnumeration:NSID3v1_Get_Year(id3v1_tag, value);
|
||||
case MetadataKeys::COMMENT:
|
||||
return index?NErr_EndOfEnumeration:NSID3v1_Get_Comment(id3v1_tag, value);
|
||||
case MetadataKeys::TRACK:
|
||||
return index?NErr_EndOfEnumeration:NSID3v1_Get_Track(id3v1_tag, value);
|
||||
case MetadataKeys::GENRE:
|
||||
{
|
||||
if (!metadata_api)
|
||||
return NErr_Unknown;
|
||||
if (index > 0)
|
||||
return NErr_EndOfEnumeration;
|
||||
|
||||
uint8_t genre_id;
|
||||
int ret = NSID3v1_Int_Get_Genre(id3v1_tag, &genre_id);
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
|
||||
nx_string_t genre;
|
||||
ret = metadata_api->GetGenre(genre_id, &genre);
|
||||
if (ret == NErr_Success)
|
||||
{
|
||||
*value = NXStringRetain(genre);
|
||||
return NErr_Success;
|
||||
}
|
||||
else if (ret == NErr_Unknown)
|
||||
{
|
||||
return NErr_Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
int ID3v1Metadata::Metadata_GetInteger(int field, unsigned int index, int64_t *value)
|
||||
{
|
||||
if (!id3v1_tag)
|
||||
return NErr_Unknown;
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case MetadataKeys::YEAR:
|
||||
{
|
||||
if (index > 0)
|
||||
return NErr_EndOfEnumeration;
|
||||
unsigned int year;
|
||||
int ret = NSID3v1_Int_Get_Year(id3v1_tag, &year);
|
||||
if (ret == NErr_Success)
|
||||
*value = (int64_t)year;
|
||||
return ret;
|
||||
}
|
||||
case MetadataKeys::TRACK:
|
||||
{
|
||||
if (index > 0)
|
||||
return NErr_EndOfEnumeration;
|
||||
uint8_t track;
|
||||
int ret = NSID3v1_Int_Get_Track(id3v1_tag, &track);
|
||||
if (ret == NErr_Success)
|
||||
*value = (int64_t)track;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
int ID3v1Metadata::Metadata_GetReal(int field, unsigned int index, double *value)
|
||||
{
|
||||
if (!id3v1_tag)
|
||||
return NErr_Unknown;
|
||||
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
int ID3v1Metadata::MetadataEditor_SetField(int field, unsigned int index, nx_string_t value)
|
||||
{
|
||||
if (!id3v1_tag)
|
||||
return NErr_NullPointer;
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case MetadataKeys::TITLE:
|
||||
return index?NErr_EndOfEnumeration:NSID3v1_Set_Title(id3v1_tag, value);
|
||||
case MetadataKeys::ARTIST:
|
||||
return index?NErr_EndOfEnumeration:NSID3v1_Set_Artist(id3v1_tag, value);
|
||||
case MetadataKeys::ALBUM:
|
||||
return index?NErr_EndOfEnumeration:NSID3v1_Set_Album(id3v1_tag, value);
|
||||
case MetadataKeys::YEAR:
|
||||
return index?NErr_EndOfEnumeration:NSID3v1_Set_Year(id3v1_tag, value);
|
||||
case MetadataKeys::COMMENT:
|
||||
return index?NErr_EndOfEnumeration:NSID3v1_Set_Comment(id3v1_tag, value);
|
||||
case MetadataKeys::TRACK:
|
||||
return index?NErr_EndOfEnumeration:NSID3v1_Set_Track(id3v1_tag, value);
|
||||
|
||||
case MetadataKeys::GENRE:
|
||||
{
|
||||
if (!metadata_api)
|
||||
return NErr_Unknown;
|
||||
if (index > 0)
|
||||
return NErr_EndOfEnumeration;
|
||||
|
||||
uint8_t genre_id;
|
||||
int ret = metadata_api->GetGenreID(value, &genre_id);
|
||||
if (ret == NErr_Success)
|
||||
return NSID3v1_Int_Set_Genre(id3v1_tag, genre_id);
|
||||
else
|
||||
return NSID3v1_Int_Set_Genre(id3v1_tag, 0xFF);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
int ID3v1Metadata::MetadataEditor_SetInteger(int field, unsigned int index, int64_t value)
|
||||
{
|
||||
if (!id3v1_tag)
|
||||
return NErr_NullPointer;
|
||||
|
||||
if (index != 0)
|
||||
return NErr_EndOfEnumeration;
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case MetadataKeys::YEAR:
|
||||
return NSID3v1_Int_Set_Year(id3v1_tag, (unsigned int)value);
|
||||
case MetadataKeys::TRACK:
|
||||
if (value < 0 || value > 255)
|
||||
return NErr_ParameterOutOfRange;
|
||||
return NSID3v1_Int_Set_Track(id3v1_tag, (uint8_t)value);
|
||||
case MetadataKeys::GENRE:
|
||||
if (value < 0 || value > 255)
|
||||
return NErr_ParameterOutOfRange;
|
||||
return NSID3v1_Int_Set_Genre(id3v1_tag, (uint8_t)value);
|
||||
}
|
||||
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
#undef DESCRIPTION
|
26
Src/replicant/nswasabi/ID3v1Metadata.h
Normal file
26
Src/replicant/nswasabi/ID3v1Metadata.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "metadata/metadata.h"
|
||||
#include "nsid3v1/nsid3v1.h"
|
||||
|
||||
/* this class mimics ifc_metadata and ifc_metadata_editor, but doesn't inherit (because it's not given out directly) */
|
||||
class ID3v1Metadata
|
||||
{
|
||||
public:
|
||||
ID3v1Metadata();
|
||||
~ID3v1Metadata();
|
||||
|
||||
static int Initialize(api_metadata *metadata_api);
|
||||
int Initialize(nsid3v1_tag_t tag);
|
||||
|
||||
/* ifc_metadata implementation */
|
||||
int WASABICALL Metadata_GetField(int field, unsigned int index, nx_string_t *value);
|
||||
int WASABICALL Metadata_GetInteger(int field, unsigned int index, int64_t *value);
|
||||
int WASABICALL Metadata_GetReal(int field, unsigned int index, double *value);
|
||||
|
||||
/* ifc_metadata_editor implementation */
|
||||
int WASABICALL MetadataEditor_SetField(int field, unsigned int index, nx_string_t value);
|
||||
int WASABICALL MetadataEditor_SetInteger(int field, unsigned int index, int64_t value);
|
||||
private:
|
||||
nsid3v1_tag_t id3v1_tag;
|
||||
static api_metadata *metadata_api;
|
||||
};
|
1087
Src/replicant/nswasabi/ID3v2Metadata.cpp
Normal file
1087
Src/replicant/nswasabi/ID3v2Metadata.cpp
Normal file
File diff suppressed because it is too large
Load Diff
34
Src/replicant/nswasabi/ID3v2Metadata.h
Normal file
34
Src/replicant/nswasabi/ID3v2Metadata.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "metadata/metadata.h"
|
||||
#include "nsid3v2/nsid3v2.h"
|
||||
|
||||
/* this class mimics ifc_metadata and ifc_metadata_editor, but doesn't inherit (because it's not given out directly) */
|
||||
class ID3v2Metadata
|
||||
{
|
||||
public:
|
||||
ID3v2Metadata();
|
||||
~ID3v2Metadata();
|
||||
|
||||
static int Initialize(api_metadata *metadata_api);
|
||||
int Initialize(nsid3v2_tag_t tag);
|
||||
|
||||
/* ifc_metadata implementation */
|
||||
int WASABICALL Metadata_GetField(int field, unsigned int index, nx_string_t *value);
|
||||
int WASABICALL Metadata_GetInteger(int field, unsigned int index, int64_t *value);
|
||||
int WASABICALL Metadata_GetReal(int field, unsigned int index, double *value);
|
||||
int WASABICALL Metadata_GetArtwork(int field, unsigned int index, artwork_t *artwork, data_flags_t flags);
|
||||
|
||||
/* ifc_metadata_editor implementation */
|
||||
int WASABICALL MetadataEditor_SetField(int field, unsigned int index, nx_string_t value);
|
||||
int WASABICALL MetadataEditor_SetArtwork(int field, unsigned int index, artwork_t *data, data_flags_t flags);
|
||||
private:
|
||||
nsid3v2_tag_t id3v2_tag;
|
||||
|
||||
int GetGenre(int index, nx_string_t *value);
|
||||
|
||||
static api_metadata *metadata_api;
|
||||
|
||||
#ifdef __APPLE__
|
||||
CFNumberFormatterRef number_formatter;
|
||||
#endif
|
||||
};
|
48
Src/replicant/nswasabi/Makefile
Normal file
48
Src/replicant/nswasabi/Makefile
Normal file
@ -0,0 +1,48 @@
|
||||
MODULE_NAME := nswasabi
|
||||
|
||||
CPPSOURCES := ComponentManagerBase.cpp ApplicationBase.cpp ID3v2Metadata.cpp ID3v1Metadata.cpp PlaybackBase.cpp APEv2Metadata.cpp
|
||||
#CSOURCES := utf.c ByteReader.c ByteWriter.c
|
||||
|
||||
LIBRARY_FILENAME := lib$(MODULE_NAME).a
|
||||
OUTPUT_PATH := ../build/$(MODULE_NAME)
|
||||
ARCHIVE_PATH := ../build/lib
|
||||
LIBRARY_FILEPATH := ../build/lib/$(LIBRARY_FILENAME)
|
||||
|
||||
CPPOBJS := $(patsubst %.cpp,$(OUTPUT_PATH)/%.o,$(CPPSOURCES))
|
||||
CPPDEPS := $(patsubst %.o,$(OUTPUT_PATH)/%.d,$(CPPOBJS))
|
||||
COBJS := $(patsubst %.c,$(OUTPUT_PATH)/%.o,$(CSOURCES))
|
||||
CDEPS := $(patsubst %.o,$(OUTPUT_PATH)/%.d,$(COBJS))
|
||||
|
||||
OBJS := $(CPPOBJS) $(COBJS)
|
||||
DEPS := $(CPPDEPS) $(CDEPS)
|
||||
|
||||
CFLAGS=-I.. -fPIC #-fvisibility=hidden
|
||||
CPPFLAGS := ${CFLAGS}
|
||||
|
||||
|
||||
|
||||
build: build-dir $(LIBRARY_FILEPATH)
|
||||
|
||||
build-dir:
|
||||
@mkdir -p $(OUTPUT_PATH)/linux > /dev/null 2> /dev/null
|
||||
@mkdir -p $(OUTPUT_PATH) > /dev/null 2> /dev/null
|
||||
@mkdir -p $(ARCHIVE_PATH) > /dev/null 2> /dev/null
|
||||
|
||||
dep:
|
||||
@rm ${DEPS}
|
||||
|
||||
$(OUTPUT_PATH)/%.o: %.cpp
|
||||
#@echo Compiling $*.cpp
|
||||
@$(CXX) $(CPPFLAGS) -MMD -MF $(OUTPUT_PATH)/$*.d -MT $(OUTPUT_PATH)/$*.o -c $*.cpp -o $(OUTPUT_PATH)/$*.o
|
||||
|
||||
$(OUTPUT_PATH)/%.o: %.c
|
||||
#@echo Compiling $*.c
|
||||
@$(CC) $(CFLAGS) -MMD -MF $(OUTPUT_PATH)/$*.d -MT $(OUTPUT_PATH)/$*.o -c $*.c -o $(OUTPUT_PATH)/$*.o
|
||||
|
||||
$(LIBRARY_FILEPATH): ${OBJS}
|
||||
@$(AR) rcs $@ ${OBJS}
|
||||
|
||||
clean:
|
||||
-rm -f ${OBJS} $(LIBRARY_FILENAME) ${DEPS}
|
||||
|
||||
-include $(DEPS)
|
97
Src/replicant/nswasabi/MetadataChain.h
Normal file
97
Src/replicant/nswasabi/MetadataChain.h
Normal file
@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
#include "metadata/ifc_metadata.h"
|
||||
|
||||
|
||||
template <class metadata_t>
|
||||
class MetadataChain : public metadata_t
|
||||
{
|
||||
public:
|
||||
MetadataChain()
|
||||
{
|
||||
parent_metadata=0;
|
||||
}
|
||||
|
||||
~MetadataChain()
|
||||
{
|
||||
if (parent_metadata)
|
||||
parent_metadata->Release();
|
||||
}
|
||||
|
||||
static bool Unhandled(ns_error_t ret)
|
||||
{
|
||||
return (ret == NErr_NotImplemented || ret == NErr_Empty || ret == NErr_Unknown);
|
||||
}
|
||||
|
||||
ns_error_t SetParentMetadata(ifc_metadata *new_parent_metadata)
|
||||
{
|
||||
if (parent_metadata)
|
||||
parent_metadata->Release();
|
||||
parent_metadata=new_parent_metadata;
|
||||
if (parent_metadata)
|
||||
parent_metadata->Retain();
|
||||
return NErr_Success;
|
||||
}
|
||||
protected:
|
||||
ifc_metadata *parent_metadata;
|
||||
private:
|
||||
ns_error_t WASABICALL Metadata_GetField(int field, unsigned int index, nx_string_t *value)
|
||||
{
|
||||
ns_error_t ret = metadata_t::Metadata_GetField(field, index, value);
|
||||
if (Unhandled(ret) && parent_metadata)
|
||||
return parent_metadata->GetField(field, index, value);
|
||||
else
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
ns_error_t WASABICALL Metadata_GetInteger(int field, unsigned int index, int64_t *value)
|
||||
{
|
||||
ns_error_t ret = metadata_t::Metadata_GetInteger(field, index, value);
|
||||
if (Unhandled(ret) && parent_metadata)
|
||||
return parent_metadata->GetInteger(field, index, value);
|
||||
else
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
ns_error_t WASABICALL Metadata_GetReal(int field, unsigned int index, double *value)
|
||||
{
|
||||
ns_error_t ret = metadata_t::Metadata_GetReal(field, index, value);
|
||||
if (Unhandled(ret) && parent_metadata)
|
||||
return parent_metadata->GetReal(field, index, value);
|
||||
else
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
ns_error_t WASABICALL Metadata_GetArtwork(int field, unsigned int index, artwork_t *artwork, data_flags_t flags)
|
||||
{
|
||||
ns_error_t ret = metadata_t::Metadata_GetArtwork(field, index, artwork, flags);
|
||||
if (Unhandled(ret) && parent_metadata)
|
||||
return parent_metadata->GetArtwork(field, index, artwork, flags);
|
||||
else
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
ns_error_t WASABICALL Metadata_GetBinary(int field, unsigned int index, nx_data_t *data)
|
||||
{
|
||||
ns_error_t ret = metadata_t::Metadata_GetBinary(field, index, data);
|
||||
if (Unhandled(ret) && parent_metadata)
|
||||
return parent_metadata->GetBinary(field, index, data);
|
||||
else
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
ns_error_t WASABICALL Metadata_GetMetadata(int field, unsigned int index, ifc_metadata **metadata)
|
||||
{
|
||||
ns_error_t ret = metadata_t::Metadata_GetMetadata(field, index, metadata);
|
||||
if (Unhandled(ret) && parent_metadata)
|
||||
return parent_metadata->GetMetadata(field, index, metadata);
|
||||
else
|
||||
return ret;
|
||||
|
||||
}
|
||||
// TODO: ns_error_t WASABICALL Metadata_Serialize(nx_data_t *data) { return NErr_NotImplemented; }
|
||||
};
|
100
Src/replicant/nswasabi/MetadataEditorChain.h
Normal file
100
Src/replicant/nswasabi/MetadataEditorChain.h
Normal file
@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
#include "metadata/ifc_metadata_editor.h"
|
||||
|
||||
|
||||
template <class metadata_t>
|
||||
class MetadataEditorChain : public metadata_t
|
||||
{
|
||||
public:
|
||||
MetadataEditorChain()
|
||||
{
|
||||
parent_metadata=0;
|
||||
}
|
||||
|
||||
~MetadataEditorChain()
|
||||
{
|
||||
if (parent_metadata)
|
||||
parent_metadata->Release();
|
||||
}
|
||||
|
||||
static bool Unhandled(ns_error_t ret)
|
||||
{
|
||||
return (ret == NErr_NotImplemented || ret == NErr_Empty || ret == NErr_Unknown);
|
||||
}
|
||||
|
||||
ns_error_t SetParentMetadata(ifc_metadata_editor *new_parent_metadata)
|
||||
{
|
||||
if (parent_metadata)
|
||||
parent_metadata->Release();
|
||||
parent_metadata=new_parent_metadata;
|
||||
if (parent_metadata)
|
||||
parent_metadata->Retain();
|
||||
return NErr_Success;
|
||||
}
|
||||
protected:
|
||||
ifc_metadata_editor *parent_metadata;
|
||||
private:
|
||||
int WASABICALL MetadataEditor_Save()
|
||||
{
|
||||
if (parent_metadata)
|
||||
return parent_metadata->Save();
|
||||
else
|
||||
return NErr_NotImplemented;
|
||||
}
|
||||
|
||||
int WASABICALL MetadataEditor_SetField(int field, unsigned int index, nx_string_t value)
|
||||
{
|
||||
bool known=false;
|
||||
if (parent_metadata && parent_metadata->SetField(field, index, value) == NErr_Success)
|
||||
known=true;
|
||||
if (metadata_t::MetadataEditor_SetField(field, index, value) == NErr_Success)
|
||||
known=true;
|
||||
|
||||
if (known)
|
||||
return NErr_Success;
|
||||
else
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
int WASABICALL MetadataEditor_SetInteger(int field, unsigned int index, int64_t value)
|
||||
{
|
||||
bool known=false;
|
||||
if (parent_metadata && parent_metadata->SetInteger(field, index, value) == NErr_Success)
|
||||
known=true;
|
||||
if (metadata_t::MetadataEditor_SetInteger(field, index, value) == NErr_Success)
|
||||
known=true;
|
||||
|
||||
if (known)
|
||||
return NErr_Success;
|
||||
else
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
int WASABICALL MetadataEditor_SetReal(int field, unsigned int index, double value)
|
||||
{
|
||||
bool known=false;
|
||||
if (parent_metadata && parent_metadata->SetReal(field, index, value) == NErr_Success)
|
||||
known=true;
|
||||
if (metadata_t::MetadataEditor_SetReal(field, index, value) == NErr_Success)
|
||||
known=true;
|
||||
|
||||
if (known)
|
||||
return NErr_Success;
|
||||
else
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
int WASABICALL MetadataEditor_SetArtwork(int field, unsigned int index, artwork_t *data, data_flags_t flags)
|
||||
{
|
||||
bool known=false;
|
||||
if (parent_metadata && parent_metadata->SetArtwork(field, index, data, flags) == NErr_Success)
|
||||
known=true;
|
||||
if (metadata_t::MetadataEditor_SetArtwork(field, index, data, flags) == NErr_Success)
|
||||
known=true;
|
||||
|
||||
if (known)
|
||||
return NErr_Success;
|
||||
else
|
||||
return NErr_Unknown;
|
||||
}
|
||||
};
|
57
Src/replicant/nswasabi/ObjectFactory.h
Normal file
57
Src/replicant/nswasabi/ObjectFactory.h
Normal file
@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include "service/ifc_servicefactory.h"
|
||||
#include "ReferenceCounted.h"
|
||||
/*
|
||||
====== Usage ======
|
||||
disp_t: your Dispatchable base class
|
||||
implt_t: your implementation class
|
||||
|
||||
ObjectFactory<disp_t, impl_t> myFactory;
|
||||
impl_t myImplementation;
|
||||
|
||||
//....
|
||||
|
||||
//during service registration
|
||||
myFactory.Register(WASABI2_API_SVC);
|
||||
|
||||
//during service deregistration
|
||||
myFactory.Deregister(WASABI2_API_SVC);
|
||||
|
||||
==== Class requirements ====
|
||||
your base or implementation class requires the following three static methods
|
||||
static FOURCC getServiceType(); // return your type (e.g. WaSvc::OBJECT)... might already be defined in the dispatchable base class
|
||||
static const char *getServiceName(); // return your service name
|
||||
static GUID getServiceGuid(); // return your service GUID
|
||||
*/
|
||||
|
||||
template <class impl_t, class disp_t>
|
||||
class CountableObjectFactory : public ifc_serviceFactory
|
||||
{
|
||||
public:
|
||||
CountableObjectFactory()
|
||||
{
|
||||
}
|
||||
|
||||
~CountableObjectFactory()
|
||||
{
|
||||
}
|
||||
|
||||
void Register(api_service *serviceManager)
|
||||
{
|
||||
serviceManager->Register(this);
|
||||
}
|
||||
|
||||
void Deregister(api_service *serviceManager)
|
||||
{
|
||||
serviceManager->Unregister(this);
|
||||
}
|
||||
|
||||
private:
|
||||
GUID WASABICALL ServiceFactory_GetServiceType() { return impl_t::GetServiceType(); }
|
||||
nx_string_t WASABICALL ServiceFactory_GetServiceName() { return impl_t::GetServiceName(); }
|
||||
GUID WASABICALL ServiceFactory_GetGUID() { return impl_t::GetServiceGUID(); } // GUID per service factory, can be INVALID_GUID
|
||||
void *WASABICALL ServiceFactory_GetInterface() { return static_cast<disp_t *>(new ReferenceCounted<impl_t>); }
|
||||
int WASABICALL ServiceFactory_ServiceNotify(int msg, intptr_t param1 = 0, intptr_t param2 = 0) { return 0; }
|
||||
};
|
||||
|
409
Src/replicant/nswasabi/PlaybackBase.cpp
Normal file
409
Src/replicant/nswasabi/PlaybackBase.cpp
Normal file
@ -0,0 +1,409 @@
|
||||
#include "PlaybackBase.h"
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h> // TODO: replace with generic logging API
|
||||
|
||||
#else
|
||||
#define ANDROID_LOG_INFO 0
|
||||
#define ANDROID_LOG_ERROR 1
|
||||
static void __android_log_print(int, const char *, const char *, ...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
PlaybackBase::PlaybackBase()
|
||||
{
|
||||
wake_flags=0;
|
||||
last_wake_flags=0;
|
||||
playback_thread=0;
|
||||
secondary_parameters=0;
|
||||
filename=0;
|
||||
player=0;
|
||||
queued_seek=0;
|
||||
output_service=0;
|
||||
}
|
||||
|
||||
int PlaybackBase::Initialize(nx_uri_t filename, ifc_player *player)
|
||||
{
|
||||
this->player = player;
|
||||
this->filename = NXURIRetain(filename);
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
PlaybackBase::~PlaybackBase()
|
||||
{
|
||||
if (secondary_parameters)
|
||||
secondary_parameters->Release();
|
||||
if (filename)
|
||||
NXURIRelease(filename);
|
||||
if (queued_seek)
|
||||
free(queued_seek);
|
||||
if (playback_thread)
|
||||
NXThreadJoin(playback_thread, 0);
|
||||
}
|
||||
|
||||
int PlaybackBase::Playback_Play(svc_output *output, ifc_playback_parameters *secondary_parameters)
|
||||
{
|
||||
if (!playback_thread)
|
||||
return 1;
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Play");
|
||||
|
||||
output_service = output;
|
||||
threadloop_node_t *apc = thread_loop.GetAPC();
|
||||
if (apc)
|
||||
{
|
||||
this->secondary_parameters = secondary_parameters;
|
||||
if (secondary_parameters)
|
||||
secondary_parameters->Retain();
|
||||
|
||||
apc->func = APC_Play;
|
||||
apc->param1 = this;
|
||||
thread_loop.Schedule(apc);
|
||||
return NErr_Success;
|
||||
}
|
||||
else
|
||||
return NErr_OutOfMemory;
|
||||
}
|
||||
|
||||
int PlaybackBase::Playback_SeekSeconds(double seconds)
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Seek (%f seconds)", seconds);
|
||||
Agave_Seek *seek = (Agave_Seek *)malloc(sizeof(Agave_Seek));
|
||||
if (seek)
|
||||
{
|
||||
seek->position_type = AGAVE_PLAYPOSITION_SECONDS;
|
||||
seek->position.seconds = seconds;
|
||||
threadloop_node_t *apc = thread_loop.GetAPC();
|
||||
if (apc)
|
||||
{
|
||||
apc->func = APC_Seek;
|
||||
apc->param1 = this;
|
||||
apc->param2 = seek;
|
||||
thread_loop.Schedule(apc);
|
||||
return NErr_Success;
|
||||
}
|
||||
}
|
||||
free(seek);
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
}
|
||||
|
||||
int PlaybackBase::Playback_Pause()
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Pause");
|
||||
threadloop_node_t *apc = thread_loop.GetAPC();
|
||||
if (apc)
|
||||
{
|
||||
apc->func = APC_Pause;
|
||||
apc->param1 = this;
|
||||
thread_loop.Schedule(apc);
|
||||
return NErr_Success;
|
||||
}
|
||||
else
|
||||
return NErr_OutOfMemory;
|
||||
}
|
||||
|
||||
int PlaybackBase::Playback_Unpause()
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Unpause");
|
||||
threadloop_node_t *apc = thread_loop.GetAPC();
|
||||
if (apc)
|
||||
{
|
||||
apc->func = APC_Unpause;
|
||||
apc->param1 = this;
|
||||
thread_loop.Schedule(apc);
|
||||
return NErr_Success;
|
||||
}
|
||||
else
|
||||
return NErr_OutOfMemory;
|
||||
}
|
||||
|
||||
int PlaybackBase::Playback_Stop()
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Stop");
|
||||
threadloop_node_t *apc = thread_loop.GetAPC();
|
||||
if (apc)
|
||||
{
|
||||
apc->func = APC_Stop;
|
||||
apc->param1 = this;
|
||||
thread_loop.Schedule(apc);
|
||||
return NErr_Success;
|
||||
}
|
||||
else
|
||||
return NErr_OutOfMemory;
|
||||
}
|
||||
|
||||
int PlaybackBase::Playback_Close()
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Close");
|
||||
threadloop_node_t *apc = thread_loop.GetAPC();
|
||||
if (apc)
|
||||
{
|
||||
apc->func = APC_Close;
|
||||
apc->param1 = this;
|
||||
thread_loop.Schedule(apc);
|
||||
return NErr_Success;
|
||||
}
|
||||
else
|
||||
return NErr_OutOfMemory;
|
||||
}
|
||||
|
||||
|
||||
int PlaybackBase::FileLockCallback_Interrupt()
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Interrupt");
|
||||
threadloop_node_t *apc = thread_loop.GetAPC();
|
||||
if (apc)
|
||||
{
|
||||
apc->func = APC_Interrupt;
|
||||
apc->param1 = this;
|
||||
thread_loop.Schedule(apc);
|
||||
return NErr_Success;
|
||||
}
|
||||
else
|
||||
return NErr_OutOfMemory;
|
||||
}
|
||||
|
||||
void PlaybackBase::ToggleFlags(int wake_reason)
|
||||
{
|
||||
switch(wake_reason)
|
||||
{
|
||||
case WAKE_KILL:
|
||||
last_wake_flags ^= WAKE_KILL; /* toggle kill flag */
|
||||
break;
|
||||
case WAKE_STOP:
|
||||
last_wake_flags ^= WAKE_STOP; /* toggle stop flag */
|
||||
break;
|
||||
case WAKE_PLAY:
|
||||
last_wake_flags ^= WAKE_PLAY; /* toggle play flag */
|
||||
break;
|
||||
case WAKE_PAUSE:
|
||||
case WAKE_UNPAUSE:
|
||||
last_wake_flags ^= WAKE_PAUSE; /* toggle pause flag */
|
||||
break;
|
||||
case WAKE_INTERRUPT:
|
||||
last_wake_flags ^= WAKE_INTERRUPT; /* toggle interrupt flag */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int PlaybackBase::WakeReason(int mask) const
|
||||
{
|
||||
int reason_awoken = last_wake_flags ^ wake_flags;
|
||||
|
||||
reason_awoken = reason_awoken & mask;
|
||||
|
||||
if (reason_awoken & WAKE_INTERRUPT)
|
||||
{
|
||||
if (wake_flags & WAKE_INTERRUPT)
|
||||
return WAKE_INTERRUPT;
|
||||
else
|
||||
return WAKE_RESUME;
|
||||
}
|
||||
|
||||
if (reason_awoken & WAKE_STOP)
|
||||
{
|
||||
return WAKE_STOP;
|
||||
}
|
||||
|
||||
if (reason_awoken & WAKE_KILL)
|
||||
{
|
||||
return WAKE_KILL;
|
||||
}
|
||||
|
||||
if (reason_awoken & WAKE_PLAY)
|
||||
{
|
||||
if (wake_flags & WAKE_PLAY)
|
||||
return WAKE_PLAY;
|
||||
else /* if someone cleared the play flag for whatever reason, just treat it as a 0 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (reason_awoken & WAKE_PAUSE)
|
||||
{
|
||||
if (wake_flags & WAKE_PAUSE)
|
||||
return WAKE_PAUSE;
|
||||
else
|
||||
return WAKE_UNPAUSE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PlaybackBase::Wake(int mask)
|
||||
{
|
||||
assert(mask != 0); /* make sure they didn't specify a 0 mask (which would make this function potentially never return */
|
||||
assert((mask & WAKE_ALL_MASK) != 0); /* make sure it's a valid mask */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int reason_awoken = last_wake_flags ^ wake_flags;
|
||||
reason_awoken = reason_awoken & mask;
|
||||
|
||||
if (reason_awoken)
|
||||
{
|
||||
int ret = WakeReason(mask);
|
||||
ToggleFlags(ret); // mark the last-known-state of the wake flags
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
if (((mask & WAKE_PLAY) && !(wake_flags & WAKE_PLAY))/* if we're stopped and they asked to be woken up for play */
|
||||
|| ((mask & WAKE_PAUSE) && (wake_flags & WAKE_PAUSE)) /* or waiting to be woken up for unpause */
|
||||
|| ((mask & WAKE_INTERRUPT) && (wake_flags & WAKE_INTERRUPT))) /* or waiting to be woken up for resume */
|
||||
{
|
||||
thread_loop.Step();
|
||||
|
||||
int ret = WakeReason(mask);
|
||||
if (ret) /* if ret is !0, it means we gotten woken up for a reason we care about */
|
||||
{
|
||||
ToggleFlags(ret); // mark the last-known-state of the wake flags
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else /* no reason to sleep, so just return 0 (no change) */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int PlaybackBase::Check(int mask)
|
||||
{
|
||||
assert(mask != 0); /* make sure they didn't specify a 0 mask (which would make this function potentially never return */
|
||||
assert((mask & WAKE_ALL_MASK) != 0); /* make sure it's a valid mask */
|
||||
|
||||
int reason_awoken = last_wake_flags ^ wake_flags;
|
||||
reason_awoken = reason_awoken & mask;
|
||||
|
||||
int ret = 0;
|
||||
if (reason_awoken)
|
||||
{
|
||||
ret = WakeReason(mask);
|
||||
ToggleFlags(ret); // mark the last-known-state of the wake flags
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int PlaybackBase::Wait(unsigned int milliseconds, int mask)
|
||||
{
|
||||
int reason_awoken = last_wake_flags ^ wake_flags;
|
||||
reason_awoken = reason_awoken & mask;
|
||||
|
||||
if (reason_awoken)
|
||||
{
|
||||
int ret = WakeReason(mask);
|
||||
ToggleFlags(ret); // mark the last-known-state of the wake flags
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
thread_loop.Step(milliseconds);
|
||||
|
||||
int ret = WakeReason(mask);
|
||||
ToggleFlags(ret); // mark the last-known-state of the wake flags
|
||||
return ret;
|
||||
}
|
||||
|
||||
int PlaybackBase::Sleep(unsigned int milliseconds, int mask)
|
||||
{
|
||||
int reason_awoken = last_wake_flags ^ wake_flags;
|
||||
reason_awoken = reason_awoken & mask;
|
||||
|
||||
if (reason_awoken)
|
||||
{
|
||||
int ret = WakeReason(mask);
|
||||
assert(ret != 0);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
thread_loop.Step(milliseconds);
|
||||
|
||||
int ret = WakeReason(mask);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void PlaybackBase::OnStopPlaying()
|
||||
{
|
||||
// turn off the play flag (also adjust old wake flags so we don't trigger a WAKE_STOP)
|
||||
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] OnStopPlaying");
|
||||
|
||||
wake_flags &= ~WAKE_PLAY;
|
||||
last_wake_flags &= ~WAKE_PLAY;
|
||||
}
|
||||
|
||||
void PlaybackBase::OnInterrupted()
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] OnInterrupted");
|
||||
|
||||
wake_flags &= ~WAKE_INTERRUPT;
|
||||
last_wake_flags &= ~WAKE_INTERRUPT;
|
||||
}
|
||||
|
||||
Agave_Seek *PlaybackBase::GetSeek()
|
||||
{
|
||||
Agave_Seek *seek = queued_seek;
|
||||
queued_seek=0;
|
||||
return seek;
|
||||
}
|
||||
|
||||
void PlaybackBase::FreeSeek(Agave_Seek *seek)
|
||||
{
|
||||
free(seek);
|
||||
}
|
||||
|
||||
bool PlaybackBase::PendingSeek()
|
||||
{
|
||||
return !!queued_seek;
|
||||
}
|
||||
|
||||
void PlaybackBase::APC_Play(void *_playback_base, void *param2, double real_value)
|
||||
{
|
||||
PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
|
||||
playback_base->wake_flags |= WAKE_PLAY;
|
||||
}
|
||||
|
||||
void PlaybackBase::APC_Seek(void *_playback_base, void *_seek, double real_value)
|
||||
{
|
||||
PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
|
||||
Agave_Seek *seek = (Agave_Seek *)_seek;
|
||||
free(playback_base->queued_seek);
|
||||
playback_base->queued_seek = seek;
|
||||
|
||||
}
|
||||
|
||||
void PlaybackBase::APC_Pause(void *_playback_base, void *param2, double real_value)
|
||||
{
|
||||
PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
|
||||
playback_base->wake_flags |= WAKE_PAUSE;
|
||||
}
|
||||
|
||||
void PlaybackBase::APC_Unpause(void *_playback_base, void *param2, double real_value)
|
||||
{
|
||||
PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
|
||||
playback_base->wake_flags &= ~WAKE_PAUSE;
|
||||
}
|
||||
|
||||
void PlaybackBase::APC_Stop(void *_playback_base, void *param2, double real_value)
|
||||
{
|
||||
PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
|
||||
playback_base->wake_flags |= WAKE_STOP;
|
||||
}
|
||||
|
||||
void PlaybackBase::APC_Close(void *_playback_base, void *param2, double real_value)
|
||||
{
|
||||
PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
|
||||
playback_base->wake_flags |= WAKE_KILL;
|
||||
}
|
||||
|
||||
void PlaybackBase::APC_Interrupt(void *_playback_base, void *param2, double real_value)
|
||||
{
|
||||
PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
|
||||
playback_base->wake_flags |= WAKE_INTERRUPT;
|
||||
}
|
91
Src/replicant/nswasabi/PlaybackBase.h
Normal file
91
Src/replicant/nswasabi/PlaybackBase.h
Normal file
@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
#include "nx/nx.h"
|
||||
#include "nu/LockFreeItem.h"
|
||||
#include "player/ifc_playback.h"
|
||||
#include "player/ifc_player.h"
|
||||
#include "player/svc_output.h"
|
||||
#include "nu/ThreadLoop.h"
|
||||
#include "filelock/api_filelock.h"
|
||||
|
||||
/* TODO: we can probably redo this without the mutex, possibly using semaphores */
|
||||
class PlaybackBase : public ifc_playback, public cb_filelock
|
||||
{
|
||||
public:
|
||||
using ifc_playback::Retain;
|
||||
using ifc_playback::Release;
|
||||
|
||||
|
||||
/* ifc_playback implementation */
|
||||
int WASABICALL Playback_Play(svc_output *output, ifc_playback_parameters *secondary_parameters);
|
||||
int WASABICALL Playback_SeekSeconds(double seconds);
|
||||
int WASABICALL Playback_Pause();
|
||||
int WASABICALL Playback_Unpause();
|
||||
int WASABICALL Playback_Stop();
|
||||
int WASABICALL Playback_Close();
|
||||
|
||||
/* cb_filelock implementation */
|
||||
int WASABICALL FileLockCallback_Interrupt();
|
||||
protected:
|
||||
nx_thread_t playback_thread;
|
||||
svc_output *output_service;
|
||||
ifc_player *player;
|
||||
ifc_playback_parameters *secondary_parameters;
|
||||
nx_uri_t filename;
|
||||
|
||||
enum
|
||||
{
|
||||
WAKE_KILL=(1<<0),
|
||||
WAKE_PLAY=(1<<1),
|
||||
WAKE_PAUSE=(1<<2),
|
||||
WAKE_STOP=(1<<3),
|
||||
WAKE_INTERRUPT=(1<<4),
|
||||
WAKE_UNPAUSE=(1<<5), // this is actually unused in wake_flags, just used as a return value from Wake/WakeReason
|
||||
WAKE_RESUME=(1<<6), // this is actually unused in wake_flags, just used as a return value from Wake/WakeReason
|
||||
WAKE_START_MASK = WAKE_PLAY|WAKE_STOP,
|
||||
WAKE_KILL_MASK = WAKE_KILL|WAKE_STOP,
|
||||
WAKE_ALL_MASK = WAKE_KILL|WAKE_PLAY|WAKE_PAUSE|WAKE_STOP|WAKE_INTERRUPT,
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
PlaybackBase();
|
||||
~PlaybackBase();
|
||||
|
||||
/* === API for derived classes to use === */
|
||||
int Initialize(nx_uri_t filename, ifc_player *player);
|
||||
int Init();
|
||||
|
||||
/* this checks if one of the flags in mask has toggled.
|
||||
if playback is stopped and WAKE_PLAY is in the mask, this will sleep until a flag changes
|
||||
if playback is paused and WAKE_PAUSE is in the mask, this will sleep until a flag changes
|
||||
if both WAKE_PLAY and WAKE_PAUSE are in the mask, this will sleep until either happens
|
||||
returns 0 if no flag changed */
|
||||
int Wake(int mask); /* Sleeps indefinitely until a flag changes */
|
||||
int Check(int mask); /* like Wake() but never actually goes to sleep for any reason */
|
||||
int Wait(unsigned int milliseconds, int mask); /* Sleeps for a limited amount of time for a flag to change */
|
||||
int Sleep(unsigned int milliseconds, int mask); /* unlike Wait, this one does *not* update last flags */
|
||||
int WakeReason(int mask) const;
|
||||
|
||||
void OnInterrupted(); /* turn off the WAKE_INTERRUPT flag */
|
||||
void OnStopPlaying(); /* turn off the WAKE_PLAY flag */
|
||||
bool PendingSeek();
|
||||
Agave_Seek *GetSeek();
|
||||
void FreeSeek(Agave_Seek *seek);
|
||||
/* === End of API for derived classes to use === */
|
||||
private:
|
||||
void ToggleFlags(int wake_reason);
|
||||
|
||||
int wake_flags; /* marked volatile so the compiler doesn't cache */
|
||||
int last_wake_flags;
|
||||
Agave_Seek *queued_seek;
|
||||
|
||||
ThreadLoop thread_loop;
|
||||
static void APC_Play(void *_playback_base, void *param2, double real_value);
|
||||
static void APC_Seek(void *_playback_base, void *param2, double real_value);
|
||||
static void APC_Pause(void *_playback_base, void *param2, double real_value);
|
||||
static void APC_Unpause(void *_playback_base, void *param2, double real_value);
|
||||
static void APC_Stop(void *_playback_base, void *param2, double real_value);
|
||||
static void APC_Close(void *_playback_base, void *param2, double real_value);
|
||||
static void APC_Interrupt(void *_playback_base, void *param2, double real_value);
|
||||
|
||||
};
|
490
Src/replicant/nswasabi/PlaybackBase2.cpp
Normal file
490
Src/replicant/nswasabi/PlaybackBase2.cpp
Normal file
@ -0,0 +1,490 @@
|
||||
#include "PlaybackBase2.h"
|
||||
|
||||
PlaybackImpl::PlaybackImpl()
|
||||
{
|
||||
playback=0;
|
||||
playback_parameters=0;
|
||||
}
|
||||
|
||||
PlaybackImpl::~PlaybackImpl()
|
||||
{
|
||||
// TODO: decide if we need playback->Release() or not
|
||||
if (playback_parameters)
|
||||
playback_parameters->Release();
|
||||
}
|
||||
|
||||
void PlaybackImpl::Connect(PlaybackBase2 *playback, ifc_playback_parameters *playback_parameters)
|
||||
{
|
||||
this->playback = playback;
|
||||
// TODO: decide if we need playback->Retain() or not
|
||||
|
||||
this->playback_parameters = playback_parameters;
|
||||
if (playback_parameters)
|
||||
playback_parameters->Retain();
|
||||
|
||||
}
|
||||
|
||||
/* ---------- */
|
||||
PlaybackBase2::PlaybackBase2()
|
||||
{
|
||||
out=0;
|
||||
implementation=0;
|
||||
filelocker=0;
|
||||
paused=false;
|
||||
last_position=0;
|
||||
output_pointers=0;
|
||||
exact_length=false;
|
||||
memset(¶meters, 0, sizeof(parameters));
|
||||
}
|
||||
|
||||
PlaybackBase2::~PlaybackBase2()
|
||||
{
|
||||
/* out should have hopefully been close already. just in case */
|
||||
if (out)
|
||||
out->Release();
|
||||
out=0;
|
||||
|
||||
if (filelocker)
|
||||
filelocker->Release();
|
||||
delete implementation;
|
||||
free(output_pointers);
|
||||
|
||||
}
|
||||
|
||||
ns_error_t PlaybackBase2::Initialize(api_service *service_manager, PlaybackImpl *implementation, nx_uri_t filename, ifc_player *player)
|
||||
{
|
||||
service_manager->GetService(&filelocker);
|
||||
|
||||
this->implementation = implementation;
|
||||
ns_error_t ret = PlaybackBase::Initialize(filename, player);
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
|
||||
implementation->Connect(this, secondary_parameters);
|
||||
|
||||
this->ifc_playback::Retain(); /* the thread needs to hold a reference to this object so that it doesn't disappear out from under us */
|
||||
NXThreadCreate(&playback_thread, PlayerThreadFunction, this);
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
nx_thread_return_t PlaybackBase2::PlayerThreadFunction(nx_thread_parameter_t param)
|
||||
{
|
||||
PlaybackBase2 *playback = (PlaybackBase2 *)param;
|
||||
NXThreadCurrentSetPriority(NX_THREAD_PRIORITY_PLAYBACK);
|
||||
nx_thread_return_t ret = playback->DecodeLoop();
|
||||
playback->ifc_playback::Release(); /* give up the reference that was acquired before spawning the thread */
|
||||
return ret;
|
||||
}
|
||||
|
||||
int PlaybackBase2::Init()
|
||||
{
|
||||
if (filelocker)
|
||||
filelocker->WaitForReadInterruptable(filename, this);
|
||||
|
||||
ns_error_t ret = implementation->Open(filename);
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
|
||||
ifc_metadata *metadata;
|
||||
if (implementation->GetMetadata(&metadata) == NErr_Success)
|
||||
{
|
||||
player->SetMetadata(metadata);
|
||||
metadata->Release();
|
||||
}
|
||||
else
|
||||
player->SetMetadata(0);
|
||||
|
||||
player->SetSeekable(implementation->IsSeekable()?1:0);
|
||||
|
||||
double length;
|
||||
ret = implementation->GetLength(&length, &exact_length);
|
||||
if (ret == NErr_Success)
|
||||
player->SetLength(length);
|
||||
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
nx_thread_return_t PlaybackBase2::DecodeLoop()
|
||||
{
|
||||
player->OnLoaded(filename);
|
||||
|
||||
int ret = Init();
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
implementation->Close();
|
||||
if (filelocker)
|
||||
filelocker->UnlockFile(filename);
|
||||
player->OnError(ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
player->OnReady();
|
||||
|
||||
/* wait for Play (or Stop to abort) */
|
||||
for (;;)
|
||||
{
|
||||
ns_error_t ret = Wake(WAKE_PLAY|WAKE_STOP|WAKE_INTERRUPT);
|
||||
if (ret == WAKE_PLAY)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (ret == WAKE_STOP)
|
||||
{
|
||||
player->OnStopped();
|
||||
goto cleanup;
|
||||
}
|
||||
else if (ret == WAKE_INTERRUPT)
|
||||
{
|
||||
ns_error_t ret = Internal_Interrupt();
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
implementation->Close();
|
||||
player->OnError(ret);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* at this point, we know that PLAY is on */
|
||||
for (;;)
|
||||
{
|
||||
int ret = Check(WAKE_STOP|WAKE_PAUSE|WAKE_INTERRUPT);
|
||||
if (ret == WAKE_PAUSE)
|
||||
{
|
||||
if (out)
|
||||
out->Pause(1);
|
||||
paused=true;
|
||||
continue; /* continue in case there's another wake reason */
|
||||
}
|
||||
else if (ret== WAKE_UNPAUSE)
|
||||
{
|
||||
if (out)
|
||||
out->Pause(0);
|
||||
paused=false;
|
||||
continue; /* continue in case there's another wake reason */
|
||||
}
|
||||
else if (ret == WAKE_STOP)
|
||||
{
|
||||
if (out)
|
||||
{
|
||||
out->Stop();
|
||||
out->Release();
|
||||
out=0;
|
||||
}
|
||||
player->OnStopped();
|
||||
goto cleanup;
|
||||
}
|
||||
else if (ret == WAKE_INTERRUPT)
|
||||
{
|
||||
ns_error_t ret = Internal_Interrupt();
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
implementation->Close();
|
||||
player->OnError(ret);
|
||||
goto cleanup;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Agave_Seek *seek = PlaybackBase::GetSeek();
|
||||
if (seek)
|
||||
{
|
||||
ns_error_t seek_error;
|
||||
double new_position;
|
||||
ns_error_t ret = implementation->Seek(seek, &seek_error, &new_position);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
player->OnError(ret);
|
||||
goto cleanup;
|
||||
}
|
||||
if (out)
|
||||
out->Flush(new_position);
|
||||
player->OnSeekComplete(seek_error, new_position);
|
||||
PlaybackBase::FreeSeek(seek);
|
||||
}
|
||||
|
||||
ret = implementation->DecodeStep();
|
||||
if (ret == NErr_EndOfFile)
|
||||
{
|
||||
if (out)
|
||||
out->Done();
|
||||
|
||||
PlaybackBase::OnStopPlaying();
|
||||
player->OnEndOfFile();
|
||||
|
||||
ret = WaitForClose();
|
||||
if (out)
|
||||
out->Release();
|
||||
out=0;
|
||||
|
||||
if (ret != NErr_True)
|
||||
goto cleanup;
|
||||
}
|
||||
else if (ret != NErr_Success)
|
||||
{
|
||||
if (out)
|
||||
{
|
||||
out->Done();
|
||||
out->Release();
|
||||
out=0;
|
||||
}
|
||||
if (ret != NErr_False)
|
||||
player->OnError(NErr_Error); // TODO: find better error code
|
||||
goto cleanup;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!exact_length)
|
||||
{
|
||||
double length;
|
||||
ret = implementation->GetLength(&length, &exact_length);
|
||||
if (ret == NErr_Success)
|
||||
player->SetLength(length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
implementation->Close();
|
||||
|
||||
if (filelocker)
|
||||
filelocker->UnlockFile(filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ns_error_t PlaybackBase2::WaitForClose()
|
||||
{
|
||||
if (!out)
|
||||
{
|
||||
player->OnClosed();
|
||||
return NErr_False;
|
||||
}
|
||||
else for (;;)
|
||||
{
|
||||
int ret = Wait(10, WAKE_PLAY|WAKE_KILL|WAKE_STOP);
|
||||
if (ret == WAKE_KILL)
|
||||
{
|
||||
player->OnClosed();
|
||||
return NErr_False;
|
||||
}
|
||||
else if (ret == WAKE_PLAY)
|
||||
{
|
||||
return NErr_True;
|
||||
}
|
||||
else if (ret == WAKE_STOP)
|
||||
{
|
||||
player->OnStopped();
|
||||
return NErr_False;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (out->Playing() == NErr_True)
|
||||
player->SetPosition(last_position - out->Latency());
|
||||
else
|
||||
{
|
||||
player->SetPosition(last_position);
|
||||
player->OnClosed();
|
||||
return NErr_False;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ns_error_t PlaybackBase2::OpenOutput(const ifc_audioout::Parameters *_parameters)
|
||||
{
|
||||
// if out is already set, it means that there was a change in parameters, so we'll start a new stream
|
||||
if (out)
|
||||
{
|
||||
// check to see that the parameters actually changed
|
||||
if (!memcmp(¶meters, _parameters, sizeof(parameters)))
|
||||
return NErr_Success;
|
||||
|
||||
out->Done();
|
||||
out=0;
|
||||
}
|
||||
|
||||
parameters = *_parameters;
|
||||
|
||||
free(output_pointers);
|
||||
output_pointers = (const uint8_t **)malloc(parameters.audio.number_of_channels * sizeof(const uint8_t *));
|
||||
if (!output_pointers)
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
ns_error_t ret = output_service->AudioOpen(¶meters, player, secondary_parameters, &out);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
player->OnError(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (paused)
|
||||
out->Pause(1);
|
||||
else
|
||||
out->Pause(0);
|
||||
|
||||
|
||||
return NErr_True;
|
||||
}
|
||||
|
||||
int PlaybackBase2::OutputNonInterleaved(const void *decode_buffer, size_t decoded, double start_position)
|
||||
{
|
||||
int ret;
|
||||
size_t frames_written=0;
|
||||
const uint8_t **buffer = (const uint8_t **)decode_buffer;
|
||||
|
||||
for (size_t c=0;c<parameters.audio.number_of_channels;c++)
|
||||
{
|
||||
output_pointers[c] = buffer[c];
|
||||
}
|
||||
|
||||
while (decoded)
|
||||
{
|
||||
size_t to_write = out->CanWrite();
|
||||
if (to_write)
|
||||
{
|
||||
if (decoded < to_write)
|
||||
to_write = decoded;
|
||||
|
||||
ret = out->Output(output_pointers, to_write);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
out->Release();
|
||||
out=0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
decoded -= to_write;
|
||||
for (size_t c=0;c<parameters.audio.number_of_channels;c++)
|
||||
{
|
||||
output_pointers[c] += to_write/parameters.audio.number_of_channels;
|
||||
}
|
||||
frames_written += to_write/parameters.audio.number_of_channels;
|
||||
player->SetPosition(start_position + (double)frames_written/parameters.audio.sample_rate - out->Latency());
|
||||
}
|
||||
else
|
||||
{
|
||||
ns_error_t ret = OutputWait();
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return NErr_True;
|
||||
}
|
||||
|
||||
int PlaybackBase2::Output(const void *decode_buffer, size_t decoded, double start_position)
|
||||
{
|
||||
int ret;
|
||||
size_t frames_written=0;
|
||||
const uint8_t *decode8 = (const uint8_t *)decode_buffer;
|
||||
size_t buffer_position=0;
|
||||
while (decoded)
|
||||
{
|
||||
size_t to_write = out->CanWrite();
|
||||
if (to_write)
|
||||
{
|
||||
if (decoded < to_write)
|
||||
to_write = decoded;
|
||||
|
||||
ret = out->Output(&decode8[buffer_position], to_write);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
out->Release();
|
||||
out=0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
decoded -= to_write;
|
||||
buffer_position += to_write;
|
||||
frames_written += to_write/parameters.audio.number_of_channels;
|
||||
player->SetPosition(start_position + (double)frames_written/parameters.audio.sample_rate - out->Latency());
|
||||
}
|
||||
else
|
||||
{
|
||||
ns_error_t ret = OutputWait();
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return NErr_True;
|
||||
}
|
||||
|
||||
ns_error_t PlaybackBase2::OutputWait()
|
||||
{
|
||||
if (paused)
|
||||
{
|
||||
/* if we're paused, we need to sit and wait until we're eiter unpaused or stopped */
|
||||
for (;;)
|
||||
{
|
||||
int ret = Wake(WAKE_STOP|WAKE_PAUSE|WAKE_INTERRUPT);
|
||||
if (ret == WAKE_STOP)
|
||||
{
|
||||
out->Stop();
|
||||
out->Release();
|
||||
out=0;
|
||||
player->OnStopped();
|
||||
return NErr_False;
|
||||
}
|
||||
else if (ret == WAKE_UNPAUSE)
|
||||
{
|
||||
out->Pause(0);
|
||||
paused=false;
|
||||
break;
|
||||
}
|
||||
else if (ret == WAKE_PAUSE)
|
||||
{
|
||||
out->Pause(1);
|
||||
paused=true;
|
||||
}
|
||||
else if (PlaybackBase::PendingSeek())
|
||||
{
|
||||
return NErr_True;
|
||||
}
|
||||
else if (ret == WAKE_INTERRUPT)
|
||||
{
|
||||
ns_error_t ret = Internal_Interrupt();
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int ret = Wait(10, WAKE_STOP);
|
||||
if (ret == WAKE_STOP)
|
||||
{
|
||||
out->Stop();
|
||||
out->Release();
|
||||
out=0;
|
||||
player->OnStopped();
|
||||
return NErr_False;
|
||||
}
|
||||
}
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
ns_error_t PlaybackBase2::Internal_Interrupt()
|
||||
{
|
||||
Agave_Seek resume_information;
|
||||
implementation->Interrupt(&resume_information);
|
||||
ns_error_t ret = filelocker->UnlockFile(filename);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
implementation->Close();
|
||||
return ret;
|
||||
}
|
||||
PlaybackBase::OnInterrupted();
|
||||
if (filelocker)
|
||||
filelocker->WaitForReadInterruptable(filename, this);
|
||||
ret = implementation->Resume(&resume_information);
|
||||
|
||||
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
ifc_metadata *metadata;
|
||||
if (implementation->GetMetadata(&metadata) == NErr_Success)
|
||||
{
|
||||
player->SetMetadata(metadata);
|
||||
metadata->Release();
|
||||
}
|
||||
return NErr_Success;
|
||||
}
|
78
Src/replicant/nswasabi/PlaybackBase2.h
Normal file
78
Src/replicant/nswasabi/PlaybackBase2.h
Normal file
@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
#include "PlaybackBase.h"
|
||||
#include "foundation/error.h"
|
||||
#include "service/api_service.h"
|
||||
/* this one does most of the work for you.
|
||||
It assumes blocking I/O and, generally, a simple implementation
|
||||
You provide an implementation of PlaybackImpl */
|
||||
|
||||
class PlaybackBase2;
|
||||
|
||||
class PlaybackImpl
|
||||
{
|
||||
public:
|
||||
void Connect(PlaybackBase2 *playback, ifc_playback_parameters *playback_parameters);
|
||||
|
||||
/* stuff you need to implement */
|
||||
|
||||
/* destructor. be diligent about closing stuff, can't guarantee that Close() got called beforehand */
|
||||
virtual ~PlaybackImpl();
|
||||
|
||||
virtual ns_error_t Open(nx_uri_t filename)=0;
|
||||
/* you need to handle the possibility that Close gets called more than one time */
|
||||
virtual void Close()=0;
|
||||
virtual bool IsSeekable()=0;
|
||||
/* implementation note: add a reference (Retain) before assigning the value */
|
||||
virtual ns_error_t GetMetadata(ifc_metadata **metadata)=0;
|
||||
/* if you set *exact=false, GetLength will get called after the next DecodeStep */
|
||||
virtual ns_error_t GetLength(double *length, bool *exact)=0;
|
||||
/* only return an error if you're in a state you can't recover from.
|
||||
if you can't seek, then just don't seek and return NErr_Success */
|
||||
virtual ns_error_t Seek(const Agave_Seek *seek, ns_error_t *seek_error, double *new_position)=0;
|
||||
/* return NErr_Success to continue
|
||||
NErr_EndOfFile to indicate a natural end of file
|
||||
otherwise return an error */
|
||||
virtual ns_error_t DecodeStep()=0;
|
||||
/* Save information and close the OS file handle.
|
||||
fill resume_information with whatever information you'll need to resume */
|
||||
virtual ns_error_t Interrupt(Agave_Seek *resume_information)=0;
|
||||
/* During resume, be sure to call player->SetMetadata again */
|
||||
virtual ns_error_t Resume(Agave_Seek *resume_information)=0;
|
||||
protected:
|
||||
|
||||
PlaybackBase2 *playback;
|
||||
ifc_playback_parameters *playback_parameters;
|
||||
PlaybackImpl();
|
||||
|
||||
};
|
||||
|
||||
class PlaybackBase2 : public PlaybackBase
|
||||
{
|
||||
public:
|
||||
PlaybackBase2();
|
||||
~PlaybackBase2();
|
||||
|
||||
ns_error_t Initialize(api_service *service_manager, PlaybackImpl *implementation, nx_uri_t filename, ifc_player *player);
|
||||
|
||||
/* this two should ONLY be called from within your DecodeStep function! */
|
||||
ns_error_t OpenOutput(const ifc_audioout::Parameters *parameters); // if this returns an error, return it from DecodeStep()
|
||||
ns_error_t Output(const void *audio_data, size_t audio_data_length, double begin_position_seconds); // if this returns an error, return it from DecodeStep()
|
||||
ns_error_t OutputNonInterleaved(const void *audio_data, size_t audio_data_length, double begin_position_seconds); // if this returns an error, return it from DecodeStep()
|
||||
|
||||
private:
|
||||
static nx_thread_return_t NXTHREADCALL PlayerThreadFunction(nx_thread_parameter_t param);
|
||||
nx_thread_return_t NXTHREADCALL DecodeLoop();
|
||||
ns_error_t Init();
|
||||
ns_error_t WaitForClose();
|
||||
ns_error_t OutputWait();
|
||||
ns_error_t Internal_Interrupt();
|
||||
|
||||
PlaybackImpl *implementation;
|
||||
api_filelock *filelocker;
|
||||
ifc_audioout *out;
|
||||
bool paused;
|
||||
double last_position;
|
||||
bool exact_length;
|
||||
ifc_audioout::Parameters parameters;
|
||||
const uint8_t **output_pointers;
|
||||
};
|
232
Src/replicant/nswasabi/ReferenceCounted.h
Normal file
232
Src/replicant/nswasabi/ReferenceCounted.h
Normal file
@ -0,0 +1,232 @@
|
||||
#pragma once
|
||||
#include "../foundation/dispatch.h"
|
||||
#include "../foundation/atomics.h"
|
||||
#include <new>
|
||||
#include "../nx/nxstring.h"
|
||||
#include "../nx/nxuri.h"
|
||||
|
||||
#define REFERENCE_COUNT_AS(x) size_t Retain() { return x::Retain(); } size_t Release() { return x::Release(); }
|
||||
template <class t>
|
||||
class ReferenceCounted : public t
|
||||
{
|
||||
public:
|
||||
ReferenceCounted() { reference_count = 1; }
|
||||
protected:
|
||||
/* Dispatchable implementation */
|
||||
|
||||
size_t WASABICALL Dispatchable_Retain()
|
||||
{
|
||||
return nx_atomic_inc(&reference_count);
|
||||
}
|
||||
|
||||
size_t WASABICALL Dispatchable_Release()
|
||||
{
|
||||
if (!reference_count)
|
||||
return reference_count;
|
||||
size_t r = nx_atomic_dec(&reference_count);
|
||||
if (!r)
|
||||
{
|
||||
#if defined(__ARM_ARCH_7A__)
|
||||
__asm__ __volatile__ ("dmb" : : : "memory");
|
||||
#endif
|
||||
delete(this);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
size_t reference_count;
|
||||
};
|
||||
|
||||
template <class t>
|
||||
class ReferenceCountedBase
|
||||
{
|
||||
public:
|
||||
ReferenceCountedBase() { reference_count = 1; }
|
||||
|
||||
size_t Retain()
|
||||
{
|
||||
return nx_atomic_inc(&reference_count);
|
||||
}
|
||||
|
||||
size_t Release()
|
||||
{
|
||||
if (!reference_count)
|
||||
return reference_count;
|
||||
size_t r = nx_atomic_dec(&reference_count);
|
||||
if (!r)
|
||||
{
|
||||
#if defined(__ARM_ARCH_7A__)
|
||||
__asm__ __volatile__ ("dmb" : : : "memory");
|
||||
#endif
|
||||
delete static_cast<t*>(this);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
size_t reference_count;
|
||||
};
|
||||
|
||||
template <class t>
|
||||
class ReferenceCountedObject
|
||||
{
|
||||
public:
|
||||
ReferenceCountedObject()
|
||||
{
|
||||
ptr = new (std::nothrow) ReferenceCounted<t>;
|
||||
};
|
||||
|
||||
~ReferenceCountedObject()
|
||||
{
|
||||
if (ptr)
|
||||
ptr->Release();
|
||||
}
|
||||
|
||||
operator t *()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
t *operator ->()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
t *ptr;
|
||||
};
|
||||
|
||||
template <class t>
|
||||
class ReferenceCountedPointer
|
||||
{
|
||||
public:
|
||||
ReferenceCountedPointer()
|
||||
{
|
||||
ptr = 0;
|
||||
};
|
||||
|
||||
ReferenceCountedPointer(t *new_ptr)
|
||||
{
|
||||
ptr = new_ptr;
|
||||
};
|
||||
|
||||
~ReferenceCountedPointer()
|
||||
{
|
||||
if (ptr)
|
||||
ptr->Release();
|
||||
}
|
||||
|
||||
operator t *()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
t *operator ->()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
t **operator &()
|
||||
{
|
||||
// if there's something already in here, we need to release it first
|
||||
if (ptr)
|
||||
ptr->Release();
|
||||
ptr=0;
|
||||
return &ptr;
|
||||
}
|
||||
|
||||
t *operator =(t *new_ptr)
|
||||
{
|
||||
if (ptr)
|
||||
ptr->Release();
|
||||
ptr=0;
|
||||
ptr = new_ptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
t *ptr;
|
||||
};
|
||||
|
||||
class ReferenceCountedNXString
|
||||
{
|
||||
public:
|
||||
ReferenceCountedNXString()
|
||||
{
|
||||
ptr = 0;
|
||||
}
|
||||
|
||||
ReferenceCountedNXString(const ReferenceCountedNXString ©)
|
||||
{
|
||||
ptr = NXStringRetain(copy.ptr);
|
||||
}
|
||||
|
||||
~ReferenceCountedNXString()
|
||||
{
|
||||
NXStringRelease(ptr);
|
||||
}
|
||||
|
||||
operator nx_string_t()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
nx_string_t *operator &()
|
||||
{
|
||||
// if there's something already in here, we need to release it first
|
||||
if (ptr)
|
||||
NXStringRelease(ptr);
|
||||
ptr=0;
|
||||
return &ptr;
|
||||
}
|
||||
|
||||
nx_string_t operator =(nx_string_t new_ptr)
|
||||
{
|
||||
if (ptr)
|
||||
NXStringRelease(ptr);
|
||||
|
||||
ptr = new_ptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
nx_string_t operator ->()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
nx_string_t ptr;
|
||||
};
|
||||
|
||||
class ReferenceCountedNXURI
|
||||
{
|
||||
public:
|
||||
ReferenceCountedNXURI()
|
||||
{
|
||||
ptr = 0;
|
||||
}
|
||||
|
||||
ReferenceCountedNXURI(const ReferenceCountedNXURI ©)
|
||||
{
|
||||
ptr = NXURIRetain(copy.ptr);
|
||||
}
|
||||
|
||||
~ReferenceCountedNXURI()
|
||||
{
|
||||
NXURIRelease(ptr);
|
||||
}
|
||||
|
||||
operator nx_uri_t()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
nx_uri_t *operator &()
|
||||
{
|
||||
// if there's something already in here, we need to release it first
|
||||
if (ptr)
|
||||
NXURIRelease(ptr);
|
||||
ptr=0;
|
||||
return &ptr;
|
||||
}
|
||||
|
||||
nx_uri_t operator ->()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
nx_uri_t ptr;
|
||||
};
|
21
Src/replicant/nswasabi/ServiceName.h
Normal file
21
Src/replicant/nswasabi/ServiceName.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "../nx/nxstring.h"
|
||||
|
||||
/*
|
||||
this is a helper class to implement GetServiceName
|
||||
just put WASABI_SERVICE_NAME("Your Service Name"); in the public section of your class declaration.
|
||||
this implementation does leak memory, but I don't think it's that big of a deal (services can't be unloaded at run-time anyway)
|
||||
if we ever implement the NXSTR() macro, we can eliminate this leak
|
||||
|
||||
e.g.
|
||||
class MyAPI : public api_whatever
|
||||
{
|
||||
public:
|
||||
WASABI_SERVICE_NAME("My API");
|
||||
};
|
||||
*/
|
||||
|
||||
#define WASABI_SERVICE_NAME(x) static nx_string_t GetServiceName(){ static nx_string_t service_name=0; if (!service_name) NXStringCreateWithUTF8(&service_name, x); return NXStringRetain(service_name); }
|
||||
#define WASABI_SERVICE_GUID(x) static GUID GetServiceGUID() { return x; }
|
||||
|
||||
|
1
Src/replicant/nswasabi/VERSION
Normal file
1
Src/replicant/nswasabi/VERSION
Normal file
@ -0,0 +1 @@
|
||||
1.2
|
44
Src/replicant/nswasabi/XMLString.cpp
Normal file
44
Src/replicant/nswasabi/XMLString.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "XMLString.h"
|
||||
|
||||
/* TODO: make and use some sort of nx_mutable_string_t object */
|
||||
XMLString::XMLString()
|
||||
{
|
||||
data=0;
|
||||
}
|
||||
|
||||
XMLString::~XMLString()
|
||||
{
|
||||
NXMutableStringDestroy(data);
|
||||
}
|
||||
|
||||
|
||||
void XMLString::Reset()
|
||||
{
|
||||
if (data)
|
||||
data->nx_string_data->len = 0; // TODO: make mutable string function for this
|
||||
}
|
||||
|
||||
nx_string_t XMLString::GetString()
|
||||
{
|
||||
// TODO: make mutable string function for this
|
||||
nx_string_t str = data->nx_string_data;
|
||||
data->nx_string_data = 0;
|
||||
NXMutableStringDestroy(data);
|
||||
data=0;
|
||||
return str;
|
||||
}
|
||||
|
||||
void XMLString::XMLCallback_OnStartElement(const nsxml_char_t *xmlpath, const nsxml_char_t *xmltag, ifc_xmlattributes *attributes)
|
||||
{
|
||||
if (data)
|
||||
data->nx_string_data->len = 0; // TODO: make mutable string function for this
|
||||
}
|
||||
|
||||
void XMLString::XMLCallback_OnCharacterData(const nsxml_char_t *xmlpath, const nsxml_char_t *xmltag, const nsxml_char_t *characters, size_t num_characters)
|
||||
{
|
||||
if (!data)
|
||||
data = NXMutableStringCreateFromXML(characters, num_characters);
|
||||
else
|
||||
NXMutableStringGrowFromXML(data, characters, num_characters);
|
||||
}
|
||||
|
21
Src/replicant/nswasabi/XMLString.h
Normal file
21
Src/replicant/nswasabi/XMLString.h
Normal file
@ -0,0 +1,21 @@
|
||||
#include "xml/ifc_xmlcallback.h"
|
||||
#include "nx/nxmutablestring.h"
|
||||
|
||||
/* this one is an xml callback that just saves the last encountered string */
|
||||
|
||||
class XMLString : public ifc_xmlcallback
|
||||
{
|
||||
public:
|
||||
XMLString();
|
||||
~XMLString();
|
||||
void Reset();
|
||||
nx_string_t GetString();
|
||||
|
||||
private:
|
||||
/* XML callbacks */
|
||||
void WASABICALL XMLCallback_OnStartElement(const nsxml_char_t *xmlpath, const nsxml_char_t *xmltag, ifc_xmlattributes *attributes);
|
||||
void WASABICALL XMLCallback_OnCharacterData(const nsxml_char_t *xmlpath, const nsxml_char_t *xmltag, const nsxml_char_t *characters, size_t num_characters);
|
||||
|
||||
nx_mutable_string_t data;
|
||||
};
|
||||
|
82
Src/replicant/nswasabi/nswasabi.sln
Normal file
82
Src/replicant/nswasabi/nswasabi.sln
Normal file
@ -0,0 +1,82 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29509.3
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nswasabi", "nswasabi.vcxproj", "{E4A6C250-B426-4328-945A-303865086F4C}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27} = {57C90706-B25D-4ACA-9B33-95CDB2427C27}
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915} = {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D} = {E105A0A2-7391-47C5-86AC-718003524C3D}
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nx", "..\nx\nx.vcxproj", "{57C90706-B25D-4ACA-9B33-95CDB2427C27}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nu", "..\nu\nu.vcxproj", "{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jnetlib", "..\jnetlib\jnetlib.vcxproj", "{E105A0A2-7391-47C5-86AC-718003524C3D}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\zlib\zlib.vcxproj", "{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E4A6C250-B426-4328-945A-303865086F4C}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{E4A6C250-B426-4328-945A-303865086F4C}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{E4A6C250-B426-4328-945A-303865086F4C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E4A6C250-B426-4328-945A-303865086F4C}.Debug|x64.Build.0 = Debug|x64
|
||||
{E4A6C250-B426-4328-945A-303865086F4C}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{E4A6C250-B426-4328-945A-303865086F4C}.Release|x64.ActiveCfg = Release|x64
|
||||
{E4A6C250-B426-4328-945A-303865086F4C}.Release|x64.Build.0 = Release|x64
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|x64.Build.0 = Debug|x64
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|Win32.Build.0 = Release|Win32
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|x64.ActiveCfg = Release|x64
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|x64.Build.0 = Release|x64
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.Build.0 = Debug|x64
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.Build.0 = Release|Win32
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.ActiveCfg = Release|x64
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.Build.0 = Release|x64
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.Build.0 = Debug|x64
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.Build.0 = Release|Win32
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.ActiveCfg = Release|x64
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.Build.0 = Release|x64
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.Build.0 = Debug|x64
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.Build.0 = Release|Win32
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.ActiveCfg = Release|x64
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C4E799C1-027B-487B-8E1A-31F2D26A1AFE}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
159
Src/replicant/nswasabi/nswasabi.vcxproj
Normal file
159
Src/replicant/nswasabi/nswasabi.vcxproj
Normal file
@ -0,0 +1,159 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{E4A6C250-B426-4328-945A-303865086F4C}</ProjectGuid>
|
||||
<RootNamespace>nswasabi</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>x86_Debug\</OutDir>
|
||||
<IntDir>x86_Debug\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>x64_Debug\</OutDir>
|
||||
<IntDir>x64_Debug\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>x86_Release\</OutDir>
|
||||
<IntDir>x86_Release\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>x64_Release\</OutDir>
|
||||
<IntDir>x64_Release\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(ProjectDir)x86_Debug\$(ProjectName).lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN64;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(ProjectDir)x64_Debug\$(ProjectName).lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(ProjectDir)x86_Release\$(ProjectName).lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN64;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(ProjectDir)x64_Release\$(ProjectName).lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ApplicationBase.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ApplicationBase.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
499
Src/replicant/nswasabi/nswasabi.xcodeproj/project.pbxproj
Normal file
499
Src/replicant/nswasabi/nswasabi.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,499 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
00479F18151C35C300F99D12 /* nswasabi-prepare */ = {
|
||||
isa = PBXAggregateTarget;
|
||||
buildConfigurationList = 00479F19151C35C300F99D12 /* Build configuration list for PBXAggregateTarget "nswasabi-prepare" */;
|
||||
buildPhases = (
|
||||
00479F20151C3CAE00F99D12 /* Generate Version Info */,
|
||||
);
|
||||
dependencies = (
|
||||
0039B375152A1F7100D96D3E /* PBXTargetDependency */,
|
||||
);
|
||||
name = "nswasabi-prepare";
|
||||
productName = "nswasabi-version";
|
||||
};
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
00479F10151C33FE00F99D12 /* XMLString.h in Headers */ = {isa = PBXBuildFile; fileRef = 00B73470151C308A00A8251C /* XMLString.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
00479F22151C3D1D00F99D12 /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = 00479F21151C3D1D00F99D12 /* version.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
00B73471151C308A00A8251C /* AutoCharNX.h in Headers */ = {isa = PBXBuildFile; fileRef = 00B7346A151C308A00A8251C /* AutoCharNX.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
00B73472151C308A00A8251C /* ObjectFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 00B7346B151C308A00A8251C /* ObjectFactory.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
00B73473151C308A00A8251C /* ReferenceCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = 00B7346C151C308A00A8251C /* ReferenceCounted.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
00B73474151C308A00A8251C /* ServiceName.h in Headers */ = {isa = PBXBuildFile; fileRef = 00B7346D151C308A00A8251C /* ServiceName.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
00B73475151C308A00A8251C /* singleton.h in Headers */ = {isa = PBXBuildFile; fileRef = 00B7346E151C308A00A8251C /* singleton.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
00C27E9A15372DEA008D95CD /* precomp.h in Headers */ = {isa = PBXBuildFile; fileRef = 00C27E9915372DEA008D95CD /* precomp.h */; };
|
||||
0CC9987C14C5DC6900484291 /* PlaybackBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CC9987A14C5DC6900484291 /* PlaybackBase.cpp */; };
|
||||
0CC9987D14C5DC6900484291 /* PlaybackBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CC9987B14C5DC6900484291 /* PlaybackBase.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
B104AEA614C7CC5100211271 /* ApplicationBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B104AEA414C7CC5100211271 /* ApplicationBase.cpp */; };
|
||||
B104AEA714C7CC5100211271 /* ApplicationBase.h in Headers */ = {isa = PBXBuildFile; fileRef = B104AEA514C7CC5100211271 /* ApplicationBase.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
B15A069D14F499F9004F70E7 /* ID3v1Metadata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B15A069914F499F9004F70E7 /* ID3v1Metadata.cpp */; };
|
||||
B15A069E14F499F9004F70E7 /* ID3v1Metadata.h in Headers */ = {isa = PBXBuildFile; fileRef = B15A069A14F499F9004F70E7 /* ID3v1Metadata.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
B15A069F14F499F9004F70E7 /* ID3v2Metadata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B15A069B14F499F9004F70E7 /* ID3v2Metadata.cpp */; };
|
||||
B15A06A014F499F9004F70E7 /* ID3v2Metadata.h in Headers */ = {isa = PBXBuildFile; fileRef = B15A069C14F499F9004F70E7 /* ID3v2Metadata.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
B193DFDA14F49B6F005D99FB /* APEv2Metadata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B193DFD814F49B6F005D99FB /* APEv2Metadata.cpp */; };
|
||||
B193DFDB14F49B6F005D99FB /* APEv2Metadata.h in Headers */ = {isa = PBXBuildFile; fileRef = B193DFD914F49B6F005D99FB /* APEv2Metadata.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
0039B374152A1F7100D96D3E /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0CC9986414C5DC3C00484291 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 00479F14151C35B700F99D12;
|
||||
remoteInfo = "nswasabi-cleanup";
|
||||
};
|
||||
00479F1C151C3C4000F99D12 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0CC9986414C5DC3C00484291 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 00479F14151C35B700F99D12;
|
||||
remoteInfo = "nswasabi-cleanup";
|
||||
};
|
||||
00479F1E151C3C4300F99D12 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0CC9986414C5DC3C00484291 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 00479F18151C35C300F99D12;
|
||||
remoteInfo = "nswasabi-version";
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
00479F21151C3D1D00F99D12 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = version.h; path = $PROJECT_DERIVED_FILE_DIR/version.h; sourceTree = "<absolute>"; };
|
||||
00B7346A151C308A00A8251C /* AutoCharNX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoCharNX.h; sourceTree = "<group>"; };
|
||||
00B7346B151C308A00A8251C /* ObjectFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectFactory.h; sourceTree = "<group>"; };
|
||||
00B7346C151C308A00A8251C /* ReferenceCounted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReferenceCounted.h; sourceTree = "<group>"; };
|
||||
00B7346D151C308A00A8251C /* ServiceName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServiceName.h; sourceTree = "<group>"; };
|
||||
00B7346E151C308A00A8251C /* singleton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = singleton.h; sourceTree = "<group>"; };
|
||||
00B7346F151C308A00A8251C /* XMLString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XMLString.cpp; sourceTree = "<group>"; };
|
||||
00B73470151C308A00A8251C /* XMLString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMLString.h; sourceTree = "<group>"; };
|
||||
00B7347A151C309D00A8251C /* VERSION */ = {isa = PBXFileReference; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
|
||||
00C27E9915372DEA008D95CD /* precomp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = precomp.h; sourceTree = "<group>"; };
|
||||
0CC9986D14C5DC3C00484291 /* libnswasabi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libnswasabi.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0CC9987A14C5DC6900484291 /* PlaybackBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlaybackBase.cpp; sourceTree = "<group>"; };
|
||||
0CC9987B14C5DC6900484291 /* PlaybackBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaybackBase.h; sourceTree = "<group>"; };
|
||||
B104AEA414C7CC5100211271 /* ApplicationBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ApplicationBase.cpp; sourceTree = "<group>"; };
|
||||
B104AEA514C7CC5100211271 /* ApplicationBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ApplicationBase.h; sourceTree = "<group>"; };
|
||||
B15A069914F499F9004F70E7 /* ID3v1Metadata.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ID3v1Metadata.cpp; sourceTree = "<group>"; };
|
||||
B15A069A14F499F9004F70E7 /* ID3v1Metadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ID3v1Metadata.h; sourceTree = "<group>"; };
|
||||
B15A069B14F499F9004F70E7 /* ID3v2Metadata.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ID3v2Metadata.cpp; sourceTree = "<group>"; };
|
||||
B15A069C14F499F9004F70E7 /* ID3v2Metadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ID3v2Metadata.h; sourceTree = "<group>"; };
|
||||
B193DFD814F49B6F005D99FB /* APEv2Metadata.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = APEv2Metadata.cpp; sourceTree = "<group>"; };
|
||||
B193DFD914F49B6F005D99FB /* APEv2Metadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APEv2Metadata.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
0CC9986A14C5DC3C00484291 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
00B73479151C308E00A8251C /* Version */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00B7347A151C309D00A8251C /* VERSION */,
|
||||
00479F21151C3D1D00F99D12 /* version.h */,
|
||||
);
|
||||
name = Version;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0CC9986214C5DC3C00484291 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00C27E9915372DEA008D95CD /* precomp.h */,
|
||||
B193DFD814F49B6F005D99FB /* APEv2Metadata.cpp */,
|
||||
B193DFD914F49B6F005D99FB /* APEv2Metadata.h */,
|
||||
B104AEA414C7CC5100211271 /* ApplicationBase.cpp */,
|
||||
B104AEA514C7CC5100211271 /* ApplicationBase.h */,
|
||||
00B7346A151C308A00A8251C /* AutoCharNX.h */,
|
||||
B15A069914F499F9004F70E7 /* ID3v1Metadata.cpp */,
|
||||
B15A069A14F499F9004F70E7 /* ID3v1Metadata.h */,
|
||||
B15A069B14F499F9004F70E7 /* ID3v2Metadata.cpp */,
|
||||
B15A069C14F499F9004F70E7 /* ID3v2Metadata.h */,
|
||||
00B7346B151C308A00A8251C /* ObjectFactory.h */,
|
||||
0CC9987A14C5DC6900484291 /* PlaybackBase.cpp */,
|
||||
0CC9987B14C5DC6900484291 /* PlaybackBase.h */,
|
||||
00B7346C151C308A00A8251C /* ReferenceCounted.h */,
|
||||
00B7346D151C308A00A8251C /* ServiceName.h */,
|
||||
00B7346E151C308A00A8251C /* singleton.h */,
|
||||
00B7346F151C308A00A8251C /* XMLString.cpp */,
|
||||
00B73470151C308A00A8251C /* XMLString.h */,
|
||||
00B73479151C308E00A8251C /* Version */,
|
||||
0CC9986E14C5DC3C00484291 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0CC9986E14C5DC3C00484291 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0CC9986D14C5DC3C00484291 /* libnswasabi.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
0CC9986B14C5DC3C00484291 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0CC9987D14C5DC6900484291 /* PlaybackBase.h in Headers */,
|
||||
B104AEA714C7CC5100211271 /* ApplicationBase.h in Headers */,
|
||||
B15A069E14F499F9004F70E7 /* ID3v1Metadata.h in Headers */,
|
||||
B15A06A014F499F9004F70E7 /* ID3v2Metadata.h in Headers */,
|
||||
B193DFDB14F49B6F005D99FB /* APEv2Metadata.h in Headers */,
|
||||
00B73471151C308A00A8251C /* AutoCharNX.h in Headers */,
|
||||
00B73472151C308A00A8251C /* ObjectFactory.h in Headers */,
|
||||
00B73473151C308A00A8251C /* ReferenceCounted.h in Headers */,
|
||||
00B73474151C308A00A8251C /* ServiceName.h in Headers */,
|
||||
00B73475151C308A00A8251C /* singleton.h in Headers */,
|
||||
00479F10151C33FE00F99D12 /* XMLString.h in Headers */,
|
||||
00479F22151C3D1D00F99D12 /* version.h in Headers */,
|
||||
00C27E9A15372DEA008D95CD /* precomp.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXLegacyTarget section */
|
||||
00479F14151C35B700F99D12 /* nswasabi-cleanup */ = {
|
||||
isa = PBXLegacyTarget;
|
||||
buildArgumentsString = "$(NSBUILD_TOOLS_BIN_DIR)/cleanbuild --xcode-mode --libraries \"$(LIBRARY_PATH)\" \"$(PUBLIC_HEADERS_DIR)\" \"$(DWARF_DSYM_PATH)\" \"$(PROJECT_DERIVED_FILE_DIR)/version.*\"";
|
||||
buildConfigurationList = 00479F15151C35B700F99D12 /* Build configuration list for PBXLegacyTarget "nswasabi-cleanup" */;
|
||||
buildPhases = (
|
||||
);
|
||||
buildToolPath = /bin/sh;
|
||||
buildWorkingDirectory = "";
|
||||
dependencies = (
|
||||
);
|
||||
name = "nswasabi-cleanup";
|
||||
passBuildSettingsInEnvironment = 1;
|
||||
productName = "nswasabi-cleanup";
|
||||
};
|
||||
/* End PBXLegacyTarget section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
0CC9986C14C5DC3C00484291 /* nswasabi */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 0CC9987114C5DC3C00484291 /* Build configuration list for PBXNativeTarget "nswasabi" */;
|
||||
buildPhases = (
|
||||
0CC9986914C5DC3C00484291 /* Sources */,
|
||||
0CC9986A14C5DC3C00484291 /* Frameworks */,
|
||||
0CC9986B14C5DC3C00484291 /* Headers */,
|
||||
00479F13151C354F00F99D12 /* Install Public Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
00479F1D151C3C4000F99D12 /* PBXTargetDependency */,
|
||||
00479F1F151C3C4300F99D12 /* PBXTargetDependency */,
|
||||
);
|
||||
name = nswasabi;
|
||||
productName = nswasabi;
|
||||
productReference = 0CC9986D14C5DC3C00484291 /* libnswasabi.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
0CC9986414C5DC3C00484291 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0500;
|
||||
ORGANIZATIONNAME = "Nullsoft, Inc.";
|
||||
};
|
||||
buildConfigurationList = 0CC9986714C5DC3C00484291 /* Build configuration list for PBXProject "nswasabi" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 0CC9986214C5DC3C00484291;
|
||||
productRefGroup = 0CC9986E14C5DC3C00484291 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
0CC9986C14C5DC3C00484291 /* nswasabi */,
|
||||
00479F14151C35B700F99D12 /* nswasabi-cleanup */,
|
||||
00479F18151C35C300F99D12 /* nswasabi-prepare */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
00479F13151C354F00F99D12 /* Install Public Headers */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 8;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(BUILT_PRODUCTS_DIR)$(PUBLIC_HEADERS_FOLDER_PATH)",
|
||||
);
|
||||
name = "Install Public Headers";
|
||||
outputPaths = (
|
||||
"$(DSTROOT)$(PUBLIC_HEADERS_FOLDER_PATH)",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "INSTALLTOOL=\"$NSBUILD_TOOLS_BIN_DIR/installtool\"\n$INSTALLTOOL --headers-only \\\n \"$SCRIPT_INPUT_FILE_0/\" \\\n \"$SCRIPT_OUTPUT_FILE_0\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
00479F20151C3CAE00F99D12 /* Generate Version Info */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(SRCROOT)/VERSION",
|
||||
"$(NSBUILD_TOOLS_SHARE_DIR)/nvgtool/lib-version.template.h",
|
||||
);
|
||||
name = "Generate Version Info";
|
||||
outputPaths = (
|
||||
"$(PROJECT_DERIVED_FILE_DIR)/version.h",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "PRODUCT_VERSION=$(cat \"$SCRIPT_INPUT_FILE_0\")\n\nif [ ! -d \"$PROJECT_DERIVED_FILE_DIR\" ]; then\n mkdir -p \"$PROJECT_DERIVED_FILE_DIR\"\nfi\n\nNVGTOOL=\"$NSBUILD_TOOLS_BIN_DIR/nvgtool\"\n$NVGTOOL --product-name \"$PRODUCT_NAME\" \\\n --product-version \"$PRODUCT_VERSION\" \\\n --input-file \"$SCRIPT_INPUT_FILE_1\" \\\n --output-file \"$SCRIPT_OUTPUT_FILE_0\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
0CC9986914C5DC3C00484291 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0CC9987C14C5DC6900484291 /* PlaybackBase.cpp in Sources */,
|
||||
B104AEA614C7CC5100211271 /* ApplicationBase.cpp in Sources */,
|
||||
B15A069D14F499F9004F70E7 /* ID3v1Metadata.cpp in Sources */,
|
||||
B15A069F14F499F9004F70E7 /* ID3v2Metadata.cpp in Sources */,
|
||||
B193DFDA14F49B6F005D99FB /* APEv2Metadata.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
0039B375152A1F7100D96D3E /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 00479F14151C35B700F99D12 /* nswasabi-cleanup */;
|
||||
targetProxy = 0039B374152A1F7100D96D3E /* PBXContainerItemProxy */;
|
||||
};
|
||||
00479F1D151C3C4000F99D12 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 00479F14151C35B700F99D12 /* nswasabi-cleanup */;
|
||||
targetProxy = 00479F1C151C3C4000F99D12 /* PBXContainerItemProxy */;
|
||||
};
|
||||
00479F1F151C3C4300F99D12 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 00479F18151C35C300F99D12 /* nswasabi-prepare */;
|
||||
targetProxy = 00479F1E151C3C4300F99D12 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
00479F16151C35B700F99D12 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DWARF_DSYM_PATH = "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_NAME).dSYM";
|
||||
LIBRARY_PATH = "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_NAME)";
|
||||
PUBLIC_HEADERS_DIR = "$(BUILT_PRODUCTS_DIR)$(PUBLIC_HEADERS_FOLDER_PATH)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
00479F17151C35B700F99D12 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DWARF_DSYM_PATH = "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_NAME).dSYM";
|
||||
LIBRARY_PATH = "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_NAME)";
|
||||
PUBLIC_HEADERS_DIR = "$(BUILT_PRODUCTS_DIR)$(PUBLIC_HEADERS_FOLDER_PATH)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
00479F1A151C35C300F99D12 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
00479F1B151C35C300F99D12 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
0CC9986F14C5DC3C00484291 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DYLIB_COMPATIBILITY_VERSION = "$(CURRENT_PROJECT_VERSION)";
|
||||
DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)";
|
||||
EXECUTABLE_EXTENSION = a;
|
||||
EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME).$(EXECUTABLE_EXTENSION)";
|
||||
EXECUTABLE_PREFIX = lib;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = precomp.h;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INSTALL_PATH = "$(INSTALL_PATH_PREFIX)/lib";
|
||||
INSTALL_PATH_PREFIX = /usr/local;
|
||||
MACH_O_TYPE = staticlib;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
NSBUILD_TOOLS_BIN_DIR = "$(NSBUILD_TOOLS_DIR)/bin";
|
||||
NSBUILD_TOOLS_DIR = "$(SRCROOT)/../../build-tools";
|
||||
NSBUILD_TOOLS_SHARE_DIR = "$(NSBUILD_TOOLS_DIR)/share";
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRIVATE_HEADERS_FOLDER_PATH = "$(INSTALL_PATH_PREFIX)/include/$(PRODUCT_NAME)";
|
||||
PRODUCT_NAME = "$(PROJECT_NAME)";
|
||||
PUBLIC_HEADERS_FOLDER_PATH = "$(INSTALL_PATH_PREFIX)/include/$(PRODUCT_NAME)";
|
||||
SDKROOT = macosx;
|
||||
USER_HEADER_SEARCH_PATHS = ".. $(BUILT_PRODUCTS_DIR)$(INSTALL_PATH_PREFIX)/include";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
0CC9987014C5DC3C00484291 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DYLIB_COMPATIBILITY_VERSION = "$(CURRENT_PROJECT_VERSION)";
|
||||
DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)";
|
||||
EXECUTABLE_EXTENSION = a;
|
||||
EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME).$(EXECUTABLE_EXTENSION)";
|
||||
EXECUTABLE_PREFIX = lib;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = precomp.h;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INSTALL_PATH = "$(INSTALL_PATH_PREFIX)/lib";
|
||||
INSTALL_PATH_PREFIX = /usr/local;
|
||||
MACH_O_TYPE = staticlib;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
NSBUILD_TOOLS_BIN_DIR = "$(NSBUILD_TOOLS_DIR)/bin";
|
||||
NSBUILD_TOOLS_DIR = "$(SRCROOT)/../../build-tools";
|
||||
NSBUILD_TOOLS_SHARE_DIR = "$(NSBUILD_TOOLS_DIR)/share";
|
||||
PRIVATE_HEADERS_FOLDER_PATH = "$(INSTALL_PATH_PREFIX)/include/$(PRODUCT_NAME)";
|
||||
PRODUCT_NAME = "$(PROJECT_NAME)";
|
||||
PUBLIC_HEADERS_FOLDER_PATH = "$(INSTALL_PATH_PREFIX)/include/$(PRODUCT_NAME)";
|
||||
SDKROOT = macosx;
|
||||
USER_HEADER_SEARCH_PATHS = ".. $(BUILT_PRODUCTS_DIR)$(INSTALL_PATH_PREFIX)/include";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
0CC9987214C5DC3C00484291 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
0CC9987314C5DC3C00484291 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
00479F15151C35B700F99D12 /* Build configuration list for PBXLegacyTarget "nswasabi-cleanup" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
00479F16151C35B700F99D12 /* Debug */,
|
||||
00479F17151C35B700F99D12 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
00479F19151C35C300F99D12 /* Build configuration list for PBXAggregateTarget "nswasabi-prepare" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
00479F1A151C35C300F99D12 /* Debug */,
|
||||
00479F1B151C35C300F99D12 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
0CC9986714C5DC3C00484291 /* Build configuration list for PBXProject "nswasabi" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
0CC9986F14C5DC3C00484291 /* Debug */,
|
||||
0CC9987014C5DC3C00484291 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
0CC9987114C5DC3C00484291 /* Build configuration list for PBXNativeTarget "nswasabi" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
0CC9987214C5DC3C00484291 /* Debug */,
|
||||
0CC9987314C5DC3C00484291 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 0CC9986414C5DC3C00484291 /* Project object */;
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0500"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0CC9986C14C5DC3C00484291"
|
||||
BuildableName = "libnswasabi.a"
|
||||
BlueprintName = "nswasabi"
|
||||
ReferencedContainer = "container:nswasabi.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
32
Src/replicant/nswasabi/precomp.h
Normal file
32
Src/replicant/nswasabi/precomp.h
Normal file
@ -0,0 +1,32 @@
|
||||
//
|
||||
// precomp.h
|
||||
// nswasabi
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "foundation/error.h"
|
||||
#include "foundation/types.h"
|
||||
|
||||
#include "nu/ByteReader.h"
|
||||
#include "nu/ByteWriter.h"
|
||||
#include "nu/LockFreeItem.h"
|
||||
#include "nu/ThreadLoop.h"
|
||||
|
||||
#include "nx/nxcondition.h"
|
||||
#include "nx/nxstring.h"
|
||||
#include "nx/nxuri.h"
|
||||
#include "nx/nxmutablestring.h"
|
||||
|
||||
#include "metadata/metadata.h"
|
||||
#include "metadata/MetadataKeys.h"
|
||||
|
||||
#include "nsid3v1/nsid3v1.h"
|
||||
#include "nsid3v2/nsid3v2.h"
|
||||
|
||||
#include "service/ifc_servicefactory.h"
|
117
Src/replicant/nswasabi/singleton.h
Normal file
117
Src/replicant/nswasabi/singleton.h
Normal file
@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
|
||||
#include "service/ifc_servicefactory.h"
|
||||
|
||||
/*
|
||||
====== Usage ======
|
||||
disp_t: your Dispatchable base class
|
||||
implt_t: your implementation class
|
||||
|
||||
SingletonServiceFactory<disp_t, impl_t> myFactory;
|
||||
impl_t myImplementation;
|
||||
|
||||
//....
|
||||
|
||||
//during service registration
|
||||
myFactory.Register(WASABI2_API_SVC, &myImplementation);
|
||||
|
||||
//during service deregistration
|
||||
myFactory.Deregister(WASABI2_API_SVC, &myImplementation);
|
||||
|
||||
==== Class requirements ====
|
||||
your base or implementation class requires the following three static methods
|
||||
static FOURCC getServiceType(); // return your type (e.g. WaSvc::UNIQUE)... might already be defined in the dispatchable base class
|
||||
static const char *getServiceName(); // return your service name
|
||||
static GUID getServiceGuid(); // return your service GUID
|
||||
*/
|
||||
|
||||
class WasabiServiceFactory
|
||||
{
|
||||
public:
|
||||
virtual ~WasabiServiceFactory() {}
|
||||
virtual void Register(api_service *serviceManager)=0;
|
||||
virtual void Deregister(api_service *serviceManager)=0;
|
||||
};
|
||||
|
||||
|
||||
template <class impl_t, class disp_t>
|
||||
class SingletonServiceFactory : public ifc_serviceFactory
|
||||
{
|
||||
public:
|
||||
SingletonServiceFactory() : impl(0)
|
||||
{
|
||||
}
|
||||
|
||||
~SingletonServiceFactory()
|
||||
{
|
||||
}
|
||||
|
||||
void Register(api_service *serviceManager, impl_t *new_impl)
|
||||
{
|
||||
impl=new_impl;
|
||||
serviceManager->Register(this);
|
||||
}
|
||||
|
||||
void Deregister(api_service *serviceManager)
|
||||
{
|
||||
if (impl)
|
||||
{
|
||||
serviceManager->Unregister(this);
|
||||
impl=0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
GUID WASABICALL ServiceFactory_GetServiceType() { return impl_t::GetServiceType(); }
|
||||
nx_string_t WASABICALL ServiceFactory_GetServiceName() { return impl_t::GetServiceName(); }
|
||||
GUID WASABICALL ServiceFactory_GetGUID() { return impl_t::GetServiceGUID(); } // GUID per service factory, can be INVALID_GUID
|
||||
void *WASABICALL ServiceFactory_GetInterface() { return static_cast<disp_t *>(impl); }
|
||||
int WASABICALL ServiceFactory_ServiceNotify(int msg, intptr_t param1 = 0, intptr_t param2 = 0) { return 0; }
|
||||
|
||||
private:
|
||||
impl_t *impl;
|
||||
|
||||
};
|
||||
|
||||
/* same as above, but this one also constructs the implementation object itself
|
||||
useful when:
|
||||
1) you don't need to ever access the implementation object yourself
|
||||
2) the implementation class requires no constructor parameters
|
||||
|
||||
TODO: might want to change this to "new" the object during Register and "delete" during Deregister,
|
||||
in case destruction during program termination isn't safe.
|
||||
*/
|
||||
template <class impl_t, class disp_t>
|
||||
class SingletonService : public ifc_serviceFactory, public WasabiServiceFactory
|
||||
{
|
||||
public:
|
||||
SingletonService()
|
||||
{
|
||||
}
|
||||
|
||||
~SingletonService()
|
||||
{
|
||||
}
|
||||
|
||||
void Register(api_service *serviceManager)
|
||||
{
|
||||
serviceManager->Register(this);
|
||||
}
|
||||
|
||||
void Deregister(api_service *serviceManager)
|
||||
{
|
||||
serviceManager->Unregister(this);
|
||||
}
|
||||
|
||||
private:
|
||||
GUID WASABICALL ServiceFactory_GetServiceType() { return impl_t::GetServiceType(); }
|
||||
nx_string_t WASABICALL ServiceFactory_GetServiceName() { return impl_t::GetServiceName(); }
|
||||
GUID WASABICALL ServiceFactory_GetGUID() { return impl_t::GetServiceGUID(); } // GUID per service factory, can be INVALID_GUID
|
||||
void *WASABICALL ServiceFactory_GetInterface() { return static_cast<disp_t *>(&impl); }
|
||||
int WASABICALL ServiceFactory_ServiceNotify(int msg, intptr_t param1 = 0, intptr_t param2 = 0) { return 0; }
|
||||
|
||||
private:
|
||||
impl_t impl;
|
||||
|
||||
};
|
||||
|
Reference in New Issue
Block a user