Direct的一个Online LiveTV项目

很赞!!!

link:  http://www.codeproject.com/KB/audio-video/TVToolbar.aspx

TV Toolbar Plays TV Shows - Internet Television Has Arrived - Part I

Introduction

I wrote the first TV Toolbar that played video in any browser back in 1997 and I have created many versions of my TV Toolbar every year since then for both Internet Explorer and all the Mozilla Browsers like FireFox. Back in 1997, the TV Toolbar played video in any window by grabbing the handle to that window and playing recorded files using DirectShow. As time went by, more and more TV stations and independent producers began to stream their TV shows from video servers all over the world and I began using VLC to play live TV shows from streaming servers and web cams.

I started to write one article that included both the code for the TV Toolbar and the code for a VLC wrapper in C++ to play video streams but I quickly realized that the article would be too large so I decided to divide the article into 2 Parts, namely, Part I, dealing with creating just the TV Toolbar in Visual Studio 2008 and Part II, adding the code to the TV Toolbar for playing video from the many sources of TV shows that are now live on the Internet using a C++ wrapper for VLC. I had posted the source code for just the TV Toolbar in Visual Studio 6.0 and a lot of people asked me for the toolbar code in Visual Studio 2008 which is included in the source code for this article along with many new things. In Part II, I will add the source code for playing streaming video and go into a discussion of the various methods you can use to play streaming video from TV and radio sources and how to find these sources on the Internet which isn't as easy as you might think.

How The TV Toolbar Plays Live TV in Your Browser

There are three main ways to play video streams using either DirectShow, VLC, or Apple's Quicktime. I have used all three of these methods in various versions of my TV Toolbar. The best method on Windows, in my experience, is VLC, i.e. VideoLan, using a wrapper for the libvlc.lib library in either C++, C#, or Java and running that wrapper in a separate process from the TV Toolbar or whatever program you use to launch it. I have written a number of Camera Walls for streaming I.P. cameras and in the real world large companies expect your camera wall to run for over a month without crashing. The secret to preventing crashing of a camera wall is to NOT place the code for playing video inside the camera wall. Instead you create an executable that just plays video and launch that executable in its own process so that if it crashes, your camera wall is still up and running. The camera Wall is just a collection of windows where you stream the video into each window from a separate process. But to actually create truly separate instances of the VLC library, you must modify the source code for VLC in several ways including adding code that adds a Display Time Stamp to all RTSP streams. The source of TV shows the TV Toolbar uses are published video servers streaming TV shows and video and music, and files posted by the copyright holders of pre-recorded shows. More and more TV stations are putting part of their programming online either as live feeds or recorded video. In Part II of this article, I will show you how to find the I.P. addresses for sources of the thousands of TV and radio servers that you can stream TV shows and radio from online.

WARNING: The TV Toolbar will NOT play any P2P sources of video because in my opinion, that may be illegal and unethical without the permission of the copyright holder. There are hackers who record TV shows and post them on P2P nets but this is a violation of the owner's copyright and the quality is terrible. Stay away from P2P programs that claim to offer TV shows or you may find that your Internet service has been terminated by your provider and your name reported to one of several groups filing lawsuits for copyright infringement like with illegal music downloads.

Creating The TV Toolbar in VS2008 with A WebBrowser in a WebBand

One of the things that made my TV Toolbar so different back in 1997 and now is the fact that I decided to embed a WebBrowser control in a toolband and make my TV Toolbar an ordinary HTML web page. This allowed me to have dozens of toolbars loaded in one single toolband at the same time. In this version in Visual Studio 2008 I also put a WebBrowser control in a toolband but I separated the code so that you can easily add a regular toolbar and switch dynamically between HTML toolbars and a hard coded ATL/WTL C++ toolbar.  By using this approach, the TV Toolbar can display anything from cool buttons to stock quotes instantly from any remote server in any language including Japanese and Chinese. Users can also customize the TV Toolbar any way they want because the TV Toolbar is just a web page loaded inside of a webbrowser placed inside of an horizontal toolbar in Internet Explorer. While there are plenty of examples of hosting the WebBrowser control in Vertical bands inside of Internet Explorer, I decided to host the WebBrowser control inside of a Horizontal toolbar in Internet Explorer and run 2 sinks, one sink for events in the toolbar and another sink for events in the main browser window. There are many advantages to placing a browser inside of a toolbar to create the User Interface of the toolbar. The main reason is that the toolbar itself can reside on a remote server and be dynamically updated with new features, functionality and advertising instantly from a remote web server which includes things like streaming stock quotes, video, etc. in any language that can then be displayed in a variety of ways to the user. Another reason is that the webbrowser can take advantage of DHTML and Java to create spectacular User Interfaces inside of the toolbar. Shown below is my first TV Toolbar in 1997. Notice the "TV Toolbar" at the top of the browser.

