4.项目成果:
此项目通过无线网络把手机和电脑连接起来后,可以将手机中的媒体内容投放到电脑 屏幕里。并且可以通过手机端的网易云音乐软件控制电脑端歌曲的播放,也可以通过 BubbleUpnp 软件控制电脑端 MP4 格式的视频播放。
5.主要代码部分
PltMediaRenderer.h
#ifndef _PLT_MEDIA_RENDERER_H_
#define _PLT_MEDIA_RENDERER_H_
/*----------------------------------------------------------------------
| includes
+---------------------------------------------------------------------*/
#include "PltDeviceHost.h"
#include
#include
#include
#include
extern int fifo_fd_to_mp;
extern int g_fifo_fd_from_mp;
extern int g_time;
extern pthread_mutex_t g_mutex;
extern char g_info[100];
/*----------------------------------------------------------------------
| PLT_MediaRendererDelegate
+---------------------------------------------------------------------*/
class PLT_MediaRendererDelegate
{
public:
virtual ~PLT_MediaRendererDelegate() {}
// ConnectionManager
virtual NPT_Result OnGetCurrentConnectionInfo(PLT_ActionReference& action) = 0;
// AVTransport
virtual NPT_Result OnNext(PLT_ActionReference& action) = 0;
virtual NPT_Result OnPause(PLT_ActionReference& action) = 0;
virtual NPT_Result OnPlay(PLT_ActionReference& action) = 0;
virtual NPT_Result OnPrevious(PLT_ActionReference& action) = 0;
virtual NPT_Result OnSeek(PLT_ActionReference& action) = 0;
virtual NPT_Result OnStop(PLT_ActionReference& action) = 0;
virtual NPT_Result OnSetAVTransportURI(PLT_ActionReference& action) = 0;
virtual NPT_Result OnSetPlayMode(PLT_ActionReference& action) = 0;
// RenderingControl
virtual NPT_Result OnSetVolume(PLT_ActionReference& action) = 0;
virtual NPT_Result OnSetVolumeDB(PLT_ActionReference& action) = 0;
virtual NPT_Result OnGetVolumeDBRange(PLT_ActionReference& action) = 0;
virtual NPT_Result OnSetMute(PLT_ActionReference& action) = 0;
};
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate
+---------------------------------------------------------------------*/
class My_PLT_MediaRendererDelegate:public PLT_MediaRendererDelegate
{
public:
friend class Thread1;
//歌曲播放状态
NPT_Result seek_flag;
NPT_Result play_flag;
//歌曲路径写入文件描述符
NPT_Result fd0;
NPT_Result fd;
NPT_Result cur_vol;
NPT_Result song_change;
My_PLT_MediaRendererDelegate();
~My_PLT_MediaRendererDelegate();
//自定义
int get_play_flag(){
return play_flag;
}
NPT_Result SndCmd(char *cmd,int len);
// ConnectionManager
virtual NPT_Result OnGetCurrentConnectionInfo(PLT_ActionReference& action);
// AVTransport
virtual NPT_Result OnNext(PLT_ActionReference& action);
virtual NPT_Result OnPause(PLT_ActionReference& action);
virtual NPT_Result OnPlay(PLT_ActionReference& action);
virtual NPT_Result OnPrevious(PLT_ActionReference& action);
virtual NPT_Result OnSeek(PLT_ActionReference& action);
virtual NPT_Result OnStop(PLT_ActionReference& action);
virtual NPT_Result OnSetAVTransportURI(PLT_ActionReference& action);
virtual NPT_Result OnSetPlayMode(PLT_ActionReference& action);
// RenderingControl
virtual NPT_Result OnSetVolume(PLT_ActionReference& action);
virtual NPT_Result OnSetVolumeDB(PLT_ActionReference& action);
virtual NPT_Result OnGetVolumeDBRange(PLT_ActionReference& action);
virtual NPT_Result OnSetMute(PLT_ActionReference& action);
};
class ThreadSnd : public NPT_Thread
{
public:
void Run(void);
//void TSndCmd(My_PLT_MediaRendererDelegate &, char *, int);
};
class ThreadRcv : public NPT_Thread
{
public:
void Run(void);
};
/*----------------------------------------------------------------------
| PLT_MediaRenderer
+---------------------------------------------------------------------*/
class PLT_MediaRenderer : public PLT_DeviceHost
{
public:
PLT_MediaRenderer(const char* friendly_name,
bool show_ip = false,
const char* uuid = NULL,
unsigned int port = 0,
bool port_rebind = false);
// methods
virtual void SetDelegate(PLT_MediaRendererDelegate* delegate) { m_Delegate = delegate; }
// PLT_DeviceHost methods
virtual NPT_Result SetupServices();
virtual NPT_Result OnAction(PLT_ActionReference& action,
const PLT_HttpRequestContext& context);
protected:
virtual ~PLT_MediaRenderer();
// PLT_MediaRendererInterface methods
// ConnectionManager
virtual NPT_Result OnGetCurrentConnectionInfo(PLT_ActionReference& action);
// AVTransport
virtual NPT_Result OnNext(PLT_ActionReference& action);
virtual NPT_Result OnPause(PLT_ActionReference& action);
virtual NPT_Result OnPlay(PLT_ActionReference& action);
virtual NPT_Result OnPrevious(PLT_ActionReference& action);
virtual NPT_Result OnSeek(PLT_ActionReference& action);
virtual NPT_Result OnStop(PLT_ActionReference& action);
virtual NPT_Result OnSetAVTransportURI(PLT_ActionReference& action);
virtual NPT_Result OnSetPlayMode(PLT_ActionReference& action);
// RenderingControl
virtual NPT_Result OnSetVolume(PLT_ActionReference& action);
virtual NPT_Result OnSetVolumeDB(PLT_ActionReference &action);
virtual NPT_Result OnGetVolumeDBRange(PLT_ActionReference &action);
virtual NPT_Result OnSetMute(PLT_ActionReference& action);
private:
PLT_MediaRendererDelegate* m_Delegate;
};
#endif /* _PLT_MEDIA_RENDERER_H_ */
PltMediaRenderer.cpp
/*----------------------------------------------------------------------
| includes
+---------------------------------------------------------------------*/
#include "Neptune.h"
#include "PltMediaRenderer.h"
#include "PltService.h"
#include
#include
#include
#include
#include
#include
int fifo_fd_to_mp; //控制Mplayer管道
int g_fifo_fd_from_mp ; //接受Mplayer信息管道
int g_time=0; //歌曲播放时间
int g_time_all=0; //歌曲长度
char g_info[100];
char g_info_all[100];
int song_len=1; //输出歌曲长度一次标志位
pthread_mutex_t g_mutex;
My_PLT_MediaRendererDelegate *my_Delegate;
NPT_SET_LOCAL_LOGGER("platinum.media.renderer")
/*----------------------------------------------------------------------
| external references
+---------------------------------------------------------------------*/
extern NPT_UInt8 RDR_ConnectionManagerSCPD[];
extern NPT_UInt8 RDR_AVTransportSCPD[];
extern NPT_UInt8 RDR_RenderingControlSCPD[];
/*----------------------------------------------------------------------
| PLT_MediaRenderer::PLT_MediaRenderer
+---------------------------------------------------------------------*/
PLT_MediaRenderer::PLT_MediaRenderer(const char* friendly_name,
bool show_ip /* = false */,
const char* uuid /* = NULL */,
unsigned int port /* = 0 */,
bool port_rebind /* = false */) :
PLT_DeviceHost("/",
uuid,
"urn:schemas-upnp-org:device:MediaRenderer:1",
friendly_name,
show_ip,
port,
port_rebind),
m_Delegate(NULL)
{
m_ModelDescription = "Plutinosoft AV Media Renderer Device";
m_ModelName = "AV Renderer Device";
m_ModelURL = "http://www.plutinosoft.com/platinum";
m_DlnaDoc = "DMR-1.50";
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::~PLT_MediaRenderer
+---------------------------------------------------------------------*/
PLT_MediaRenderer::~PLT_MediaRenderer()
{
}
void TSndCmd(My_PLT_MediaRendererDelegate &x,char *cmd ,int len)
{
x.SndCmd(cmd,len);
}
void ThreadRcv::Run(void)
{
while(1)
{
usleep(500*1000);
char buff[1024] = "";
char *p = NULL;
int position_time=0;
read(g_fifo_fd_from_mp,buff,sizeof(buff));
position_time = g_time;
if((p = strstr(buff,"ANS_TIME_POSITION="))!=NULL)
{
sscanf(p,"ANS_TIME_POSITION=%d",&g_time);
if(position_time != g_time)
{
pthread_mutex_lock(&g_mutex);
sprintf(g_info,"%02d:%02d:%02d",g_time/60/60,g_time/60%60,g_time%60);
pthread_mutex_unlock(&g_mutex);
//printf("-%s--%s----------now song position --> %s\n",__FILE__,__FUNCTION__,g_info);
}
p = NULL;
}
if(((p = strstr(buff,"ANS_LENGTH="))!=NULL) && (song_len==1))
{
//printf("------------------------------------------------recvMpl\n");
sscanf(p,"ANS_LENGTH=%d",&g_time_all);
pthread_mutex_lock(&g_mutex);
sprintf(g_info_all,"%02d:%02d:%02d",g_time_all/60/60,g_time_all/60%60,g_time_all%60);
//printf("---------------now---song length-------------------> %s\n\t************************************\n",g_info_all);
pthread_mutex_unlock(&g_mutex);
song_len=0;
}
}
}
void ThreadSnd:: Run(void)
{
while(1)
{
if(song_len==1)
{
TSndCmd(*my_Delegate,"get_time_length\n",strlen("get_time_length\n"));
}
usleep(500*1000);
if(my_Delegate->get_play_flag()==1)
{
TSndCmd(*my_Delegate,"get_time_pos\n",strlen("get_time_pos\n"));
}
}
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::SetupServices
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::SetupServices()
{
my_Delegate = new My_PLT_MediaRendererDelegate();
this->SetDelegate(my_Delegate);
NPT_Thread *threadSnd = new ThreadSnd();
threadSnd->Start();
NPT_Thread *threadRcv = new ThreadRcv();
threadRcv->Start();
NPT_Reference service;
{
/* AVTransport */
service = new PLT_Service(
this,
"urn:schemas-upnp-org:service:AVTransport:1",
"urn:upnp-org:serviceId:AVTransport",
"AVTransport",
"urn:schemas-upnp-org:metadata-1-0/AVT/");
NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_AVTransportSCPD));
NPT_CHECK_FATAL(AddService(service.AsPointer()));
service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f));
service->SetStateVariable("A_ARG_TYPE_InstanceID", "0");
// GetCurrentTransportActions
service->SetStateVariable("CurrentTransportActions", "Play,Pause,Stop,Seek,Next,Previous");
// GetDeviceCapabilities
service->SetStateVariable("PossiblePlaybackStorageMedia", "NONE,NETWORK,HDD,CD-DA,UNKNOWN");
service->SetStateVariable("PossibleRecordStorageMedia", "NOT_IMPLEMENTED");
service->SetStateVariable("PossibleRecordQualityModes", "NOT_IMPLEMENTED");
// GetMediaInfo
service->SetStateVariable("NumberOfTracks", "0");
service->SetStateVariable("CurrentMediaDuration", "00:00:00");
service->SetStateVariable("AVTransportURI", "");
service->SetStateVariable("AVTransportURIMetadata", "");;
service->SetStateVariable("NextAVTransportURI", "NOT_IMPLEMENTED");
service->SetStateVariable("NextAVTransportURIMetadata", "NOT_IMPLEMENTED");
service->SetStateVariable("PlaybackStorageMedium", "NONE");
service->SetStateVariable("RecordStorageMedium", "NOT_IMPLEMENTED");
service->SetStateVariable("RecordMediumWriteStatus", "NOT_IMPLEMENTED");
// GetPositionInfo
service->SetStateVariable("CurrentTrack", "0");
service->SetStateVariable("CurrentTrackDuration", "00:00:00");
service->SetStateVariable("CurrentTrackMetadata", "");
service->SetStateVariable("CurrentTrackURI", "");
service->SetStateVariable("RelativeTimePosition", "00:00:00");
service->SetStateVariable("AbsoluteTimePosition", "00:00:00");
service->SetStateVariable("RelativeCounterPosition", "2147483647"); // means NOT_IMPLEMENTED
service->SetStateVariable("AbsoluteCounterPosition", "2147483647"); // means NOT_IMPLEMENTED
// disable indirect eventing for certain state variables
PLT_StateVariable* var;
var = service->FindStateVariable("RelativeTimePosition");
if (var) var->DisableIndirectEventing();
var = service->FindStateVariable("AbsoluteTimePosition");
if (var) var->DisableIndirectEventing();
var = service->FindStateVariable("RelativeCounterPosition");
if (var) var->DisableIndirectEventing();
var = service->FindStateVariable("AbsoluteCounterPosition");
if (var) var->DisableIndirectEventing();
// GetTransportInfo
service->SetStateVariable("TransportState", "NO_MEDIA_PRESENT");
service->SetStateVariable("TransportStatus", "OK");
service->SetStateVariable("TransportPlaySpeed", "1");
// GetTransportSettings
service->SetStateVariable("CurrentPlayMode", "NORMAL");
service->SetStateVariable("CurrentRecordQualityMode", "NOT_IMPLEMENTED");
service.Detach();
service = NULL;
}
{
/* ConnectionManager */
service = new PLT_Service(
this,
"urn:schemas-upnp-org:service:ConnectionManager:1",
"urn:upnp-org:serviceId:ConnectionManager",
"ConnectionManager");
NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_ConnectionManagerSCPD));
NPT_CHECK_FATAL(AddService(service.AsPointer()));
service->SetStateVariable("CurrentConnectionIDs", "0");
// put all supported mime types here instead
service->SetStateVariable("SinkProtocolInfo", "http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO,http-get:*:video/x-ms-asf:DLNA.ORG_PN=MPEG4_P2_ASF_SP_G726,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMDRM_WMABASE,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVSPLL_BASE,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC_XAC3,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMDRM_WMVSPLL_BASE,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVSPML_BASE,http-get:*:video/x-ms-asf:DLNA.ORG_PN=MPEG4_P2_ASF_ASP_L5_SO_G726,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL_XAC3,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAPRO,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN,http-get:*:video/x-ms-asf:DLNA.ORG_PN=MPEG4_P2_ASF_ASP_L4_SO_G726,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3X,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVSPML_MP3,http-get:*:video/x-ms-wmv:*");
service->SetStateVariable("SourceProtocolInfo", "");
service.Detach();
service = NULL;
}
{
/* RenderingControl */
service = new PLT_Service(
this,
"urn:schemas-upnp-org:service:RenderingControl:1",
"urn:upnp-org:serviceId:RenderingControl",
"RenderingControl",
"urn:schemas-upnp-org:metadata-1-0/RCS/");
NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_RenderingControlSCPD));
NPT_CHECK_FATAL(AddService(service.AsPointer()));
service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f));
service->SetStateVariable("Mute", "0");
service->SetStateVariableExtraAttribute("Mute", "Channel", "Master");
service->SetStateVariable("Volume", "100");
service->SetStateVariableExtraAttribute("Volume", "Channel", "Master");
service->SetStateVariable("VolumeDB", "0");
service->SetStateVariableExtraAttribute("VolumeDB", "Channel", "Master");
service->SetStateVariable("PresetNameList", "FactoryDefaults");
service.Detach();
service = NULL;
}
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnAction
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnAction(PLT_ActionReference& action,
const PLT_HttpRequestContext& context)
{
NPT_COMPILER_UNUSED(context);
PLT_Service *service = action->GetActionDesc().GetService();
/* parse the action name */
NPT_String name = action->GetActionDesc().GetName();
// since all actions take an instance ID and we only support 1 instance
// verify that the Instance ID is 0 and return an error here now if not
NPT_String serviceType = action->GetActionDesc().GetService()->GetServiceType();
if (serviceType.Compare("urn:schemas-upnp-org:service:AVTransport:1", true) == 0) {
if (NPT_FAILED(action->VerifyArgumentValue("InstanceID", "0"))) {
action->SetError(718, "Not valid InstanceID");
return NPT_FAILURE;
}
}
serviceType = action->GetActionDesc().GetService()->GetServiceType();
if (serviceType.Compare("urn:schemas-upnp-org:service:RenderingControl:1", true) == 0) {
if (NPT_FAILED(action->VerifyArgumentValue("InstanceID", "0"))) {
action->SetError(702, "Not valid InstanceID");
return NPT_FAILURE;
}
}
/* Is it a ConnectionManager Service Action ? */
if (name.Compare("GetCurrentConnectionInfo", true) == 0) {
return OnGetCurrentConnectionInfo(action);
}
/* Is it a AVTransport Service Action ? */
if (name.Compare("Next", true) == 0) {
return OnNext(action);
}
if (name.Compare("Pause", true) == 0) {
return OnPause(action);
}
if (name.Compare("Play", true) == 0) {
return OnPlay(action);
}
if (name.Compare("Previous", true) == 0) {
return OnPrevious(action);
}
if (name.Compare("Seek", true) == 0) {
return OnSeek(action);
}
if (name.Compare("Stop", true) == 0) {
return OnStop(action);
}
if (name.Compare("SetAVTransportURI", true) == 0) {
return OnSetAVTransportURI(action);
}
if (name.Compare("SetPlayMode", true) == 0) {
return OnSetPlayMode(action);
}
/* Is it a RendererControl Service Action ? */
if (name.Compare("SetVolume", true) == 0) {
return OnSetVolume(action);
}
//设置默认音量 反馈到手机
if (name.Compare("GetVolume", true) == 0) {
char vol[10] = "";
sprintf(vol,"%d",my_Delegate->cur_vol);
service->SetStateVariable("Volume", vol);
}
if (name.Compare("SetVolumeDB", true) == 0) {
return OnSetVolumeDB(action);
}
if (name.Compare("GetVolumeDBRange", true) == 0) {
return OnGetVolumeDBRange(action);
}
if (name.Compare("SetMute", true) == 0) {
return OnSetMute(action);
}
//同步播放进度
if(my_Delegate->seek_flag == 1){
my_Delegate->seek_flag = 0;
}
else{
pthread_mutex_lock(&g_mutex);
service->SetStateVariable("RelativeTimePosition",g_info);
service->SetStateVariable("AbsoluteTimePosition",g_info);
pthread_mutex_unlock(&g_mutex);
}
//if(g_time == g_time_all && g_time_all != 0){
//my_Delegate->OnNext(action);
//}
// other actions rely on state variables
NPT_CHECK_LABEL_WARNING(action->SetArgumentsOutFromStateVariable(), failure);
return NPT_SUCCESS;
failure:
action->SetError(401,"No Such Action.");
return NPT_FAILURE;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnGetCurrentConnectionInfo
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnGetCurrentConnectionInfo(PLT_ActionReference& action)
{
if (m_Delegate) {
return m_Delegate->OnGetCurrentConnectionInfo(action);
}
if (NPT_FAILED(action->VerifyArgumentValue("ConnectionID", "0"))) {
action->SetError(706,"No Such Connection.");
return NPT_FAILURE;
}
if (NPT_FAILED(action->SetArgumentValue("RcsID", "0"))){
return NPT_FAILURE;
}
if (NPT_FAILED(action->SetArgumentValue("AVTransportID", "0"))) {
return NPT_FAILURE;
}
if (NPT_FAILED(action->SetArgumentOutFromStateVariable("ProtocolInfo"))) {
return NPT_FAILURE;
}
if (NPT_FAILED(action->SetArgumentValue("PeerConnectionManager", "/"))) {
return NPT_FAILURE;
}
if (NPT_FAILED(action->SetArgumentValue("PeerConnectionID", "-1"))) {
return NPT_FAILURE;
}
if (NPT_FAILED(action->SetArgumentValue("Direction", "Input"))) {
return NPT_FAILURE;
}
if (NPT_FAILED(action->SetArgumentValue("Status", "Unknown"))) {
return NPT_FAILURE;
}
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnNext
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnNext(PLT_ActionReference& action)
{
if (m_Delegate) {
return m_Delegate->OnNext(action);
}
return NPT_ERROR_NOT_IMPLEMENTED;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnPause
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnPause(PLT_ActionReference& action)
{
if (m_Delegate) {
return m_Delegate->OnPause(action);
}
return NPT_ERROR_NOT_IMPLEMENTED;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnPlay
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnPlay(PLT_ActionReference& action)
{
if (m_Delegate) {
return m_Delegate->OnPlay(action);
}
return NPT_ERROR_NOT_IMPLEMENTED;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnPrevious
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnPrevious(PLT_ActionReference& action)
{
if (m_Delegate) {
return m_Delegate->OnPrevious(action);
}
return NPT_ERROR_NOT_IMPLEMENTED;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnSeek
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnSeek(PLT_ActionReference& action)
{
if (m_Delegate) {
return m_Delegate->OnSeek(action);
}
return NPT_ERROR_NOT_IMPLEMENTED;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnStop
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnStop(PLT_ActionReference& action)
{
if (m_Delegate) {
return m_Delegate->OnStop(action);
}
return NPT_ERROR_NOT_IMPLEMENTED;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnSetAVTransportURI
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnSetAVTransportURI(PLT_ActionReference& action)
{
// default implementation is using state variable
NPT_String uri;
NPT_CHECK_WARNING(action->GetArgumentValue("CurrentURI", uri));
NPT_String metadata;
NPT_CHECK_WARNING(action->GetArgumentValue("CurrentURIMetaData", metadata));
PLT_Service* serviceAVT;
NPT_CHECK_WARNING(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", serviceAVT));
// update service state variables
serviceAVT->SetStateVariable("AVTransportURI", uri);
serviceAVT->SetStateVariable("AVTransportURIMetaData", metadata);
if (m_Delegate) {
return m_Delegate->OnSetAVTransportURI(action);
}
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnSetPlayMode
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnSetPlayMode(PLT_ActionReference& action)
{
if (m_Delegate) {
return m_Delegate->OnSetPlayMode(action);
}
return NPT_ERROR_NOT_IMPLEMENTED;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnSetVolume
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnSetVolume(PLT_ActionReference& action)
{
if (m_Delegate) {
return m_Delegate->OnSetVolume(action);
}
return NPT_ERROR_NOT_IMPLEMENTED;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnSetVolumeDB
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnSetVolumeDB(PLT_ActionReference& action)
{
if (m_Delegate) {
return m_Delegate->OnSetVolumeDB(action);
}
return NPT_ERROR_NOT_IMPLEMENTED;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnGetVolumeDBRange
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnGetVolumeDBRange(PLT_ActionReference& action)
{
if (m_Delegate) {
return m_Delegate->OnGetVolumeDBRange(action);
}
return NPT_ERROR_NOT_IMPLEMENTED;
}
/*----------------------------------------------------------------------
| PLT_MediaRenderer::OnSetMute
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaRenderer::OnSetMute(PLT_ActionReference& action)
{
if (m_Delegate) {
return m_Delegate->OnSetMute(action);
}
return NPT_ERROR_NOT_IMPLEMENTED;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::My_PLT_MediaRendererDelegate
+---------------------------------------------------------------------*/
My_PLT_MediaRendererDelegate::My_PLT_MediaRendererDelegate()
{
pthread_mutex_init(&g_mutex,NULL);
fifo_fd_to_mp = open("./contrMpl",O_RDWR);
cur_vol = 30;
play_flag = 0;
seek_flag = 0;
song_change= 1;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::~My_PLT_MediaRendererDelegate
+---------------------------------------------------------------------*/
My_PLT_MediaRendererDelegate::~My_PLT_MediaRendererDelegate()
{
pthread_mutex_destroy(&g_mutex);
close(fifo_fd_to_mp);
close(g_fifo_fd_from_mp);
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::SndCmd
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::SndCmd(char *cmd,int len)
{
pthread_mutex_lock(&g_mutex);
write(fifo_fd_to_mp,cmd,len);
pthread_mutex_unlock(&g_mutex);
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::OnGetCurrentConnectionInfo
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::OnGetCurrentConnectionInfo(PLT_ActionReference& action)
{
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::OnPlay
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::OnPlay(PLT_ActionReference& action)
{
play_flag = 1;
char read_buf[1024] = "";
//PLT_Service *service = action->GetActionDesc().GetService();
if(song_change==1)
{
//获取歌曲名称
PLT_Service *service = action->GetActionDesc().GetService();
NPT_String uri;
//读歌曲状态路径变量
service->GetStateVariableValue("AVTransportURI", uri);
//歌曲路径写入、播放
sprintf(read_buf,"loadfile %s\n",(char*)uri);
//printf("--->uri=%s\n",(char *)uri);
SndCmd(read_buf,strlen(read_buf));
//printf("len=%d\n",len);
action->GetActionDesc().GetService()->SetStateVariable("RelativeTimePosition","00:00:00");
action->GetActionDesc().GetService()->SetStateVariable("AbsoluteTimePosition","00:00:00");
//歌曲播放状态变化
song_change=0;
//状态信息反馈
service->SetStateVariable("TransportState", "PLAYING");
service->SetStateVariable("TransportStatus", "OK");
//设置正常音量
bzero(read_buf,sizeof(read_buf));
sprintf(read_buf,"volume %d 1\n",my_Delegate->cur_vol);
SndCmd(read_buf,strlen(read_buf));
//printf("--------------------------------------------this is onplay\n");
}
else
{
SndCmd("pause\n",strlen("pause\n"));
//usleep(1000);
sprintf(read_buf,"volume %d 1\n",my_Delegate->cur_vol);
SndCmd(read_buf,strlen(read_buf));
//printf("*****************************************this is open pause\n");
}
//状态信息反馈
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::OnNext
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::OnNext(PLT_ActionReference& action)
{
//song_len = 1;
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::OnPause
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::OnPause(PLT_ActionReference& action)
{
PLT_Service *service = action->GetActionDesc().GetService();
SndCmd("pause\n",strlen("pause\n"));
//反馈信息
service->SetStateVariable("TransportState", "PAUSED_PLAYBACK");
service->SetStateVariable("TransportStatus", "OK");
play_flag=0;
//printf("--------------------------------------------this is OnPause\n");
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::OnPrevious
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::OnPrevious(PLT_ActionReference& action)
{
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::OnSeek
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::OnSeek(PLT_ActionReference& action)
{
int seek_time_h =0, seek_time_m = 0,seek_time_s = 0;
int seek_pos = 0;
seek_flag = 1;
PLT_Service *service = action->GetActionDesc().GetService();
NPT_String seek;
action->GetArgumentValue("Target",seek);
sscanf((char *)seek,"%02d:%02d:%02d",&seek_time_h,&seek_time_m,&seek_time_s);
seek_pos = (seek_time_h * 60 *60+seek_time_m *60+seek_time_s);
int offset = seek_pos - g_time;
char cmd[256]="";
service->SetStateVariable("RelativeTimePosition",(char *)seek);
service->SetStateVariable("AbsoluteTimePosition",(char *)seek);
sprintf(cmd,"seek %d\n",offset);
SndCmd(cmd,strlen(cmd));
//usleep(300*1000);
bzero(cmd,sizeof(cmd));
sprintf(cmd,"volume %d 1\n ",my_Delegate->cur_vol);
SndCmd(cmd,strlen(cmd));
play_flag = 1;
service->SetStateVariable("TransportState","PLAYING");
service->SetStateVariable("TransportStatus","OK");
//printf("--------------------------------------------this is OnSeek\n");
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::OnStop
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::OnStop(PLT_ActionReference& action)
{
PLT_Service *service = action->GetActionDesc().GetService();
SndCmd("pause\n",strlen("pause\n"));
play_flag = 0;
//反馈信息
service->SetStateVariable("TransportState", "STOPPED");
service->SetStateVariable("TransportStatus", "OK");
song_change = 1;
//printf("--------------------------------------------this is OnStop\n");
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::OnSetAVTransportURI
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::OnSetAVTransportURI(PLT_ActionReference& action)
{
play_flag=1;
song_change=1;
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::OnSetPlayMode
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::OnSetPlayMode(PLT_ActionReference& action)
{
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::OnSetVolume
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::OnSetVolume(PLT_ActionReference& action)
{
NPT_String vol;
action->GetArgumentValue("DesiredVolume",vol);
//printf("----%s--%s------>volume=%s\n",__FILE__,__FUNCTION__,(char *)vol);
sscanf((char*)vol,"%d",&(my_Delegate->cur_vol));
char cmd[128]="";
int len=sprintf(cmd,"volume %d 1\n",my_Delegate->cur_vol);
SndCmd(cmd,len);
if(play_flag == 0)
SndCmd("pause\n",strlen("pause\n"));
//usleep(1000*1000);
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::OnSetVolumeDB
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::OnSetVolumeDB(PLT_ActionReference& action)
{
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::OnGetVolumeDBRange
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::OnGetVolumeDBRange(PLT_ActionReference& action)
{
return NPT_SUCCESS;
}
/*----------------------------------------------------------------------
| My_PLT_MediaRendererDelegate::OnSetMute
+---------------------------------------------------------------------*/
NPT_Result My_PLT_MediaRendererDelegate::OnSetMute(PLT_ActionReference& action)
{
return NPT_SUCCESS;
}
MediaRendererTest.cpp
/*----------------------------------------------------------------------
| includes
+---------------------------------------------------------------------*/
#include "PltUPnP.h"
#include "PltMediaRenderer.h"
#include
#include
#include
#include
#include
/*----------------------------------------------------------------------
| globals
+---------------------------------------------------------------------*/
struct Options {
const char* friendly_name;
} Options;
/*----------------------------------------------------------------------
| PrintUsageAndExit
+---------------------------------------------------------------------*/
static void
PrintUsageAndExit(char** args)
{
fprintf(stderr, "usage: %s [-f ]\n", args[0]);
fprintf(stderr, "-f : optional upnp server friendly name\n");
fprintf(stderr, " : local path to serve\n");
exit(1);
}
/*----------------------------------------------------------------------
| ParseCommandLine
+---------------------------------------------------------------------*/
static void
ParseCommandLine(char** args)
{
const char* arg;
char** tmp = args+1;
/* default values */
Options.friendly_name = NULL;
while ((arg = *tmp++)) {
if (!strcmp(arg, "-f")) {
Options.friendly_name = *tmp++;
} else {
fprintf(stderr, "ERROR: too many arguments\n");
PrintUsageAndExit(args);
}
}
}
/*----------------------------------------------------------------------
| main
+---------------------------------------------------------------------*/
int
main(int /* argc */, char** argv)
{
//创建命名管道 负责发送控制消息和读取返回信息
mkfifo("./contrMpl",0666);
mkfifo("./readMpl",0666);
g_fifo_fd_from_mp = open("./readMpl",O_RDWR);
//创建子进程启动mplayer
pid_t pid = fork();
if(pid < 0 ){
perror("fork");
exit(-1);
}
else if(pid == 0){
//重定向标准输出
dup2(g_fifo_fd_from_mp,1);
execlp("mplayer","mplayer_arm", "-slave","-idle", "-quiet","-input","file=./contrMpl",NULL);
perror("execl");
_exit(1);
}
PLT_UPnP upnp;
/* parse command line */
ParseCommandLine(argv);
PLT_DeviceHostReference device(
new PLT_MediaRenderer(Options.friendly_name?Options.friendly_name:"Platinum Media Renderer",
false,
"e6572b54-f3c7-2d91-2fb5-b757f2537e21"));
upnp.AddDevice(device);
bool added = true;
upnp.Start();
char buf[256];
while (gets(buf)) {
if (*buf == 'q')
break;
if (*buf == 's') {
if (added) {
upnp.RemoveDevice(device);
} else {
upnp.AddDevice(device);
}
added = !added;
}
}
upnp.Stop();
return 0;
}