Initial community commit

This commit is contained in:
Jef
2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit 20d28e80a5
16810 changed files with 4640254 additions and 2 deletions

View 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;
}

View 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;
};

View 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)

View 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;
}

View 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;
};

View 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:
};

View 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;
}

View 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;
};

View 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

View 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;
};

File diff suppressed because it is too large Load Diff

View 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
};

View 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)

View 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; }
};

View 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;
}
};

View 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; }
};

View 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;
}

View 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);
};

View 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(&parameters, 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(&parameters, _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(&parameters, 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;
}

View 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;
};

View 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 &copy)
{
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 &copy)
{
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;
};

View 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; }

View File

@ -0,0 +1 @@
1.2

View 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);
}

View 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;
};

View 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

View 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>

View 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 */;
}

View File

@ -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>

View 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"

View 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;
};