TV Toolbbar

I decided to add the code for my TV Button shown below that installs as a separate DLL. When you click this button, you will see a dropdown menu that allows you to play videos INSIDE Internet Explorer using DirectShow. However, while this is okay for demonstrating the concept of playing video in a Browser window by getting the handle to the window, DirectShow or a VLC wrapper needs to run from a separate process in order to stream TV shows and have the system work well as I will cover in Part II of this article. Notice the HTML media control buttons I added to the TV Toolbar--right now they don't do anything but in Part II of this article I will add in the code that will communicate with a separate VLC wrapper for the latest version of VLC to play any form of video anywhere in any window on your computer. My idea was to create a website, www.tv-toolbars.com, that displays an updated list of TV and radio stations and you would drop the links from the web page right onto the white area on the right of these media controls to play that TV station. For example, in Part II of this article I will add a page to the website, www.tv-toolbars.com/tvshows.aspx, and put a list of TV stations on the web page with the I.P. address in the link on the web page, then a user can drag that link from the web page and drop it on the TV Toolbar in the white area to the right of the media controls and the TV Toolbar will then launch in a separate process the VLC wrapper and pass it the I.P. stream to play as shown below in "TV Links Drop Zone":

TV Toolbbar

A Different TV Toolbar for Each Tab

I decided to create a different instance of the TV Toolbar for EACH Tab in Internet Explorer which allows you to have a different TV Toolbar loaded for each tab as shown below. If you look at the source code, you will see that the class CWBToolbar is the class that manages the WebBrowser control interfaces and I create a separate instance of this class for each new tab created in Internet Explorer 7 & above. I left out the classes for connecting to a webservice to retrieve new toolbars and new TV and radio sources but I will add those classes back in Part II of this series of articles. In Part II, I will show you how to add a data management class, namely, CTVData, that we will maintain only one instance of to share the data between all tabs. CTVData will wrap shared memory to provide real time updates of data between multiple instances of the browser as well as the tabs. But I thought all that was too much code to discuss in Part I of this series of articles. And in Part II I will show you how to add a worker thread to handle all timer processing as well as fetching data from a web server as needed. This must be done in a thread and NOT using a WM_TIMER message because we're accessing Internet Explorer's message loop, and doing it in an message handler would hang the browser by freezing the message pump for the duration of the interaction over the internet. In fact, a thorough discussion of using a web service to retrieve TV data is fairly complex and I may write a Part III to this article series just to discuss all the complex issues involved. For example, timeout values should be stored in shared memory, so the locks are maintained there as well via member variables with an internal critical section which is higher performance than a named mutex in any toolbar calling a webservice.

There are no limits to the number of different TV Toolbars you can load so on one tab you might have the TV Toolbar for watching a TV show and on another tab you might have the Nerds TV Toolbar for developers as shown below:

TV Toolbar

TV Toolbar

Getting Things in Focus in The TV Toolbar

One usually experiences keystroke issues associated with hosting the WebBrowser control in an Explorer band which often cause problems with the backspace and delete keys when focus is set to an edit box by clicking on it with the left mouse button. These problems are caused if Internet Explorer does not know that the band currently has the focus. In order to alleviate these problems, I implement IOleControlSite. In the IOleControlSite::OnFocus method, the WebBrowser's IInputObjectSite::OnFocusChangesIS is called to tell the WebBrowser control who has the focus. So when the user presses a key, several things occur:

  1. The IInputObject::HasFocusIO method is called to see if WBToolBar currently has the focus. 
  2. The IInputObject::UIActivateIO method is called to tell WBToolBar that is being activated. 
  3. The IInputObject::TranslateAccelerator method is called. It is here that WBToolBar passes the keystroke to the hosted WebBrowser control. This causes accelerator keys such as backspace and delete to be processed.

To be certain that navigation will occur in the correct window, WBToolBar sinks events for all anchors on the page through the "all" collection when a page is loaded, so when a marked anchor is clicked, the target of the navigation is changed from the band window to the main browser window.

Navigation in TV Toolbar vs. Main Browser & Anchors

I cause navigation to occur in the correct window in a number of ways. When a page is loaded, the toolbar sinks events for all anchors on the page through the "all" collection. When an anchor is clicked, the target of the navigation is changed from the band window to the main browser window. I used a fragment identifier (i.e., bookmark) like "#_tbload" to navigate to the TOOLBAR and replace it with a new toolbar from any remote server.

