Add even more of the source
This should be about everything needed to build so far?
This commit is contained in:
parent
af3619d4fa
commit
849723c9cf
547 changed files with 149239 additions and 0 deletions
508
APIModules/QTSSMP3StreamingModule/QTSSMP3StreamingModule.h
Executable file
508
APIModules/QTSSMP3StreamingModule/QTSSMP3StreamingModule.h
Executable file
|
@ -0,0 +1,508 @@
|
|||
/*
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
File: QTSSMP3StreamingModule.h
|
||||
|
||||
Contains: Handle ShoutCast/IceCast-style MP3 streaming.
|
||||
|
||||
Written by: Steve Ussery
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __QTSSMP3STREAMINGMODULE_H__
|
||||
#define __QTSSMP3STREAMINGMODULE_H__
|
||||
|
||||
#include "QTSS.h"
|
||||
#include "OSQueue.h"
|
||||
#include "OSMutex.h"
|
||||
#include "OSHashTable.h"
|
||||
#include "OSBufferPool.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
EXPORT QTSS_Error QTSSMP3StreamingModule_Main(void* inPrivateArgs);
|
||||
}
|
||||
|
||||
#define kURLBufferSize 1024
|
||||
#define kSongNameBufferSize 1024
|
||||
#define kHeaderBufferSize 1024
|
||||
#define kRequestBufferSize 512
|
||||
#define kHostNameBufferSize 256
|
||||
#define kUserAgentBufferSize 256
|
||||
#define kClientMetaInt 24576
|
||||
|
||||
// The client poll interval in milliseconds
|
||||
#define kClientPollInterval 253
|
||||
|
||||
// FORWARD CLASS DEFINES
|
||||
|
||||
class MP3ClientSessionRef;
|
||||
class MP3ClientSession;
|
||||
class MP3ClientQueue;
|
||||
class MP3BroadcasterSession;
|
||||
class MP3BroadcasterQueue;
|
||||
class MP3SessionRef;
|
||||
class MP3SessionRefKey;
|
||||
class MP3SessionTable;
|
||||
|
||||
enum {
|
||||
kMP3UndefinedSessionType = 0,
|
||||
kMP3BroadcasterSessionType,
|
||||
kMP3ClientSessionType
|
||||
};
|
||||
|
||||
//
|
||||
// MP3Session -- This is a base class to hold all the MP3 Session state info.
|
||||
// We will subclass it for MP3 Broadcaster sessions and MP3 Client sessions.
|
||||
// (See the MP3BroadcasterSession & MP3ClientSession classes defined below.)
|
||||
//
|
||||
class MP3Session
|
||||
{
|
||||
public:
|
||||
MP3Session();
|
||||
|
||||
MP3Session(QTSS_RTSPSessionObject sess, QTSS_StreamRef stream);
|
||||
|
||||
virtual ~MP3Session();
|
||||
|
||||
// The IsA() method is a mechanism for subclasses of this class to
|
||||
// identify their type. It is kMP3UndefinedSessionType for this
|
||||
// base class.
|
||||
|
||||
virtual UInt8 IsA() const;
|
||||
|
||||
// Session data field accessor methods
|
||||
|
||||
QTSS_RTSPSessionObject GetSession() { return fSession; }
|
||||
|
||||
void SetSessionID(UInt32 sessID) { fSessID = sessID; }
|
||||
|
||||
UInt32 GetSessionID() { return fSessID; }
|
||||
|
||||
QTSS_StreamRef GetStreamRef() { return fStream; }
|
||||
|
||||
UInt16 GetState() { return fState; }
|
||||
|
||||
void SetState(UInt16 state) { fState = state; }
|
||||
|
||||
UInt16 GetResult() { return fResult; }
|
||||
|
||||
void SetResult(UInt16 result) { fResult = result; }
|
||||
|
||||
static SInt32 GetTotalNumMP3Sessions() { return sTotalNumMP3Sessions; }
|
||||
|
||||
protected:
|
||||
|
||||
void SetSession(QTSS_RTSPSessionObject session) { fSession = session; }
|
||||
|
||||
void SetStreamRef(QTSS_StreamRef stream) { fStream = stream; }
|
||||
|
||||
private:
|
||||
|
||||
static SInt32 sTotalNumMP3Sessions;
|
||||
|
||||
UInt16 fState;
|
||||
UInt16 fResult;
|
||||
QTSS_StreamRef fStream;
|
||||
QTSS_RTSPSessionObject fSession;
|
||||
UInt32 fSessID;
|
||||
};
|
||||
|
||||
//
|
||||
// MP3BroadcasterSession -- This is a class to hold all the MP3 Broadcaster
|
||||
// session-related state info. There is a global queue of these managed by the
|
||||
// server. Each instance of this class must have a unique mountpoint name
|
||||
// string which clients will use to identify the broadcast stream they are
|
||||
// "tuning" into.
|
||||
//
|
||||
class MP3BroadcasterSession : public MP3Session
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
// MP3BroadcasterSession states
|
||||
|
||||
enum {
|
||||
kBroadcasterInitState = 0,
|
||||
kBroadcasterValidatePasswordState,
|
||||
kBroadcasterGetHeaderState,
|
||||
kBroadcasterRecvDataState,
|
||||
kBroadcasterShutDownState
|
||||
};
|
||||
|
||||
MP3BroadcasterSession(QTSS_RTSPSessionObject sess, QTSS_StreamRef stream);
|
||||
|
||||
virtual ~MP3BroadcasterSession();
|
||||
|
||||
// The IsA() method is a mechanism for subclasses of the MP3Session class
|
||||
// to identify their type. It is kMP3BroadcasterSessionType for this
|
||||
// subclass.
|
||||
|
||||
virtual UInt8 IsA() const;
|
||||
|
||||
// Session state control methods
|
||||
|
||||
QTSS_Error ExecuteState();
|
||||
|
||||
void InitBroadcastSessionState();
|
||||
|
||||
void AcceptBroadcastSessionState();
|
||||
|
||||
void AcceptPasswordState();
|
||||
|
||||
void AcceptDataStreamState();
|
||||
|
||||
void ShutDownState();
|
||||
|
||||
// MP3 Client handling methods
|
||||
|
||||
QTSS_Error AddClient(QTSS_RTSPSessionObject sess, QTSS_StreamRef stream);
|
||||
|
||||
QTSS_Error RemoveClient(QTSS_RTSPSessionObject sess);
|
||||
|
||||
Bool16 IsMyClient(QTSS_RTSPSessionObject sess);
|
||||
|
||||
// Session data field accessor methods
|
||||
|
||||
void SetMountpoint(char* mp);
|
||||
|
||||
void SetMountpoint(StrPtrLen& mp);
|
||||
|
||||
Bool16 MountpointEqual(char* mp);
|
||||
|
||||
Bool16 MountpointEqual(StrPtrLen& mp);
|
||||
|
||||
char* GetMountpoint() { return fMountpoint; }
|
||||
|
||||
char* GetHeader() { return fHeader; }
|
||||
|
||||
void SetSongName(char* sn);
|
||||
|
||||
char* GetSongName() { return fSongName; }
|
||||
|
||||
// Session data handlers
|
||||
|
||||
QTSS_Error SendOKResponse();
|
||||
|
||||
QTSS_Error GetBroadcastHeaders();
|
||||
|
||||
QTSS_Error GetBroadcastData();
|
||||
|
||||
QTSS_Error SendClientsData();
|
||||
|
||||
void PreflightClients();
|
||||
|
||||
protected:
|
||||
|
||||
void TerminateHeaders();
|
||||
|
||||
private:
|
||||
|
||||
MP3BroadcasterSession();
|
||||
|
||||
MP3ClientQueue* fMP3ClientQueue;
|
||||
UInt32 fDataBufferLen;
|
||||
UInt32 fDataBufferSize;
|
||||
char fMountpoint[kURLBufferSize];
|
||||
char fHeader[kHeaderBufferSize];
|
||||
char fSongName[kSongNameBufferSize];
|
||||
char* fBuffer;
|
||||
OSMutex fSongNameMutex;
|
||||
Bool16 fNewSongName;
|
||||
};
|
||||
|
||||
//
|
||||
// MP3ClientSession -- This is a class to hold all the MP3 client
|
||||
// session-related state info. These class instances are always owned by a
|
||||
// instance of the MP3BroadcasterSession class which has a queue of these.
|
||||
//
|
||||
class MP3ClientSession : public MP3Session
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
// MP3ClientSession states
|
||||
|
||||
enum {
|
||||
kClientInitState = 0,
|
||||
kClientSendResponse,
|
||||
kClientSendDataState,
|
||||
kClientShutDownState
|
||||
};
|
||||
|
||||
MP3ClientSession(QTSS_RTSPSessionObject sess,
|
||||
QTSS_StreamRef stream,
|
||||
MP3BroadcasterSession* owner);
|
||||
|
||||
virtual ~MP3ClientSession();
|
||||
|
||||
// The IsA() method is a mechanism for subclasses of the MP3Session class
|
||||
// to identify their type. It is kMP3ClientSessionType for this subclass.
|
||||
|
||||
virtual UInt8 IsA() const;
|
||||
|
||||
// Session stream handlers
|
||||
|
||||
QTSS_Error SendResponse();
|
||||
|
||||
QTSS_Error SendMP3Data(char* buffer, UInt32 bufferlen);
|
||||
|
||||
QTSS_Error RetrySendData();
|
||||
|
||||
QTSS_Error SendMetaData();
|
||||
|
||||
// Session data field accessor methods
|
||||
|
||||
void SetHeader(char* header);
|
||||
|
||||
char* GetHeader() { return fHeader; }
|
||||
|
||||
char* GetHostName() { return fHostName; }
|
||||
|
||||
char* GetUserAgent() { return fUserAgent; }
|
||||
|
||||
void SetSongName(char* sn);
|
||||
|
||||
char* GetSongName() { return fSongName; }
|
||||
|
||||
MP3BroadcasterSession* GetOwner() { return fOwner; }
|
||||
|
||||
void SetOwner(MP3BroadcasterSession* owner) { fOwner = owner; }
|
||||
|
||||
Bool16 WasBlocked() { return fWasBlocked; }
|
||||
|
||||
Bool16 WantsContentLength() { return fNeedsContentLength; }
|
||||
|
||||
void SetRequest(char* req) { ::strcpy(fRequestBuffer, req); }
|
||||
|
||||
char* GetRequest() { return fRequestBuffer; }
|
||||
|
||||
UInt32 GetTotalCount() { return fBytesSent; }
|
||||
|
||||
SInt64 GetConnectTime() { return fConnectTime; }
|
||||
|
||||
private:
|
||||
|
||||
MP3ClientSession();
|
||||
|
||||
void UpdateBitRateInternal(const SInt64& curTime);
|
||||
|
||||
void ParseRequestParams(QTSS_StreamRef stream);
|
||||
|
||||
UInt32 fBytesSent;
|
||||
UInt32 fCurrentBitRate;
|
||||
UInt32 fLastBitRateBytes;
|
||||
SInt64 fLastBitRateUpdateTime;
|
||||
SInt64 fConnectTime;
|
||||
UInt32 fSendCount;
|
||||
UInt32 fRetryCount;
|
||||
MP3BroadcasterSession* fOwner;
|
||||
char fHeader[kHeaderBufferSize];
|
||||
char fHostName[kHostNameBufferSize];
|
||||
char fUserAgent[kUserAgentBufferSize];
|
||||
char fSongName[kSongNameBufferSize];
|
||||
OSMutex fSongNameMutex;
|
||||
Bool16 fNewSongName;
|
||||
Bool16 fWasBlocked;
|
||||
SInt64 fBlockTime;
|
||||
Bool16 fNeedsContentLength;
|
||||
Bool16 fWantsMetaData;
|
||||
char fRequestBuffer[kRequestBufferSize];
|
||||
QTSS_Object fQTSSObject;
|
||||
};
|
||||
|
||||
//
|
||||
// MP3SessionRef -- This class is just a wrapper class for handling the
|
||||
// mapping of RTSP Session refs to the corresponding MP3 Session class refs.
|
||||
// It will be the an element of our hash table in the MP3SessionTable class.
|
||||
//
|
||||
class MP3SessionRef
|
||||
{
|
||||
public:
|
||||
MP3SessionRef(MP3Session* mp3Session);
|
||||
|
||||
~MP3SessionRef();
|
||||
|
||||
private:
|
||||
|
||||
MP3Session* GetMP3Session() { return fMP3Session; }
|
||||
|
||||
QTSS_RTSPSessionObject GetSession() { return fMP3Session->GetSession(); }
|
||||
|
||||
MP3SessionRef* fNextHashEntry;
|
||||
PointerSizedInt fHashValue;
|
||||
MP3Session* fMP3Session;
|
||||
|
||||
friend class MP3SessionRefKey;
|
||||
friend class OSHashTable<MP3SessionRef, MP3SessionRefKey>;
|
||||
friend class OSHashTableIter<MP3SessionRef, MP3SessionRefKey>;
|
||||
friend class MP3SessionTable;
|
||||
};
|
||||
|
||||
//
|
||||
// MP3SessionRefKey -- This class is used to generate hash keys for looking
|
||||
// up values in our MP3SessionTable.
|
||||
//
|
||||
class MP3SessionRefKey
|
||||
{
|
||||
public:
|
||||
MP3SessionRefKey(MP3SessionRef* mp3SessRef);
|
||||
|
||||
MP3SessionRefKey(QTSS_RTSPSessionObject rtspSessRef);
|
||||
|
||||
~MP3SessionRefKey();
|
||||
|
||||
private:
|
||||
|
||||
PointerSizedInt GetHashKey() { return fHashValue; }
|
||||
|
||||
friend int operator ==(const MP3SessionRefKey &key1, const MP3SessionRefKey &key2)
|
||||
{
|
||||
return (key1.fHashValue == key2.fHashValue);
|
||||
}
|
||||
|
||||
MP3SessionRef* fKeyValue;
|
||||
PointerSizedInt fHashValue;
|
||||
MP3Session* fMP3Session;
|
||||
|
||||
friend class OSHashTable<MP3SessionRef, MP3SessionRefKey>;
|
||||
};
|
||||
|
||||
typedef OSHashTable<MP3SessionRef, MP3SessionRefKey> MP3SessRefHashTable;
|
||||
typedef OSHashTableIter<MP3SessionRef, MP3SessionRefKey> MP3SessRefHashTableIter;
|
||||
|
||||
//
|
||||
// MP3SessionTable -- This class provides a way to map RTSP Session references
|
||||
// into the corresponding MP3Session class instances if any.
|
||||
//
|
||||
class MP3SessionTable
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kDefaultTableSize = 19
|
||||
};
|
||||
|
||||
// tableSize is the number of hash buckets not the number of entries.
|
||||
|
||||
MP3SessionTable(UInt32 tableSize = kDefaultTableSize);
|
||||
|
||||
~MP3SessionTable();
|
||||
|
||||
UInt32 GetNumSessionsInTable() { return (UInt32) fTable.GetNumEntries(); }
|
||||
|
||||
// Attempt to add a new MP3Session ref to the table's map.
|
||||
// returns true on success or false if it fails.
|
||||
Bool16 RegisterSession(MP3Session* session);
|
||||
|
||||
// Given an QTSS_RTSPSessionObject resolve it into a MP3Session class
|
||||
// reference. Returns NULL if there's none in out map.
|
||||
MP3Session* Resolve(QTSS_RTSPSessionObject rtspSession);
|
||||
|
||||
// Attempt to remove a MP3Session ref from the table's map.
|
||||
// returns true on success or false if it fails.
|
||||
Bool16 UnRegisterSession(MP3Session* session);
|
||||
|
||||
private:
|
||||
|
||||
MP3SessRefHashTable fTable;
|
||||
OSMutex fMutex;
|
||||
};
|
||||
|
||||
//
|
||||
// MP3ClientQueue -- This is a class manages a queue of MP3Client objects.
|
||||
// Every MP3BroadcasterSession class instance contains one of these objects.
|
||||
//
|
||||
class MP3ClientQueue
|
||||
{
|
||||
public:
|
||||
|
||||
MP3ClientQueue();
|
||||
|
||||
~MP3ClientQueue();
|
||||
|
||||
UInt32 GetNumClients() { return fQueue.GetLength(); }
|
||||
|
||||
QTSS_Error AddClient(QTSS_RTSPSessionObject clientsess, QTSS_StreamRef clientstream,
|
||||
MP3BroadcasterSession* owner);
|
||||
|
||||
QTSS_Error RemoveClient(QTSS_RTSPSessionObject clientsess);
|
||||
|
||||
Bool16 InQueue(QTSS_RTSPSessionObject clientsess);
|
||||
|
||||
QTSS_Error SendToAllClients(char* buffer, UInt32 bufferlen);
|
||||
|
||||
void PreflightClients(char* songname);
|
||||
|
||||
private:
|
||||
|
||||
void TerminateClients();
|
||||
|
||||
OSMutex fMutex;
|
||||
OSQueue fQueue;
|
||||
};
|
||||
|
||||
//
|
||||
// MP3BroadcasterQueue -- This is a class manages a queue of MP3Broadcaster objects.
|
||||
// There is only one global instance of this class owned by the server.
|
||||
//
|
||||
class MP3BroadcasterQueue
|
||||
{
|
||||
public:
|
||||
|
||||
MP3BroadcasterQueue();
|
||||
|
||||
~MP3BroadcasterQueue();
|
||||
|
||||
UInt32 GetNumBroadcasters() { return fQueue.GetLength(); }
|
||||
|
||||
QTSS_Error CreateBroadcaster(QTSS_RTSPSessionObject bcastsess, QTSS_StreamRef bcaststream, StrPtrLen& mountpt);
|
||||
|
||||
QTSS_Error RemoveBroadcaster(QTSS_RTSPSessionObject bcastsess);
|
||||
|
||||
QTSS_Error RemoveClient(QTSS_RTSPSessionObject clientsess);
|
||||
|
||||
Bool16 InQueue(QTSS_RTSPSessionObject bcastsess);
|
||||
|
||||
Bool16 IsActiveClient(QTSS_RTSPSessionObject clientsess);
|
||||
|
||||
MP3BroadcasterSession* FindByMountPoint(char* mountpoint);
|
||||
|
||||
MP3BroadcasterSession* FindByMountPoint(StrPtrLen& mountpoint);
|
||||
|
||||
MP3BroadcasterSession* FindBySession(QTSS_RTSPSessionObject bcastsess);
|
||||
|
||||
void TerminateAllBroadcastSessions();
|
||||
|
||||
private:
|
||||
|
||||
OSMutex fMutex;
|
||||
OSQueue fQueue;
|
||||
};
|
||||
|
||||
#endif // __QTSSMP3STREAMINGMODULE_H__
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue