Index: configure.ac =================================================================== --- configure.ac (revision 11655) +++ configure.ac (working copy) @@ -3407,6 +3407,52 @@ fi dnl +dnl CyberLink for C++ UPnP stack +dnl +AC_ARG_ENABLE(cyberlink, + [ --enable-cyberlink CyberLink for C++ UPnP stack (default disabled)]) +if test "${CXX}" != "" -a "${enable_cyberlink}" = "yes" || (test "${enable_cyberlink}" != "no"); then + AC_ARG_WITH(cyberlink-tree, + [ --with-cyberlink-tree=PATH CyberLink for C++ tree for static linking]) + + dnl + dnl test for --with-cyberlink-tree + dnl + if test ! -z "${with_cyberlink_tree}" -a "${CXX}" != ""; then + AC_LANG_PUSH(C++) + real_cyberlink_tree="`cd ${with_cyberlink_tree} 2>/dev/null && pwd`" + if test -z "${real_cyberlink_tree}" + then + dnl The given directory can't be found + AC_MSG_RESULT(no) + AC_MSG_ERROR([cannot cd to ${with_cyberlink_tree}]) + fi + CXXFLAGS_save="${CXXFLAGS}" + CXXFLAGS_cyberlink="-I${real_cyberlink_tree}/include" + CXXFLAGS="${CXXFLAGS} ${CXXFLAGS_cyberlink}" + AC_MSG_CHECKING(for cybergarage/upnp/MediaServer.h in ${with_cyberlink_tree}) + AC_CHECK_HEADERS([cybergarage/upnp/MediaServer.h], + [ VLC_ADD_CXXFLAGS([wxwindows], [${CXXFLAGS_cyberlink}]) + VLC_ADD_PLUGINS([wxwindows]) + ],[ + AC_MSG_ERROR([cannot find CyberLink for C++ headers]) + ]) + AC_MSG_CHECKING(for libclink.a in ${with_cyberlink_tree}) + if test -f "${real_cyberlink_tree}/lib/unix/libclink.a" + then + AC_MSG_RESULT(${real_cyberlink_tree}/lib/unix/libclink.a) + VLC_ADD_LDFLAGS([wxwindows], [${real_cyberlink_tree}/lib/unix/libclink.a]) + else + AC_MSG_RESULT(no) + AC_MSG_ERROR([cannot find ${real_cyberlink_tree}/lib/unix/libclink.a, make sure you compiled CyberLink for C++ in ${with_cyberlink_tree}]) + fi + CXXFLAGS="${CXXFLAGS_save}" + AC_LANG_POP([C++]) + AC_DEFINE(ENABLE_CYBERLINK, 1, Define if you want CyberLink for C++ UPnP extension) + fi +fi + +dnl dnl Interface plugins dnl Index: modules/gui/wxwindows/interface.cpp =================================================================== --- modules/gui/wxwindows/interface.cpp (revision 11655) +++ modules/gui/wxwindows/interface.cpp (working copy) @@ -122,6 +122,7 @@ OpenFile_Event, OpenDir_Event, OpenDisc_Event, + OpenUPnP_Event, OpenNet_Event, OpenCapture_Event, OpenSat_Event, @@ -188,6 +189,7 @@ EVT_MENU(OpenFile_Event, Interface::OnShowDialog) EVT_MENU(OpenDir_Event, Interface::OnShowDialog) EVT_MENU(OpenDisc_Event, Interface::OnShowDialog) + EVT_MENU(OpenUPnP_Event, Interface::OnShowDialog) EVT_MENU(OpenNet_Event, Interface::OnShowDialog) EVT_MENU(OpenCapture_Event, Interface::OnShowDialog) EVT_MENU(OpenSat_Event, Interface::OnShowDialog) @@ -402,6 +404,8 @@ file_menu->Append( OpenFile_Event, wxU(_("Open &File...\tCtrl-F")) ); file_menu->Append( OpenDir_Event, wxU(_("Open Dir&ectory...\tCtrl-E")) ); file_menu->Append( OpenDisc_Event, wxU(_("Open &Disc...\tCtrl-D")) ); + file_menu->Append( OpenUPnP_Event, + wxU(_("Open &UPnP...\tCtrl-U")) ); file_menu->Append( OpenNet_Event, wxU(_("Open &Network Stream...\tCtrl-N")) ); file_menu->Append( OpenCapture_Event, @@ -886,6 +890,9 @@ case OpenDisc_Event: i_id = INTF_DIALOG_DISC; break; + case OpenUPnP_Event: + i_id = INTF_DIALOG_UPNP; + break; case OpenNet_Event: i_id = INTF_DIALOG_NET; break; Index: modules/gui/wxwindows/open.cpp =================================================================== --- modules/gui/wxwindows/open.cpp (revision 11655) +++ modules/gui/wxwindows/open.cpp (working copy) @@ -71,6 +71,15 @@ NetAddr1_Event, NetAddr2_Event, NetAddr3_Event, NetAddr4_Event, NetForceIPv6_Event, NetTimeshift_Event, +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (S) +//////////////////////////////////////////////////////////////////////// + UPnPContainer_Event, + UPnPItem_Event, +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (E) +//////////////////////////////////////////////////////////////////////// + SubsFileEnable_Event, SubsFileSettings_Event, @@ -124,6 +133,10 @@ EVT_CHECKBOX(NetForceIPv6_Event, OpenDialog::OnNetPanelChange) EVT_CHECKBOX(NetTimeshift_Event, OpenDialog::OnNetPanelChange) + /* Events generated by the UPnP Panel */ + EVT_TREE_SEL_CHANGED(UPnPContainer_Event, OpenDialog::OnUPnPContainerChange) + EVT_LISTBOX(UPnPItem_Event, OpenDialog::OnUPnPItemChange) + /* Events generated by the subtitle file buttons */ EVT_CHECKBOX(SubsFileEnable_Event, OpenDialog::OnSubsFileEnable) EVT_BUTTON(SubsFileSettings_Event, OpenDialog::OnSubsFileSettings) @@ -472,9 +485,18 @@ i_access_method == FILE_ACCESS ); notebook->AddPage( DiscPanel( notebook ), wxU(_("Disc")), i_access_method == DISC_ACCESS ); +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (S) +//////////////////////////////////////////////////////////////////////// + notebook->AddPage( UPnPPanel( notebook ), wxU(_("UPnP")), + i_access_method == UPNP_ACCESS ); +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (E) +//////////////////////////////////////////////////////////////////////// notebook->AddPage( NetPanel( notebook ), wxU(_("Network")), i_access_method == NET_ACCESS ); + module_t *p_module = config_FindModule( VLC_OBJECT(p_intf), "v4l" ); if( p_module ) { @@ -686,6 +708,53 @@ return panel; } +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (S) +//////////////////////////////////////////////////////////////////////// + +#include "upnp_media_server.h" + +wxPanel *OpenDialog::UPnPPanel( wxWindow* parent ) +{ + struct upnp_media_server_wxwidgets wxwidget_data; + + int panelWidth = 200; + int panelHeight = 220; + int treeWidth = 80; + int listWidth = panelWidth - treeWidth; + + wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition, + wxSize(panelWidth, panelHeight) ); + + wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL ); + + wxTreeCtrl *treeCtrl = new wxTreeCtrl( panel, UPnPContainer_Event, + wxDefaultPosition, + wxSize(treeWidth, panelHeight) ); + wxTreeItemId rootTreeID = treeCtrl->AddRoot(_("Media Server")); + sizer->Add( treeCtrl, 1, wxALL, 5 ); + + wxListBox *listBox = new wxListBox ( panel, UPnPItem_Event, + wxDefaultPosition, + wxSize(listWidth, panelHeight)); + sizer->Add( listBox, 1, wxALL, 5 ); + + panel->SetSizerAndFit( sizer ); + + wxwidget_data.treeRootItemId = rootTreeID; + wxwidget_data.treeCtrl = treeCtrl; + wxwidget_data.listBox = listBox; + + upnp_media_server_init(&wxwidget_data); + upnp_media_server_start(); + + return panel; +} + +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (E) +//////////////////////////////////////////////////////////////////////// + wxPanel *OpenDialog::NetPanel( wxWindow* parent ) { int i; @@ -1267,7 +1336,30 @@ UpdateMRL( DISC_ACCESS ); } + +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (S) +//////////////////////////////////////////////////////////////////////// /***************************************************************************** + * UPnP panel event methods. + *****************************************************************************/ +void OpenDialog::OnUPnPContainerChange( wxTreeEvent& event ) +{ + wxTreeItemId itemID = event.GetItem(); + upnp_media_server_container_selected(itemID); +} + +void OpenDialog::OnUPnPItemChange( wxCommandEvent& event ) +{ + int itemID = event.GetInt(); + upnp_media_server_item_selected(mrl_combo, itemID); +} +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (E) +//////////////////////////////////////////////////////////////////////// + + +/***************************************************************************** * Net panel event methods. *****************************************************************************/ void OpenDialog::OnNetPanelChangeSpin( wxSpinEvent& event ) Index: modules/gui/wxwindows/upnp_media_server.cpp =================================================================== --- modules/gui/wxwindows/upnp_media_server.cpp (revision 0) +++ modules/gui/wxwindows/upnp_media_server.cpp (revision 0) @@ -0,0 +1,317 @@ +/***************************************************************************** +* upnp_media_server.cpp : UPnP extention for VideoLAN. +***************************************************************************** +* Copyright (C) 2000, 2001 VideoLAN +* +* Authors: Satoshi Konno +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +*****************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "upnp_media_server.h" + +using namespace std; +using namespace CyberLink; +using namespace CyberUtil; + +/***************************************************************************** +* VLCMediaPlayer +*****************************************************************************/ + +class VLCMediaPlayer : public MediaPlayer, public NotifyListener, public EventListener, public SearchResponseListener, public wxEvtHandler +{ + vector devUSNList; + +public: + VLCMediaPlayer(); + +public: + void addDevice(string &usn); + void removeDevice(string &usn); + bool hasDevice(string &usn); + +public: + void deviceNotifyReceived(SSDPPacket *packet); + void deviceSearchResponseReceived(SSDPPacket *packet); + void eventNotifyReceived(const char *uuid, long seq, const char *name, const char *value); +}; + +/***************************************************************************** +* VLCMediaPlayer +*****************************************************************************/ + +class TreeContainerData : public wxTreeItemData +{ + ContainerNode *node; + +public: + TreeContainerData(ContainerNode *node) + { + this->node = node; + } + + ContainerNode *getNode() + { + return node; + } +}; + +/***************************************************************************** +* Global variables +*****************************************************************************/ + +wxTreeCtrl *upnp_media_server_tree_ctrl; +wxTreeItemId upnp_media_server_tree_root_id; +wxListBox *upnp_media_server_list_box; + +VLCMediaPlayer *mplayer = NULL; + +/***************************************************************************** +* update_upnp_media_server_widget_items +*****************************************************************************/ + +static void DebugMessage(const char *msg) +{ + Debug::on(); + Debug::message(msg, "/tmp/vlc-upnp.log"); +} + +void upnp_media_server_item_selected(wxComboBox *combo, int itemID) +{ + ItemNode *itemNode = (ItemNode *)upnp_media_server_list_box->GetClientData(itemID); + if (itemNode == NULL) + return; + + const char *res = itemNode->getResource(); + wxString wxRes(res); + combo->SetValue( wxRes ); +} + +void upnp_media_server_container_selected(wxTreeItemId &itemID) +{ + if (mplayer == NULL) + return; + + TreeContainerData *treeItemData = (TreeContainerData *)upnp_media_server_tree_ctrl->GetItemData(itemID); + if (treeItemData == NULL) + return; + + ContainerNode *conNode = treeItemData->getNode(); + if (conNode == NULL) + return; + + upnp_media_server_list_box->Clear(); + + int nContentNodes = conNode->getNContentNodes(); + for (int n=0; ngetContentNode(n); + if (cnode->isItemNode() == false) + continue; + ItemNode *itemNode = (ItemNode *)cnode; + const char *title = itemNode->getTitle(); + if (title == NULL) + continue; + wxString wxTitle(title); + upnp_media_server_list_box->Append(wxTitle, itemNode); + } +} + +void update_upnp_media_server_widget_content_items(ContentNode *node, wxTreeItemId parentTreeItemID) +{ + if (node->isContainerNode() == false) + return; + + ContainerNode *conNode = (ContainerNode *)node; + + const char *title = conNode->getTitle(); + if (title == NULL) + return; + + wxString wxTitle(title); + TreeContainerData *treeItemData = new TreeContainerData(conNode); + wxTreeItemId newTreeItemID = upnp_media_server_tree_ctrl->AppendItem(parentTreeItemID, wxTitle, -1, -1, treeItemData); + + if (node->hasContainerNodes() == false) + return; + + int nContentNodes = conNode->getNContentNodes(); + for (int n=0; ngetContentNode(n); + update_upnp_media_server_widget_content_items(cnode, newTreeItemID); + } +} + +void update_upnp_media_server_widget_items(VLCMediaPlayer *mplayer, SSDPPacket *packet) +{ + if (packet->isRootDevice() == false) + return; + + string usn; + string nts; + string nt; + packet->getUSN(usn); + packet->getNT(nt); + packet->getNTS(nts); + string udn = usn.substr(0, usn.find("::")); + + if (packet->isAlive() == true) { + if (mplayer->hasDevice(usn) == true) + return; + mplayer->addDevice(usn); + } + if (packet->isByeBye() == true) { + if (mplayer->hasDevice(usn) == false) + return; + mplayer->removeDevice(usn); + } + + Device *dev = mplayer->getDevice(udn.c_str()); + if (dev == NULL) + return; + if (dev->isDeviceType(MediaServer::DEVICE_TYPE) == false) + return; + + upnp_media_server_tree_ctrl->DeleteChildren(upnp_media_server_tree_root_id); + upnp_media_server_list_box->Clear(); + + DeviceList *devList = mplayer->getDeviceList(); + int devCnt = devList->size(); + for (int n=0; ngetDevice(n); + if (dev->isDeviceType(MediaServer::DEVICE_TYPE) == false) + continue; + const char *name = dev->getFriendlyName(); + if (name == NULL) + continue; + + wxString wxName(name); + wxTreeItemId newTreeItemID = upnp_media_server_tree_ctrl->AppendItem(upnp_media_server_tree_root_id, wxName, -1, -1, (wxTreeItemData *)NULL); + + ContentNode *cnode = mplayer->getContentDirectory(dev); + if (cnode == NULL) + continue; + update_upnp_media_server_widget_content_items(cnode, newTreeItemID); + } +} + + +/***************************************************************************** +* VLCMediaPlayer +*****************************************************************************/ + +VLCMediaPlayer::VLCMediaPlayer() +{ + addNotifyListener(this); + addSearchResponseListener(this); + addEventListener(this); +} + +void VLCMediaPlayer::addDevice(string &usn) +{ + devUSNList.push_back(usn); +} + +void VLCMediaPlayer::removeDevice(string &usn) +{ + int devCnt = devUSNList.size(); + for (int n=0; ntreeCtrl; + upnp_media_server_tree_root_id = wxwidget_data->treeRootItemId; + upnp_media_server_list_box = wxwidget_data->listBox; +} + +/***************************************************************************** +* upnp_media_server_start +*****************************************************************************/ + +void upnp_media_server_start() +{ + mplayer->stop(); + mplayer->start(); +} + +/***************************************************************************** +* upnp_media_server_quit +*****************************************************************************/ + +void upnp_media_server_quit() +{ + mplayer->stop(); + delete mplayer; +} + Index: modules/gui/wxwindows/upnp_media_server.h =================================================================== --- modules/gui/wxwindows/upnp_media_server.h (revision 0) +++ modules/gui/wxwindows/upnp_media_server.h (revision 0) @@ -0,0 +1,42 @@ +/***************************************************************************** +* upnp_media_server.h : UPnP extention for VideoLAN. +***************************************************************************** +* Copyright (C) 2000, 2001 VideoLAN +* +* Authors: Satoshi Konno +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +*****************************************************************************/ + +#ifndef WXWINDOWS_UPNP_MEDIA_SERVER_H +#define WXWINDOWS_UPNP_MEDIA_SERVER_H + +#include +#include +#include + +typedef struct upnp_media_server_wxwidgets { + wxTreeCtrl *treeCtrl; + wxTreeItemId treeRootItemId; + wxListBox *listBox; +} _upnp_media_server_wxwidgets; + +void upnp_media_server_init (void *arg); +void upnp_media_server_quit (); +void upnp_media_server_start (); +void upnp_media_server_container_selected(wxTreeItemId &itemID); +void upnp_media_server_item_selected(wxComboBox *combo, int itemID); + +#endif Index: modules/gui/wxwindows/wxwindows.h =================================================================== --- modules/gui/wxwindows/wxwindows.h (revision 11655) +++ modules/gui/wxwindows/wxwindows.h (working copy) @@ -390,6 +390,7 @@ void OnOpenDir( wxCommandEvent& event ); void OnOpenFile( wxCommandEvent& event ); void OnOpenDisc( wxCommandEvent& event ); + void OnOpenUPnP( wxCommandEvent& event ); void OnOpenNet( wxCommandEvent& event ); void OnOpenSat( wxCommandEvent& event ); @@ -460,6 +461,13 @@ private: wxPanel *FilePanel( wxWindow* parent ); wxPanel *DiscPanel( wxWindow* parent ); +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (S) +//////////////////////////////////////////////////////////////////////// + wxPanel *UPnPPanel( wxWindow* parent ); +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (E) +//////////////////////////////////////////////////////////////////////// wxPanel *NetPanel( wxWindow* parent ); ArrayOfAutoBuiltPanel input_tab_array; @@ -482,6 +490,16 @@ void OnDiscTypeChange( wxCommandEvent& event ); void OnDiscDeviceChange( wxCommandEvent& event ); +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (S) +//////////////////////////////////////////////////////////////////////// + /* Event handlers for UPnP Media Server */ + void OnUPnPContainerChange( wxTreeEvent& event ); + void OnUPnPItemChange( wxCommandEvent& event ); +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (E) +//////////////////////////////////////////////////////////////////////// + /* Event handlers for the net page */ void OnNetPanelChangeSpin( wxSpinEvent& event ); void OnNetPanelChange( wxCommandEvent& event ); @@ -566,8 +584,15 @@ { FILE_ACCESS = 0, DISC_ACCESS, +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (S) +//////////////////////////////////////////////////////////////////////// + UPNP_ACCESS, +//////////////////////////////////////////////////////////////////////// +// UPnP Media Server Extention (E) +//////////////////////////////////////////////////////////////////////// NET_ACCESS, - + /* Auto-built panels */ CAPTURE_ACCESS }; Index: modules/gui/wxwindows/dialogs.cpp =================================================================== --- modules/gui/wxwindows/dialogs.cpp (revision 11655) +++ modules/gui/wxwindows/dialogs.cpp (working copy) @@ -63,6 +63,7 @@ void OnOpenDirectory( wxCommandEvent& event ); void OnOpenFile( wxCommandEvent& event ); void OnOpenDisc( wxCommandEvent& event ); + void OnOpenUPnP( wxCommandEvent& event ); void OnOpenNet( wxCommandEvent& event ); void OnOpenCapture( wxCommandEvent& event ); void OnOpenSat( wxCommandEvent& event ); @@ -100,6 +101,7 @@ /* Custom wxDialog events */ EVT_COMMAND(INTF_DIALOG_FILE, wxEVT_DIALOG, DialogsProvider::OnOpenFile) EVT_COMMAND(INTF_DIALOG_DISC, wxEVT_DIALOG, DialogsProvider::OnOpenDisc) + EVT_COMMAND(INTF_DIALOG_UPNP, wxEVT_DIALOG, DialogsProvider::OnOpenUPnP) EVT_COMMAND(INTF_DIALOG_NET, wxEVT_DIALOG, DialogsProvider::OnOpenNet) EVT_COMMAND(INTF_DIALOG_CAPTURE, wxEVT_DIALOG, DialogsProvider::OnOpenCapture) @@ -446,6 +448,11 @@ Open( DISC_ACCESS, event.GetInt() ); } +void DialogsProvider::OnOpenUPnP( wxCommandEvent& event ) +{ + Open( UPNP_ACCESS, event.GetInt() ); +} + void DialogsProvider::OnOpenNet( wxCommandEvent& event ) { Open( NET_ACCESS, event.GetInt() ); Index: modules/gui/wxwindows/Modules.am =================================================================== --- modules/gui/wxwindows/Modules.am (revision 11655) +++ modules/gui/wxwindows/Modules.am (working copy) @@ -20,6 +20,8 @@ subtitles.cpp \ bookmarks.cpp \ video.cpp \ + upnp_media_server.cpp \ + upnp_media_server.h \ $(NULL) EXTRA_DIST += \ Index: include/vlc_interface.h =================================================================== --- include/vlc_interface.h (revision 11655) +++ include/vlc_interface.h (working copy) @@ -138,20 +138,21 @@ #define INTF_DIALOG_FILE_SIMPLE 1 #define INTF_DIALOG_FILE 2 #define INTF_DIALOG_DISC 3 -#define INTF_DIALOG_NET 4 -#define INTF_DIALOG_CAPTURE 5 -#define INTF_DIALOG_SAT 6 +#define INTF_DIALOG_UPNP 4 +#define INTF_DIALOG_NET 5 +#define INTF_DIALOG_CAPTURE 6 +#define INTF_DIALOG_SAT 7 -#define INTF_DIALOG_DIRECTORY 7 +#define INTF_DIALOG_DIRECTORY 8 -#define INTF_DIALOG_STREAMWIZARD 8 -#define INTF_DIALOG_WIZARD 9 +#define INTF_DIALOG_STREAMWIZARD 9 +#define INTF_DIALOG_WIZARD 10 -#define INTF_DIALOG_PLAYLIST 10 -#define INTF_DIALOG_MESSAGES 11 -#define INTF_DIALOG_FILEINFO 12 -#define INTF_DIALOG_PREFS 13 -#define INTF_DIALOG_BOOKMARKS 14 +#define INTF_DIALOG_PLAYLIST 11 +#define INTF_DIALOG_MESSAGES 12 +#define INTF_DIALOG_FILEINFO 13 +#define INTF_DIALOG_PREFS 14 +#define INTF_DIALOG_BOOKMARKS 15 #define INTF_DIALOG_POPUPMENU 20