Since our toolband will contain multiple instances of our webbrowser control and we will have multiple tabs in Internet Explorer 7 and above, we need to control which window navigation will occur in. There are other ways to accomplish this but this approach is simple and has worked well in the many TV Toolbars I have sold since 1997.

When a toolbar link is clicked, it will automatically navigate inside the band window so we sink events for all anchors in the toolbar's HTML file and look for an anchor passed in the URL in the BeforeNavigate2 event handler so we can determine whether to navigate inside the toolband or the main browser. In the TV Toolbar to control which window navigation will occur in, we sink events for all anchors on page. We navigate in the main window if an anchor is clicked. To determine where we want navigation to occur, we use in our URL an indicator known as a fragment identifier (otherwise known as a bookmark). We can't use the TARGET attribute because it causes Internet Explorer to open the link in a new window. We have defined the following anchors:

#define TB_SHELL "#_tbshell" 	// Launch a program file (.exe)
#define TB_LOAD "#_tbload" // Load the given toolbar .htm file
#define MB_LCHM "#_mblchm" // Load chm file into main browser
#define TB_LCHM "#_tblchm" // Load chm file into toolbar
#define IE_OPTION "#_option" // Show Options Dialog

Loading Anchors

If the anchor ("#") is omitted from the URL, then the link will be loaded into the main browser window below the TV Toolbar. For example, the following link in an HTML TV Toolbar .htm file would load the "www.yahoo.com" web page into the main browser as follows:

<a href="www.yahoo.com/">

To load a new HTML TV Toolbar, i.e., tvtoolbar.htm, as a toolbar you would include the anchor in the link as follows:

<a href="tvtoolbar.htm#_tbload">

Adjust Initial Height of the TV ToolBar at Launch

The HEIGHT of the TV Toolbar is automatically set at 26 PIXELS which is perfect for most toolbars. But you can control the height of the TV Toolbar and make it any value from 10 pixels to 100 pixels. To control the HEIGHT of the TV Toolbar from the hypertext script for the toolbar, say to set it at 36 PIXELS, you would use the following code between the <TITLE> tags as follows:

<TITLE>TBARV:36</TITLE>

And in the DISPID_DOCUMENTCOMPLETE event, we set the height of the TV Toolbar dynamically as follows:

