owntone-server/osx/FireflyCommon.h

230 lines
6.0 KiB
C

/*
* FireflyCommonConstants.h
*
* Created by Mike Kobb on 7/12/06.
* Copyright 2006 Roku LLC. All rights reserved.
*
* This file contains common constants and types needed by both the
* prefs pane and helper apps.
*/
#ifndef __ORG_FIREFLYMEDIASERVER_FIREFLY_COMMON_H
#define __ORG_FIREFLYMEDIASERVER_FIREFLY_COMMON_H
#include <sys/sysctl.h> // used by GetProcesses
#define FIREFLY_SERVER_NAME "firefly"
#define FIREFLY_DIR_NAME "Firefly"
#define FIREFLY_CONF_NAME "firefly.conf"
#define FF_PREFS_DOMAIN "org.fireflymediaserver.firefly"
#define FF_PREFS_LAUNCH_AT_LOGIN "org.fireflymediaserver.launchAtLogin"
#define FF_PREFS_SHOW_MENU_EXTRA "org.fireflymediaserver.showMenuExtra"
// Define this to enable certain debug output
//#define FIREFLY_DEBUG
typedef enum
{
kFireflyStartInvalid = 0,
kFireflyStartSuccess = 1,
kFireflyStartFail = 2
} FireflyStartResult;
typedef enum
{
kFireflyStopInvalid = 0,
kFireflyStopSuccess = 1,
kFireflyStopFail = 2
} FireflyStopResult;
typedef enum
{
kFireflyRestartInvalid = 0,
kFireflyRestartSuccess = 1,
kFireflyRestartFail = 2
} FireflyRestartResult;
typedef enum
{
kFireflyRescanInvalid = 0,
kFireflyRescanSuccess = 1,
kFireflyRescanFail = 2
} FireflyRescanResult;
typedef enum
{
kFireflyStatusInvalid,
kFireflyStatusStopped,
kFireflyStatusStarting,
kFireflyStatusActive,
kFireflyStatusScanning,
kFireflyStatusStopping,
kFireflyStatusRestarting,
kFireflyStatusStartFailed,
kFireflyStatusCrashed
} FireflyServerStatus;
static NSString*
StringForFireflyStatus( FireflyServerStatus inStatus )
{
NSString *retVal = nil;
switch( inStatus )
{
case kFireflyStatusStopped:
retVal = NSLocalizedString( @"Firefly is not running",
@"Status message for Firefly" );
break;
case kFireflyStatusStarting:
retVal = NSLocalizedString( @"Firefly is starting",
@"Status message for Firefly" );
break;
case kFireflyStatusActive:
retVal = NSLocalizedString( @"Firefly is running",
@"Status message for Firefly" );
break;
case kFireflyStatusScanning:
retVal = NSLocalizedString( @"Firefly is scanning the library",
@"Status message for Firefly" );
break;
case kFireflyStatusStopping:
retVal = NSLocalizedString( @"Firefly is stopping",
@"Status message for Firefly" );
break;
case kFireflyStatusRestarting:
retVal = NSLocalizedString( @"Firefly is restarting",
@"Status message for Firefly" );
break;
case kFireflyStatusStartFailed:
retVal = NSLocalizedString( @"Firefly failed to start",
@"Status message for Firefly" );
break;
case kFireflyStatusCrashed:
retVal = NSLocalizedString( @"Firefly stopped unexpectedly",
@"Status message for Firefly" );
break;
case kFireflyStatusInvalid:
default:
retVal = NSLocalizedString( @"Firefly status is unknown",
@"Status message for Firefly" );
break;
}
return retVal;
}
// ===========================================================================
// Process management the Unix way -- Finding if the server is already
// running, or finding a specific process
// ===========================================================================
// This just makes syntax more convenient (don't have to say 'struct' everyplace)
typedef struct kinfo_proc kinfo_proc;
// ------------------------------------------------------------------------
// GetProcesses
//
// Static utility function allocates and returns an array of kinfo_proc
// structures representing the currently-running processes on the machine.
// The calling function is responsible for disposing the returned pointer
// with free()
//
// Because Firefly runs as a BSD daemon, the Process Manager is not useful
// in finding it. Instead, we have to talk to the BSD layer. This code
// was provided by Apple in a tech note.
// ------------------------------------------------------------------------
static void
GetProcesses( kinfo_proc **outResult, size_t *outLength)
{
int err;
kinfo_proc * result;
BOOL done;
static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
// Declaring name as const requires us to cast it when passing it to
// sysctl because the prototype doesn't include the const modifier.
// (That's the Apple comment, but they don't say *why* they made it const...)
size_t length;
// We call sysctl with result == NULL and length == 0.
// That will succeed, and set length to the appropriate length.
// We then allocate a buffer of that size and call sysctl again
// with that buffer. If that succeeds, we're done. If that fails
// with ENOMEM, we have to throw away our buffer and loop. Note
// that the loop causes use to call sysctl with NULL again; this
// is necessary because the ENOMEM failure case sets length to
// the amount of data returned, not the amount of data that
// could have been returned.
result = NULL;
done = NO;
do
{
// Call sysctl with a NULL buffer.
length = 0;
err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
NULL, &length,
NULL, 0);
if (err == -1)
err = errno;
// Allocate an appropriately sized buffer based on the results
// from the previous call.
if (err == 0)
{
result = malloc(length);
if (result == NULL)
err = ENOMEM;
}
// Call sysctl again with the new buffer. If we get an ENOMEM
// error, toss away our buffer and start again.
if (err == 0)
{
err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
result, &length,
NULL, 0);
if (err == -1)
err = errno;
if (err == 0)
done = YES;
else if (err == ENOMEM)
{
free(result);
result = NULL;
err = 0;
}
}
} while (err == 0 && !done);
// Clean up and establish post conditions.
if( err != 0 )
{
if( result != NULL)
free(result);
*outResult = NULL;
*outLength = 0;
}
if( err == 0 )
{
*outResult = result;
*outLength = length;
}
}
// __ORG_FIREFLYMEDIASERVER_FIREFLY_COMMON_H
#endif