[xiph-commits] r3118 - in liboggplay/trunk/plugin: .
mac/liboggplay.xcodeproj support
tahn at svn.annodex.net
tahn at svn.annodex.net
Thu Jun 28 05:29:38 PDT 2007
Author: tahn
Date: 2007-06-28 05:29:38 -0700 (Thu, 28 Jun 2007)
New Revision: 3118
Removed:
liboggplay/trunk/plugin/plugin_playlist.c
liboggplay/trunk/plugin/plugin_playlist.h
Modified:
liboggplay/trunk/plugin/mac/liboggplay.xcodeproj/project.pbxproj
liboggplay/trunk/plugin/nsILibOggPlugin.idl
liboggplay/trunk/plugin/plugin.cpp
liboggplay/trunk/plugin/plugin.h
liboggplay/trunk/plugin/plugin_c.h
liboggplay/trunk/plugin/plugin_gui_linux.c
liboggplay/trunk/plugin/plugin_gui_mac.c
liboggplay/trunk/plugin/support/nsScriptablePeer.cpp
Log:
Implemented playlists.
Modified: liboggplay/trunk/plugin/mac/liboggplay.xcodeproj/project.pbxproj
===================================================================
--- liboggplay/trunk/plugin/mac/liboggplay.xcodeproj/project.pbxproj 2007-06-28 12:17:24 UTC (rev 3117)
+++ liboggplay/trunk/plugin/mac/liboggplay.xcodeproj/project.pbxproj 2007-06-28 12:29:38 UTC (rev 3118)
@@ -8,8 +8,7 @@
/* Begin PBXBuildFile section */
2C31AFE40BF455CB002C55BF /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C31AFE30BF455CB002C55BF /* Carbon.framework */; };
- 2C81E4140C1E119F008364B7 /* plugin_playlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C81E4120C1E119F008364B7 /* plugin_playlist.h */; };
- 2C81E4150C1E119F008364B7 /* plugin_playlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 2C81E4130C1E119F008364B7 /* plugin_playlist.c */; };
+ 2C613F4F0C33950A00F9298C /* plugin_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C613F4E0C33950A00F9298C /* plugin_c.h */; };
2C83A7A10BE86E72004C14F4 /* liboggplay.r in Rez */ = {isa = PBXBuildFile; fileRef = 2C83A7110BE85E80004C14F4 /* liboggplay.r */; };
2C83A8620BE96764004C14F4 /* np_mac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2C83A8610BE96764004C14F4 /* np_mac.cpp */; };
2C83A8AB0BE9698F004C14F4 /* npp_gate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2CD58C990BD33B65001D751D /* npp_gate.cpp */; };
@@ -56,8 +55,7 @@
/* Begin PBXFileReference section */
2C31AFE30BF455CB002C55BF /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
- 2C81E4120C1E119F008364B7 /* plugin_playlist.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = plugin_playlist.h; path = ../plugin_playlist.h; sourceTree = SOURCE_ROOT; };
- 2C81E4130C1E119F008364B7 /* plugin_playlist.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = plugin_playlist.c; path = ../plugin_playlist.c; sourceTree = SOURCE_ROOT; };
+ 2C613F4E0C33950A00F9298C /* plugin_c.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = plugin_c.h; path = ../plugin_c.h; sourceTree = SOURCE_ROOT; };
2C83A7110BE85E80004C14F4 /* liboggplay.r */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.rez; path = liboggplay.r; sourceTree = "<group>"; };
2C83A8610BE96764004C14F4 /* np_mac.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = np_mac.cpp; sourceTree = "<group>"; };
2C83AB270BE9C6EB004C14F4 /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = /System/Library/Frameworks/AGL.framework; sourceTree = "<absolute>"; };
@@ -176,6 +174,7 @@
children = (
2CD58C4E0BD319C3001D751D /* plugin.cpp */,
2CD58C4F0BD319C3001D751D /* plugin.h */,
+ 2C613F4E0C33950A00F9298C /* plugin_c.h */,
2CD58C4C0BD319C3001D751D /* plugin_oggplay.c */,
2CD58C4D0BD319C3001D751D /* plugin_oggplay.h */,
2CD58C4A0BD319C3001D751D /* plugin_gui_mac.c */,
@@ -184,8 +183,6 @@
2CD58C4B0BD319C3001D751D /* plugin_gui.h */,
2CF2FD420C191F8A0074A9C3 /* plugin_tools.c */,
2CF2FD430C191F8A0074A9C3 /* plugin_tools.h */,
- 2C81E4130C1E119F008364B7 /* plugin_playlist.c */,
- 2C81E4120C1E119F008364B7 /* plugin_playlist.h */,
2CA761D40BF978E10008A3B7 /* std_semaphore.h */,
2C9F53E10C2A5727007365C0 /* nsILibOggPlugin.idl */,
2CF2FD540C191FD70074A9C3 /* audio */,
@@ -307,7 +304,7 @@
2CA761D50BF978E10008A3B7 /* std_semaphore.h in Headers */,
2CD6AD870C0D355B007E42D5 /* sydney_audio_new.h in Headers */,
2CF2FD450C191F8A0074A9C3 /* plugin_tools.h in Headers */,
- 2C81E4140C1E119F008364B7 /* plugin_playlist.h in Headers */,
+ 2C613F4F0C33950A00F9298C /* plugin_c.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -420,7 +417,6 @@
2C83A8AB0BE9698F004C14F4 /* npp_gate.cpp in Sources */,
2C96D1330C0666340015B6AC /* sydney_audio_mac.c in Sources */,
2CF2FD440C191F8A0074A9C3 /* plugin_tools.c in Sources */,
- 2C81E4150C1E119F008364B7 /* plugin_playlist.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Modified: liboggplay/trunk/plugin/nsILibOggPlugin.idl
===================================================================
--- liboggplay/trunk/plugin/nsILibOggPlugin.idl 2007-06-28 12:17:24 UTC (rev 3117)
+++ liboggplay/trunk/plugin/nsILibOggPlugin.idl 2007-06-28 12:29:38 UTC (rev 3118)
@@ -53,8 +53,8 @@
[scriptable, uuid(482e1890-1fe5-11d5-9cf8-0260b0fbd8ac)]
interface nsILibOggPlugin : nsISupports {
- const short apiVersionMajor = 0;
- const short apiVersionMinor = 1;
+ const short apiVersionMajor = 1;
+ const short apiVersionMinor = 0;
string getVersionString();
@@ -82,13 +82,14 @@
void unfreezePlaylistProgression();
long getPlaylistLength();
long getCurrentPlaylistPosition();
+ boolean playMovieAt(in long position);
+ boolean playlistNext();
+ boolean playlistPrev();
string getMovieAt(in long position);
boolean setMovieAt(in long position, in string url);
void appendMovie(in string url);
boolean insertMovieBefore(in long position, in string url);
boolean removeMovieAt(in long position);
- long getPlayPositionWithinMovie();
- boolean setPlayPositionWithinMovie(in long milliseconds);
string retrieveAnnotationsAt(in long position);
long getMovieLengthAt(in long position);
void registerPlaylistCallback(in nsILibOggCallbackNoArg callback);
Modified: liboggplay/trunk/plugin/plugin.cpp
===================================================================
--- liboggplay/trunk/plugin/plugin.cpp 2007-06-28 12:17:24 UTC (rev 3117)
+++ liboggplay/trunk/plugin/plugin.cpp 2007-06-28 12:29:38 UTC (rev 3118)
@@ -228,30 +228,28 @@
mScriptablePeer(NULL),
mOggHandle(NULL),
mGuiHandle(NULL),
- mSource(NULL),
mServiceManager(NULL),
+ mProxyHost(NULL),
+ mProxyPort(80),
+ mPlaylistPos(0),
+ mReachedEndOfMovie(FALSE),
mCmmlCallback(NULL),
- mEndPlayCallback(NULL)
+ mEndPlayCallback(NULL),
+ mPlaylistCallback(NULL)
#if defined(XP_MACOSX)
,
mOutputCleared(FALSE)
#elif defined (XP_WIN)
,
mPollingStarted(false),
- mPollingPeriod(POLLING_PERIOD),
- mProxyHost(NULL),
- mProxyPort(80)
+ mPollingPeriod(POLLING_PERIOD)
#endif
{
nsISupports * sm = NULL;
nsIPrefService * prefs = NULL;
nsIPrefBranch * branch = NULL;
- mString[0] = '\0';
- setSource(source);
- SEM_CREATE(mCmmlSem, 1);
- SEM_CREATE(mEndPlaySem, 1);
-
+ // Jump through some hoops to get the proxy info
NPN_GetValue(NULL, NPNVserviceManager, &sm);
if (sm) {
@@ -264,7 +262,6 @@
mServiceManager->GetServiceByContractID(
"@mozilla.org/preferences-service;1",
NS_GET_IID(nsIPrefService), (void **)&prefs);
-
}
if (prefs != NULL) {
@@ -283,10 +280,19 @@
}
}
+ // Initialise the remaining members, and create our playlist of 1
+ SEM_CREATE(mCrossThreadSem, 1);
+ appendMovie(source);
}
nsPluginInstance::~nsPluginInstance()
{
+#if defined(XP_WIN)
+ if (mPollingStarted == true) {
+ KillTimer((HWND)mWindow->window, IDT_CALLBACK_TIMER);
+ }
+#endif
+
// mScriptablePeer may be also held by the browser
// so releasing it here does not guarantee that it is over
// we should take precaution in case it will be called later
@@ -295,30 +301,23 @@
mScriptablePeer->SetInstance(NULL);
NS_IF_RELEASE(mScriptablePeer);
}
- if (mSource != NULL) {
- free(mSource);
- }
if (mCmmlCallback != NULL) {
NS_RELEASE(mCmmlCallback);
}
if (mEndPlayCallback != NULL) {
NS_RELEASE(mEndPlayCallback);
}
+ if (mPlaylistCallback != NULL) {
+ NS_RELEASE(mPlaylistCallback);
+ }
-#if defined(XP_WIN)
- if (this->mPollingStarted == true) {
- KillTimer((HWND)mWindow->window, IDT_CALLBACK_TIMER);
+ for (unsigned int i = 0; i < mPlaylist.size(); i++) {
+ free(mPlaylist[i]);
}
-#endif
-
- SEM_CLOSE(mCmmlSem);
- SEM_CLOSE(mEndPlaySem);
-#if defined(XP_MACOSX) || defined(XP_WIN)
clearCmmlStrings();
-#endif
+ SEM_CLOSE(mCrossThreadSem);
}
-#if defined(XP_MACOSX) || defined (XP_WIN)
void
nsPluginInstance::clearCmmlStrings() {
for (unsigned int i = 0; i < mCmmlStrings.size(); i++) {
@@ -326,26 +325,7 @@
}
mCmmlStrings.clear();
}
-#endif
-void
-nsPluginInstance::setSource(const char *source)
-{
- if (mSource != NULL) {
- free(mSource);
- mSource = NULL;
- }
- if (source != NULL) {
- mSource = strdup(source);
- }
-}
-
-char *
-nsPluginInstance::getSource()
-{
- return mSource;
-}
-
NPBool
nsPluginInstance::init(NPWindow* aWindow)
{
@@ -376,7 +356,7 @@
NPError
nsPluginInstance::NewStream(NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype)
{
- printf("URL %s for this Mime-Type %s\n", (char*)type, stream->url);
+ //printf("URL %s for this Mime-Type %s\n", (char*)type, stream->url);
return NPERR_NO_ERROR;
}
@@ -387,10 +367,10 @@
// When the browser window is resized, we usually receive one or more calls
// to SetWindow, often with a zero-sized clip, followed by an update event
// in HandleEvent with the correct clip. Therefore, we want to ignore the
- // SetWindow calls and only update the clip size in the event handler.
+ // SetWindow calls and only update the clip size in HandleEvent.
// -- MAC OS X SPECIFIC -
if (mWindowInitialised == FALSE) {
- if (getSource() == NULL) {
+ if (curMovie() == NULL) {
return NPERR_NO_ERROR;
}
@@ -398,7 +378,7 @@
// code is responsible for destroying it, because only the gui code knows
// when to shut down the old handle after a new media source has been
// provided.
- mOggHandle = initialise_oggplay(getSource(), mProxyHost, mProxyPort);
+ mOggHandle = initialise_oggplay(curMovie(), mProxyHost, mProxyPort);
mGuiHandle = initialise_gui(this, aWindow, mOggHandle);
mWindow = aWindow;
mWindowInitialised = TRUE;
@@ -429,8 +409,10 @@
// which are the null event. While this is not exactly efficient, it does
// turn out to be useful for a couple of things.
//
- // First, to send the cmml strings collected by onCMMLData to the browser..
- executeCmmlCallback();
+ // First, to process any events triggered from the display thread..
+ SEM_WAIT(mCrossThreadSem);
+ processCrossThreadCalls();
+ SEM_SIGNAL(mCrossThreadSem);
// ..and second, to handle hiding our output when the user changes tabs or
// scrolls the media off the page.
@@ -469,31 +451,13 @@
nsPluginInstance * plugin = NULL;
plugin = (nsPluginInstance *)GetWindowLongPtr(hWnd, GWL_USERDATA);
- plugin->executeCmmlCallback();
+ SEM_WAIT(mCrossThreadSem);
+ plugin->processCrossThreadCalls();
+ SEM_SIGNAL(mCrossThreadSem);
}
#endif
-#if defined (XP_MACOSX) || defined(XP_WIN)
-void
-nsPluginInstance::executeCmmlCallback() {
- // Since this function is called very frequently, we don't want to grab
- // the semaphore every time, but checking the pointer for null before locking
- // introduces a potential race condition, so we need to double-check.
- if (mCmmlCallback != NULL) {
- SEM_WAIT(mCmmlSem);
- if (mCmmlCallback != NULL && mCmmlStrings.size() > 0) {
- for (unsigned int i = 0; i < mCmmlStrings.size(); i++) {
- //printf("Sending CMML to Javascript: %s\n", mCmmlStrings[i]);
- mCmmlCallback->Call(mCmmlStrings[i]);
- }
- clearCmmlStrings();
- }
- SEM_SIGNAL(mCmmlSem);
- }
-}
-#endif
-
// ==============================
// ! Scriptability related code !
// ==============================
@@ -568,6 +532,20 @@
////////////////////////////////////////
//
+// Private helper functions
+//
+char *
+nsPluginInstance::curMovie() const {
+ return mPlaylist[mPlaylistPos];
+}
+
+bool
+nsPluginInstance::playlistIndexOk(long index) const {
+ return (index >= 0 && index < (long)mPlaylist.size());
+}
+
+////////////////////////////////////////
+//
// Javascript API - standard playback
//
void
@@ -595,8 +573,8 @@
void
nsPluginInstance::restart() {
- if (getSource() != NULL) {
- mOggHandle = initialise_oggplay(getSource(), mProxyHost, mProxyPort);
+ if (curMovie() != NULL) {
+ mOggHandle = initialise_oggplay(curMovie(), mProxyHost, mProxyPort);
update_gui_with_new_oggplay(mGuiHandle, mOggHandle);
gui_play(mGuiHandle);
}
@@ -609,21 +587,17 @@
void
nsPluginInstance::setCurrentMovie(const char *url) {
- // It's ok to lose the reference to the old oggplay handle (no, really, it
- // is). The gui code will destroy it before swapping over to the new handle.
- setSource(url);
- mOggHandle = initialise_oggplay(getSource(), mProxyHost, mProxyPort);
- update_gui_with_new_oggplay(mGuiHandle, mOggHandle);
+ setMovieAt(mPlaylistPos, url);
}
char *
nsPluginInstance::getCurrentMovie() {
char *url = NULL;
- if (getSource() != NULL) {
- url = (char *)NPN_MemAlloc(strlen(getSource()) + 1);
+ if (curMovie() != NULL) {
+ url = (char *)NPN_MemAlloc(strlen(curMovie()) + 1);
if (url != NULL) {
- strcpy(url, getSource());
+ strcpy(url, curMovie());
}
}
return url;
@@ -671,14 +645,7 @@
char *
nsPluginInstance::retrieveAnnotations() {
-//!todo
- char *annotations = NULL;
-
- annotations = (char *)NPN_MemAlloc(100);
- if (annotations != NULL) {
- strcpy(annotations, "all ur annotations are belong to us");
- }
- return annotations;
+ return retrieveAnnotationsAt(mPlaylistPos);
}
////////////////////////////////////////
@@ -697,107 +664,149 @@
long
nsPluginInstance::getPlaylistLength() {
-//!todo
- return 0;
+ return mPlaylist.size();
}
long
nsPluginInstance::getCurrentPlaylistPosition() {
-//!todo
- return 0;
+ return mPlaylistPos;
}
+bool
+nsPluginInstance::playMovieAt(long position) {
+ if (!playlistIndexOk(position)) {
+ return FALSE;
+ }
+ mPlaylistPos = position;
+ restart();
+ return TRUE;
+}
+
+bool
+nsPluginInstance::playlistNext() {
+ if (mPlaylistPos == (int)mPlaylist.size() - 1) {
+ return FALSE;
+ }
+ mPlaylistPos++;
+ restart();
+ return TRUE;
+}
+
+bool
+nsPluginInstance::playlistPrev() {
+ if (mPlaylistPos == 0) {
+ return FALSE;
+ }
+ mPlaylistPos--;
+ restart();
+ return TRUE;
+}
+
char *
nsPluginInstance::getMovieAt(long position) {
-//!todo - remove bad pun
- char *movie = NULL;
-
- movie = (char *)NPN_MemAlloc(100);
+ if (!playlistIndexOk(position)) {
+ return NULL;
+ }
+ char *movie = (char *)NPN_MemAlloc(strlen(mPlaylist[position]) + 1);
if (movie != NULL) {
- strcpy(movie, "nothing to see here, movie along");
+ strcpy(movie, mPlaylist[position]);
}
return movie;
}
bool
nsPluginInstance::setMovieAt(long position, const char *url) {
-//!todo
+ if (!playlistIndexOk(position)) {
+ return FALSE;
+ }
+ free(mPlaylist[position]);
+ mPlaylist[position] = strdup(url);
+ if (position == mPlaylistPos) {
+ // We can just discard our reference to the old oggplay handle; the gui
+ // code will destroy it before swapping over to the new one.
+ mOggHandle = initialise_oggplay(curMovie(), mProxyHost, mProxyPort);
+ update_gui_with_new_oggplay(mGuiHandle, mOggHandle);
+ }
return TRUE;
}
void
nsPluginInstance::appendMovie(const char *url) {
-//!todo
- return;
+ mPlaylist.push_back(strdup(url));
}
bool
nsPluginInstance::insertMovieBefore(long position, const char *url) {
-//!todo
+ if (!playlistIndexOk(position)) {
+ return FALSE;
+ }
+ mPlaylist.insert(mPlaylist.begin() + position, strdup(url));
+ if (position <= mPlaylistPos) {
+ mPlaylistPos++;
+ }
return TRUE;
}
bool
nsPluginInstance::removeMovieAt(long position) {
-//!todo
+ if (!playlistIndexOk(position) || mPlaylist.size() <= 1) {
+ return FALSE;
+ }
+ free(mPlaylist[position]);
+ mPlaylist.erase(mPlaylist.begin() + position);
+ // remember that mPlaylist.size() has been decremented now!
+ if ((position < mPlaylistPos && mPlaylistPos > 0) ||
+ (mPlaylistPos == (int)mPlaylist.size())) {
+ mPlaylistPos--;
+ }
+ //!todo - if this is current movie, need to progress to next...
return TRUE;
}
-long
-nsPluginInstance::getPlayPositionWithinMovie() {
-//!todo
- return 0;
-}
-
-bool
-nsPluginInstance::setPlayPositionWithinMovie(long milliseconds) {
-//!todo
- return TRUE;
-}
-
char *
nsPluginInstance::retrieveAnnotationsAt(long position) {
-//!todo
- char *annotations = NULL;
-
- annotations = (char *)NPN_MemAlloc(100);
+ if (!playlistIndexOk(position)) {
+ return NULL;
+ }
+ //!todo
+ char *annotations = (char *)NPN_MemAlloc(100);
if (annotations != NULL) {
- strcpy(annotations, "annotations ftw");
+ sprintf(annotations, "annotations for %ld ftw", position);
}
return annotations;
}
long
nsPluginInstance::getMovieLengthAt(long position) {
-//!todo
- return 0;
+ if (!playlistIndexOk(position)) {
+ return -1;
+ }
+ //!todo
+ return -1;
}
-////////////////////////////////////////
+///////////////////////////////////////////
//
-// Javascript API - callback handling
+// Javascript API - callback registration
//
void
nsPluginInstance::registerCMMLCallback(nsILibOggCallbackString *cbObj) {
- SEM_WAIT(mCmmlSem);
+ SEM_WAIT(mCrossThreadSem);
if (mCmmlCallback != NULL) {
NS_RELEASE(mCmmlCallback);
}
mCmmlCallback = cbObj;
if (mCmmlCallback != NULL) {
NS_ADDREF(mCmmlCallback);
- }
-#if defined(XP_MACOSX) || defined(XP_WIN)
- if (mCmmlCallback == NULL) {
+ } else {
clearCmmlStrings();
}
-#endif
- SEM_SIGNAL(mCmmlSem);
+ SEM_SIGNAL(mCrossThreadSem);
}
void
nsPluginInstance::registerEndPlayCallback(nsILibOggCallbackNoArg *cbObj) {
- SEM_WAIT(mEndPlaySem);
+ SEM_WAIT(mCrossThreadSem);
if (mEndPlayCallback != NULL) {
NS_RELEASE(mEndPlayCallback);
}
@@ -805,12 +814,12 @@
if (mEndPlayCallback != NULL) {
NS_ADDREF(mEndPlayCallback);
}
- SEM_SIGNAL(mEndPlaySem);
+ SEM_SIGNAL(mCrossThreadSem);
}
void
nsPluginInstance::registerPlaylistCallback(nsILibOggCallbackNoArg *cbObj) {
- SEM_WAIT(mPlaylistSem);
+ SEM_WAIT(mCrossThreadSem);
if (mPlaylistCallback != NULL) {
NS_RELEASE(mPlaylistCallback);
}
@@ -818,73 +827,106 @@
if (mPlaylistCallback != NULL) {
NS_ADDREF(mPlaylistCallback);
}
- SEM_SIGNAL(mPlaylistSem);
+ SEM_SIGNAL(mCrossThreadSem);
}
+////////////////////////////////////////
+//
+// Cross-thread event handling
+//
+// Mac and Windows don't like cross-thread calls between the GUI thread and
+// the main plugin/browser thread, so the callbacks are triggered by the
+// display thread but must be invoked by the main thread. We do this with a
+// deferred invocation model:
+// - The callback notification functions are executed by the display thread,
+// and simply store their data in the plugin class.
+// - processCrossThreadCalls is executed at regular intervals by the main
+// thread, and invokes the Javascript callback objects when needed.
+//
+// On the Mac, the "regular intervals" bit is achieved by piggybacking on the
+// constant stream of browser-originated calls to HandleEvent. On Windows we
+// use SetTimer to provide an artificial heartbeat.
+//
+// Linux doesn't have a problem with cross-thread calls, so we can execute
+// processCrossThreadCalls directly from the callback notification functions.
+
+// -- Callback notification functions --
+// These are executed in the display thread.
void
nsPluginInstance::onCMMLData(char **cmml_data, int cmml_size) {
- SEM_WAIT(mCmmlSem);
+ SEM_WAIT(mCrossThreadSem);
if (mCmmlCallback != NULL) {
-#if defined(XP_MACOSX) || defined(XP_WIN)
- // The Mac and Windows don't like cross-thread calls between the GUI thread
- // and the plugin/browser thread. We need to execute the cmml callback in
- // the main browser thread, but this function is called from the GUI
- // display thread. So we buffer up the cmml strings here.
- // [MACOSX]
- // On Mac we piggyback on the browser-originated calls to HandleEvent
- // to send the strings to the browser.
- // [Win32]
- // On Windows we use a timer introduced to provide an artificial
- // heartbeat similar to ongoing event processing on Mac.
- // We need to make copies of the strings because the oggplay frame can be
- // freed before we get in to HandleEvent (Mac) or timer handler funtion
- // (Win32).
- for (int i = 0; i < cmml_size; i++) {
+ for (int i = 0; i < cmml_size; i++) {
+ // We need to make copies of the strings because the oggplay frame in
+ // which they're stored can be freed before processCrossThreadCalls
+ // passes them to the browser.
mCmmlStrings.push_back(strdup(cmml_data[i]));
}
-#else
- for (int i = 0; i < cmml_size; i++) {
- mCmmlCallback->Call(cmml_data[i]);
- }
+#if defined(XP_UX)
+ processCrossThreadCalls();
#endif
}
- SEM_SIGNAL(mCmmlSem);
+ SEM_SIGNAL(mCrossThreadSem);
}
void
-nsPluginInstance::onEndOfPlay() {
- SEM_WAIT(mEndPlaySem);
- if (mEndPlayCallback != NULL) {
- mEndPlayCallback->Call();
- }
- SEM_SIGNAL(mEndPlaySem);
+nsPluginInstance::onEndOfMovie() {
+ SEM_WAIT(mCrossThreadSem);
+ mReachedEndOfMovie = TRUE;
+#if defined(XP_UX)
+ processCrossThreadCalls();
+#endif
+ SEM_SIGNAL(mCrossThreadSem);
}
-void
-nsPluginInstance::onPlaylistTrackChanged() {
- SEM_WAIT(mPlaylistSem);
- if (mPlaylistCallback != NULL) {
- mPlaylistCallback->Call();
- }
- SEM_SIGNAL(mPlaylistSem);
-}
-
// C hooks for the callback notification functions
extern "C" {
void
onCMMLData(nsPluginInstance *i, char **cmml_data, int cmml_size) {
- i->onCMMLData(cmml_data, cmml_size);
+ i->onCMMLData(cmml_data, cmml_size);
}
void
-onEndOfPlay(nsPluginInstance *i) {
- i->onEndOfPlay();
+onEndOfMovie(nsPluginInstance *i) {
+ i->onEndOfMovie();
}
+} // extern "C"
+
+// -- Deferred callback processing --
+// Every call to this method must protected by mCrossThreadSem.
void
-onPlaylistTrackChanged(nsPluginInstance *i) {
- i->onPlaylistTrackChanged();
+nsPluginInstance::processCrossThreadCalls() {
+
+ // Send any cmml strings collected by onCMMLData.
+ if (mCmmlStrings.size() > 0) {
+ if (mCmmlCallback != NULL) {
+ for (unsigned int i = 0; i < mCmmlStrings.size(); i++) {
+ mCmmlCallback->Call(mCmmlStrings[i]);
+ }
+ }
+ clearCmmlStrings();
+ }
+
+ // End-of-movie handling.
+ if (mReachedEndOfMovie) {
+ mReachedEndOfMovie = FALSE;
+
+ // If we've reached the end of playlist, just throw the end-play callback
+ // and we're done. Otherwise, throw the playlist callback and advance to
+ // the next movie.
+ if (mPlaylistPos == (int)mPlaylist.size() - 1) {
+ if (mEndPlayCallback != NULL) {
+ mEndPlayCallback->Call();
+ }
+ } else {
+ if (mPlaylistCallback != NULL) {
+ mPlaylistCallback->Call();
+ }
+ mPlaylistPos++;
+ restart();
+ }
+ }
+
}
-} // extern "C"
-
Modified: liboggplay/trunk/plugin/plugin.h
===================================================================
--- liboggplay/trunk/plugin/plugin.h 2007-06-28 12:17:24 UTC (rev 3117)
+++ liboggplay/trunk/plugin/plugin.h 2007-06-28 12:29:38 UTC (rev 3118)
@@ -73,11 +73,6 @@
NPError NewStream(NPMIMEType type, NPStream* stream,
NPBool seekable, uint16* stype);
-// FIX ME: this method seem not to be implemented at all!!!
-#if defined(XP_UX)
- void redraw(Widget widget, XtPointer call_data);
-#endif
-
#if defined (XP_MACOSX) || defined(XP_WIN)
// wrapper method (for MACOSX and Win32 only)
// this is used only in Win32 and MACOSX version of the plugin
@@ -111,13 +106,14 @@
void unfreezePlaylistProgression();
long getPlaylistLength();
long getCurrentPlaylistPosition();
+ bool playMovieAt(long position);
+ bool playlistNext();
+ bool playlistPrev();
char * getMovieAt(long position);
bool setMovieAt(long position, const char *url);
void appendMovie(const char *url);
bool insertMovieBefore(long position, const char *url);
bool removeMovieAt(long position);
- long getPlayPositionWithinMovie();
- bool setPlayPositionWithinMovie(long milliseconds);
char * retrieveAnnotationsAt(long position);
long getMovieLengthAt(long position);
@@ -125,47 +121,39 @@
void registerEndPlayCallback(nsILibOggCallbackNoArg *cbObj);
void registerPlaylistCallback(nsILibOggCallbackNoArg *cbObj);
void onCMMLData(char **cmml_data, int cmml_size);
- void onEndOfPlay();
- void onPlaylistTrackChanged();
+ void onEndOfMovie();
private:
- void setSource(const char *source);
- char * getSource();
+ char * curMovie() const;
+ bool playlistIndexOk(long index) const;
+ void clearCmmlStrings();
+ void processCrossThreadCalls();
- NPP mInstance;
- NPBool mPluginInitialised;
- NPBool mWindowInitialised;
- NPWindow * mWindow;
- nsScriptablePeer * mScriptablePeer;
- void * mOggHandle;
- void * mGuiHandle;
- char * mSource;
- nsIServiceManager * mServiceManager;
-
+ NPP mInstance;
+ NPBool mPluginInitialised;
+ NPBool mWindowInitialised;
+ NPWindow * mWindow;
+ nsScriptablePeer * mScriptablePeer;
+ void * mOggHandle;
+ void * mGuiHandle;
+ nsIServiceManager * mServiceManager;
+ char * mProxyHost;
+ int mProxyPort;
+ std::vector<char*> mPlaylist;
+ int mPlaylistPos;
+ NPBool mReachedEndOfMovie;
+ std::vector<char*> mCmmlStrings;
nsILibOggCallbackString * mCmmlCallback;
nsILibOggCallbackNoArg * mEndPlayCallback;
nsILibOggCallbackNoArg * mPlaylistCallback;
- semaphore mCmmlSem;
- semaphore mEndPlaySem;
- semaphore mPlaylistSem;
+ semaphore mCrossThreadSem;
- char * mProxyHost;
- int mProxyPort;
-
#if defined(XP_WIN)
- WNDPROC lpOldProc;
- bool mPollingStarted;
- UINT mPollingPeriod;
- std::vector<char*> mCmmlStrings;
- void clearCmmlStrings();
+ bool mPollingStarted;
+ UINT mPollingPeriod;
#elif defined(XP_MACOSX)
- NPBool mOutputCleared;
- std::vector<char*> mCmmlStrings;
- void clearCmmlStrings();
+ NPBool mOutputCleared;
#endif
-
-public:
- char mString[128];
};
#endif // __PLUGIN_H__
Modified: liboggplay/trunk/plugin/plugin_c.h
===================================================================
--- liboggplay/trunk/plugin/plugin_c.h 2007-06-28 12:17:24 UTC (rev 3117)
+++ liboggplay/trunk/plugin/plugin_c.h 2007-06-28 12:29:38 UTC (rev 3118)
@@ -3,3 +3,6 @@
void
onCMMLData(nsPluginInstance *i, char **cmml_data, int cmml_size);
+
+void
+onEndOfMovie(nsPluginInstance *i);
Modified: liboggplay/trunk/plugin/plugin_gui_linux.c
===================================================================
--- liboggplay/trunk/plugin/plugin_gui_linux.c 2007-06-28 12:17:24 UTC (rev 3117)
+++ liboggplay/trunk/plugin/plugin_gui_linux.c 2007-06-28 12:29:38 UTC (rev 3118)
@@ -177,6 +177,7 @@
case OGGPLAY_STREAM_LAST_DATA:
info->playback_finished = TRUE;
+ onEndOfMovie(info->pluginInstance);
return TRUE;
default:
Modified: liboggplay/trunk/plugin/plugin_gui_mac.c
===================================================================
--- liboggplay/trunk/plugin/plugin_gui_mac.c 2007-06-28 12:17:24 UTC (rev 3117)
+++ liboggplay/trunk/plugin/plugin_gui_mac.c 2007-06-28 12:29:38 UTC (rev 3118)
@@ -425,6 +425,7 @@
break;
case OGGPLAY_STREAM_LAST_DATA:
info->playback_finished = TRUE;
+ onEndOfMovie(info->plugin_instance);
break;
}
}
Deleted: liboggplay/trunk/plugin/plugin_playlist.c
===================================================================
--- liboggplay/trunk/plugin/plugin_playlist.c 2007-06-28 12:17:24 UTC (rev 3117)
+++ liboggplay/trunk/plugin/plugin_playlist.c 2007-06-28 12:29:38 UTC (rev 3118)
@@ -1,154 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Initial Developer of the Original Code is
- * CSIRO
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s): Marcin Lubonski
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-
-#include "plugin_playlist.h"
-
-
-/**
- * Private functions for management of list elements
- */
-static void
-shift_up(PluginPlaylist *playlist, unsigned int start_pos, unsigned int end_pos) {
- unsigned int i, j;
- if (playlist->data == NULL)
- return;
-
- if ((start_pos < 1) || (end_pos > playlist->length))
- return;
-
- for (j = 0, i = end_pos - 1; j < end_pos - start_pos; i--, j++) {
- playlist->data[i] = playlist->data[i - 1];
- }
-}
-
-static void
-shift_down(PluginPlaylist *playlist, unsigned int start_pos, unsigned int end_pos) {
- unsigned int i, j;
- if (playlist->data == NULL)
- return;
-
- if ((start_pos < 1) || (end_pos > playlist->length))
- return;
-
- for (j = 0, i = start_pos - 1; j < end_pos - start_pos; j++, i++) {
- playlist->data[i] = playlist->data[i + 1];
- }
-}
-
-/**
- * Playlist public interface
- */
-void
-init(PluginPlaylist *playlist) {
- playlist->data = NULL;
- playlist->length = 0;
-}
-
-/*
- * \brief - Append new element at the end of the list
- */
-void
-append(PluginPlaylist * playlist, void * elem) {
-
- if (playlist->data == NULL) {
- playlist->data = (void**)malloc(sizeof(void*));
- playlist->length = 1;
- }
- else
- {
- playlist->data = realloc(playlist->data, (playlist->length + 1) * sizeof(void *));
- playlist->length += 1;
- }
-
- playlist->data[playlist->length-1] = elem;
- return;
-}
-/*
- * \brief - Add new element at position list_pos
- */
-void
-insert_at(PluginPlaylist* playlist, void * elem, unsigned int list_pos) {
-
- if (playlist->data == NULL) {
- if (list_pos > 1)
- return;
- playlist->data = (void **)malloc(sizeof(void *));
- playlist->length = 1;
- } else {
- if (list_pos > playlist->length + 1)
- return;
- playlist->data = realloc(playlist->data, (playlist->length + 1) * sizeof(void *));
- playlist->length += 1;
- }
-
- if (playlist->length > 1) {
- // if the existing element require shifting up
- if (list_pos < playlist->length) {
- shift_up(playlist, list_pos, playlist->length);
- }
- }
- playlist->data[list_pos-1] = elem;
- return;
-}
-
-/*
- * \brief Removes element of the playlist
- */
-void
-remove_at(PluginPlaylist* playlist, unsigned int list_pos) {
-
- if (playlist->data == NULL)
- return;
-
- if ((list_pos <= 0) || (list_pos > playlist->length))
- return;
-
- shift_down(playlist, list_pos, playlist->length);
- playlist->data = realloc(playlist->data, (playlist->length - 1) * sizeof(void *));
- playlist->length -= 1;
-
- return;
-}
-
-void
-show(PluginPlaylist* playlist) {
- unsigned int i;
- if (playlist != NULL) {
- for (i = 0; i < playlist->length; i++) {
- printf("Playlist entry [%d] is : %s\n", i + 1, (char *)playlist->data[i]);
- }
- }
- return;
-}
Deleted: liboggplay/trunk/plugin/plugin_playlist.h
===================================================================
--- liboggplay/trunk/plugin/plugin_playlist.h 2007-06-28 12:17:24 UTC (rev 3117)
+++ liboggplay/trunk/plugin/plugin_playlist.h 2007-06-28 12:29:38 UTC (rev 3118)
@@ -1,63 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Initial Developer of the Original Code is
- * CSIRO
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s): Shane Stephens, Michael Martin
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef __PLUGIN_PLAYLIST__
-#define __PLUGIN_PLAYLIST__
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#define PLAYLIST_ELEM_TYPE char*
-
-typedef struct {
- void ** data;
- unsigned int length;
-} PluginPlaylist;
-
-void
-init(PluginPlaylist * playlist);
-
-void
-append(PluginPlaylist * playlist, void * elem);
-
-void
-insert_at(PluginPlaylist* playlist, void * elem, unsigned int list_pos);
-
-void
-remove_at(PluginPlaylist* playlist, unsigned int list_pos);
-
-void
-show(PluginPlaylist* playlist);
-
-#endif //__PLUGIN_PLAYLIST__
Modified: liboggplay/trunk/plugin/support/nsScriptablePeer.cpp
===================================================================
--- liboggplay/trunk/plugin/support/nsScriptablePeer.cpp 2007-06-28 12:17:24 UTC (rev 3117)
+++ liboggplay/trunk/plugin/support/nsScriptablePeer.cpp 2007-06-28 12:29:38 UTC (rev 3118)
@@ -263,6 +263,27 @@
return NS_OK;
}
+NS_IMETHODIMP nsScriptablePeer::PlayMovieAt(PRInt32 position, PRInt32 *_retval) {
+ *_retval = FALSE;
+ if (mPlugin)
+ *_retval = mPlugin->playMovieAt(position);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsScriptablePeer::PlaylistNext(PRInt32 *_retval) {
+ *_retval = FALSE;
+ if (mPlugin)
+ *_retval = mPlugin->playlistNext();
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsScriptablePeer::PlaylistPrev(PRInt32 *_retval) {
+ *_retval = FALSE;
+ if (mPlugin)
+ *_retval = mPlugin->playlistPrev();
+ return NS_OK;
+}
+
NS_IMETHODIMP nsScriptablePeer::GetMovieAt(PRInt32 position, char **_retval) {
*_retval = NULL;
if (mPlugin)
@@ -297,20 +318,6 @@
return NS_OK;
}
-NS_IMETHODIMP nsScriptablePeer::GetPlayPositionWithinMovie(PRInt32 *_retval) {
- *_retval = -1;
- if (mPlugin)
- *_retval = mPlugin->getPlayPositionWithinMovie();
- return NS_OK;
-}
-
-NS_IMETHODIMP nsScriptablePeer::SetPlayPositionWithinMovie(PRInt32 milliseconds, PRBool *_retval) {
- *_retval = FALSE;
- if (mPlugin)
- *_retval = mPlugin->setPlayPositionWithinMovie(milliseconds);
- return NS_OK;
-}
-
NS_IMETHODIMP nsScriptablePeer::RetrieveAnnotationsAt(PRInt32 position, char **_retval) {
*_retval = NULL;
if (mPlugin)
More information about the commits
mailing list