case DISPID_DOCUMENTCOMPLETE:
{
USES_CONVERSION;
CString strUrl = "";
if (_pWebBrowserOC) {
BSTR bstrUrl;
_pWebBrowserOC->get_LocationURL(&bstrUrl);
strUrl = CString(bstrUrl);
IDispatch *pDispatch = NULL;
if (SUCCEEDED(_pWebBrowserOC->get_Document(&pDispatch)) && pDispatch) {
try {
IHTMLDocument2 *pDoc = NULL;
if (SUCCEEDED(pDispatch->QueryInterface(IID_IHTMLDocument2,
(void**)&pDoc)) && pDoc) {
try {
CString csTitleData = "";
CString csID = "";
CString csHeight = "";
// SET HEIGHT OF TOOLBAR FROM <TITLE>TBARV:36</TITLE>
BSTR bstTitle = NULL;
if ( SUCCEEDED( pDoc->get_title(&bstTitle) ) ) {
csTitleData = (CString)bstTitle;
AfxExtractSubString(csID, csTitleData, 0, (TCHAR)':');
AfxExtractSubString(csHeight, csTitleData, 1, (TCHAR)':');
if ( ( csID == "TBAR" ) || ( csID == "TBARV" ) ) {
LONG lTempHeight = 26;
lTempHeight = atoi(csHeight);
if ( ( lTempHeight > 10 ) && ( lTempHeight < 100 ) ) {
_lBandHeight = lTempHeight;
} else { _lBandHeight = 26; }
if ( csID == "TBARV" ) _bBandVarH = TRUE;
} else { _bBandVarH = FALSE; _lBandHeight = 26; }
// MAKE SURE WE HAVE THE TOOLBAR!
IOleCommandTarget* pCmdTarget;
if (SUCCEEDED(_pSite->QueryInterface(IID_IOleCommandTarget,
(LPVOID*)&pCmdTarget))){
pCmdTarget->Exec(&CGID_DeskBand, DBID_BANDINFOCHANGED,
OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
pCmdTarget->Release();
}
}
} catch(CException* pe){ pe->Delete(); }
}
} catch(CException* pe){ pe->Delete(); }
}
}

Creating HTML TV Toolbars

The sample TV Toolbars included in the source code with this article have TV Toolbars made in a number of different ways. Some of the TV Toolbars us a Java Applet to create cool-looking buttons with great colors and 3-D appearances. With a Java applet menu, the dropdowns will overlap the browser window which is a requirement. If you create a web page to use as a menu and don't want to use a Java applet, then you can use a Microsoft PopUp Object to create the toolbar and the dropdowns will overlap the browser window as required. It is pretty easy to create your own HTML toolbars in a few minutes to replace the ones in this sample. Toolbars can reside on the local client machine or a remote web server and can be almost anything: text files, .htm file, .chm files, ASP, JSP, etc. You can load web toolbars that reside on remote servers by just loading their URLs or you can use the Launcher Program or a DLL you create to retrieve web toolbars from remote servers and then stream those toolbars to a file on the client machine and load the files saved from the remote server from the client side which helps to bypass security problems on intranets. I included support for loading .chm files which can be easily expanded to search for all of the .htm files in the .chm file.

You can add as many toolbars as you want. For example, in the sample TV Toolbar with this article, I added the following TV Toolbars that you can dynamically switch between from any toolbar to another toolbar through the dropdown menu as follows:

TV Toolbbar

Launch Programs From The TV ToolBar

Launch a program file (.exe) by using the #_tbshell" anchor in your URL as follows:

#_tbshell#killer.exe#   This will launch the killer.exe file.

The NSIS Installer & Launching The TV Toolbar

I prefer using NSIS because, in my opinion, it is vastly superior to all the other installers like Microsoft, InstallShield, and WISE. The NSIS installation script is included. In order to add a Desktop link that users could use to launch the TV Toolbar I included a program called, TVTool, that is used to launch the TV Toolbar and make sure it is loaded into Internet Explorer as a toolbar. Microsoft's example of how to launch a toolbar is incorrect. You MUST pass "&vtEmpty" and NOT "0" as the last parameter as follows:

// Display Explorer ToolBar
VARIANT vtBandGUID, vtShow;
vtBandGUID.vt = VT_BSTR;
vtBandGUID.bstrVal =
SysAllocString(OLESTR("{5D570CA3-3123-11D5-B8D0-D2E7CAE90E45}"));
vtShow.vt = VT_BOOL;
vtShow.boolVal = true;
// You MUST pass "&vtEmpty"
and NOT "0" as last parameter!
m_pBrowserApp->ShowBrowserBar(&vtBandGUID,
&vtShow, &vtEmpty);
SysFreeString(vtBandGUID.bstrVal);
dispIE.m_lpDispatch->Release();

This launcher program includes a method LauchIEBrowser(), to launch an instance of Internet Explorer and a method, Register(), to register the DLL without using "regsvr32.exe" which may not be present on the user's computer.

The installer installs the TV Toolbar in C:\\Program Files\TVToolbar\TVToolbar.dll.
The "toolbars" directory in the nsis folder must be in the "TVToolbar" directory so that the toolbar can find the .htm toolbars and images.
I would suggest you run the compiled file, itvtoolbar.exe, in the nsis folder to install the toolbars, HTML files, and images in the correct directories.

In Conclusion

In the next week or two, I will post Part II of this article series that will focus on playing from a wide variety of sources. In the versions of the TV Toolbar I have released, I have primarily used either DirectShow or VLC. To use DirectShow, you need to write a DirectShow Source Filter for RTSP which I did which works but you still want to use the fantastic Demuxer in VLC even if you use DirectShow. You can modify the source code in VLC fairly easily to add a DirectShow Source Filter inside VLC and recompile VLC. The easiest way to compile VLC on Windows is to use Unbuntu on a memory drive. I will go into all of this in Part II. And to prevent locking up the browser, you must run play the video stream in a separate process that the TV Toolbar communicates with through one of several different methods.

I have written a lot of VLC wrappers in C++ (managed & unmanaged code) and C# .NET and I have tweaked one of them for this TV Toolbar in Part II of this article. I temporarily put some images into the TV Toolbar for play, stop, pause, etc. buttons and I will add the comments to hook them up in Part II of this article.

Bill SerGio
tv-toolbars.com

History

  • 12th May, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Bill SerGio, The Infomercial King

CEO
http://www.CutlerBayTV.com
United States United States

Member
I am an investor and I launch new companies using infomercials, www.GeminiGroupTV.com. An infomercial can gross from $60 million to $300 million in less than one year in TV sales. I put Spots and infomercials on National TV where I only pay the TV stations a percentage of my sales. www.StationBreak.net
 
My company is a pioneer in Data Mining going back to 1984.
We cross reference the Census Database and the Political Action Committee(PAC) Databases with your customer database and generate 376 additional pieces of information about your each of your customers. We then segment your customers into Targeting Niches and provides you with a list of products that we know will sell to each of those targeted lists.
 
Bill SerGio
www.SpyWhacker.com

你可能感兴趣的:(online)