Author: fejj
Date: 2008-01-25 17:24:01 -0500 (Fri, 25 Jan 2008)
New Revision: 93963
Modified:
trunk/moon/src/ChangeLog
trunk/moon/src/media.cpp
trunk/moon/src/media.h
Log:
2008-01-25 Jeffrey Stedfast <[EMAIL PROTECTED]>
* media.cpp|h: Consolidated all of the bool state variables into a
single bitfield.
Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog 2008-01-25 21:27:30 UTC (rev 93962)
+++ trunk/moon/src/ChangeLog 2008-01-25 22:24:01 UTC (rev 93963)
@@ -1,3 +1,8 @@
+2008-01-25 Jeffrey Stedfast <[EMAIL PROTECTED]>
+
+ * media.cpp|h: Consolidated all of the bool state variables into a
+ single bitfield.
+
2008-01-25 Rolf Bjarne Kvinge <[EMAIL PROTECTED]>
* pipeline.h, pipeline.cpp: ProgressiveSource: Make the position we're
Modified: trunk/moon/src/media.cpp
===================================================================
--- trunk/moon/src/media.cpp 2008-01-25 21:27:30 UTC (rev 93962)
+++ trunk/moon/src/media.cpp 2008-01-25 22:24:01 UTC (rev 93963)
@@ -252,19 +252,34 @@
int MediaElement::MediaFailedEvent = -1;
int MediaElement::MediaOpenedEvent = -1;
-const char *media_element_states[] = { "Closed", "Opening", "Buffering",
"Playing", "Paused", "Stopped", "Error", NULL };
+enum MediaElementFlags {
+ Loaded = (1 << 0), // set once OnLoaded has been called
+ TryOpenOnLoaded = (1 << 1), // set if OnLoaded should call TryOpen
+ PlayRequested = (1 << 2), // set if Play() has been requested
prior to being ready
+ BufferingMedia = (1 << 3), // set if TryOpen() succeeded and we are
now buffering
+ DisableBuffering = (1 << 4), // set if we cannot give useful
buffering progress
+ DownloadComplete = (1 << 5), // set if the download is complete
+ UpdatingPosition = (1 << 6), // set if we are updating the
PositionProperty as opposed to someone else
+ RecalculateMatrix = (1 << 7) // set if the patern matrix needs to be
recomputed
+};
+
+
+const char *media_element_states[] = { "Closed", "Opening", "Buffering",
"Playing", "Paused", "Stopped", "Error" };
+
const char *
-MediaElement::GetStateName (State state)
+MediaElement::GetStateName (MediaElementState state)
{
- if ((int) state >= 0 && (int) state <= Error) {
- return media_element_states [state];
- } else {
- return NULL;
- }
+ int i = (int) state;
+
+ if (i >= 0 && i < (int) G_N_ELEMENTS (media_element_states))
+ return media_element_states[i];
+
+ return NULL;
}
-static MediaResult marker_callback (MediaClosure *closure)
+static MediaResult
+marker_callback (MediaClosure *closure)
{
MediaElement *element = (MediaElement *) closure->context;
MediaMarker *marker = closure->marker;
@@ -326,7 +341,7 @@
col = new TimelineMarkerCollection ();
while (current != NULL) {
- MediaMarker* marker = current->marker;
+ MediaMarker *marker = current->marker;
TimelineMarker *new_marker = new TimelineMarker ();
new_marker->SetValue (TimelineMarker::TextProperty,
marker->Text ());
new_marker->SetValue (TimelineMarker::TypeProperty,
marker->Type ());
@@ -412,14 +427,13 @@
advanced = mplayer->AdvanceFrame ();
- position = mplayer->Position ();
- position *= TIMESPANTICKS_IN_SECOND / 1000;
+ position = mplayer->Position () * (TIMESPANTICKS_IN_SECOND / 1000);
if (advanced) {
- updating = true;
//printf ("MediaElement::AdvanceFrame (): advanced, setting
position to: %lld\n", position);
+ flags |= UpdatingPosition;
media_element_set_position (this, position);
- updating = false;
+ flags &= ~UpdatingPosition;
}
CheckMarkers (previous_position, position);
@@ -446,18 +460,17 @@
return (gboolean) media->AdvanceFrame ();
}
-MediaElement::MediaElement ()
+MediaElement::MediaElement ()
{
- media = NULL;
+ streamed_markers = NULL;
downloaded_file = NULL;
- streamed_markers = NULL;
downloader = NULL;
part_name = NULL;
mplayer = NULL;
- loaded = false;
- play_pending = false;
+ media = NULL;
+ flags = 0;
- Cleanup ();
+ Reinitialize ();
mplayer = new MediaPlayer ();
@@ -467,17 +480,19 @@
MediaElement::~MediaElement ()
{
- Cleanup ();
+ Reinitialize ();
delete mplayer;
}
void
-MediaElement::Cleanup ()
-{
- if (mplayer != NULL)
+MediaElement::Reinitialize ()
+{
+ Value *val;
+
+ if (mplayer)
mplayer->Close ();
-
+
if (media != NULL) {
// Media will delete its source upon destruction
// so clear out our reference if they're the same.
@@ -488,35 +503,26 @@
media = NULL;
}
+ flags = (flags & (Loaded | PlayRequested)) | RecalculateMatrix;
+ prev_state = Closed;
state = Closed;
- previous_state = Closed;
- recalculate_matrix = true;
+ DownloaderAbort ();
+ g_free (part_name);
+ part_name = NULL;
- // loaded = false; // OnLoaded is only called once, so once 'loaded' is
set, keep it set
- download_complete = false;
- waiting_for_loaded = false;
- updating = false;
- // play_pending = false; // Halo breaks if we reset this too..
- tried_buffering = false;
- previous_position = 0;
+ if (downloaded_file) {
+ delete downloaded_file;
+ downloaded_file = NULL;
+ }
- if (downloader)
- DownloaderAbort ();
- downloader = NULL;
-
buffering_start = 0;
- delete downloaded_file;
- downloaded_file = NULL;
- g_free (part_name);
- part_name = NULL;
-
if (streamed_markers)
streamed_markers->unref ();
streamed_markers = NULL;
-
- Value *val;
+ previous_position = 0;
+
val = GetValue (MediaElement::MarkersProperty);
if (val != NULL && val->AsCollection () != NULL)
val->AsCollection ()->Clear ();
@@ -626,11 +632,11 @@
cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
pattern = cairo_pattern_create_for_surface (surface);
-
- if (recalculate_matrix) {
+
+ if (flags & RecalculateMatrix) {
image_brush_compute_pattern_matrix (&matrix, w, h,
mplayer->width, mplayer->height, stretch,
AlignmentXCenter,
AlignmentYCenter, NULL, NULL);
- recalculate_matrix = false;
+ flags &= ~RecalculateMatrix;
}
cairo_pattern_set_matrix (pattern, &matrix);
@@ -713,29 +719,30 @@
}
void
-MediaElement::SetState (State new_state)
+MediaElement::SetState (MediaElementState state)
{
const char *name;
- if (new_state == Buffering && downloaded_file == NULL) {
+ if (state == Buffering && downloaded_file == NULL) {
// The code assumes that if Buffering then downloaded_file
isn't NULL
// (crashes might occur if this took place)
// So don't allow it to happen.
fprintf (stderr, "MediaElement::SetState (%d): Trying to change
to 'Buffering' "
- "but there's no file to save buffered data to.\n",
new_state);
+ "but there's no file to save buffered data to.\n",
state);
return;
}
- if (state != new_state) {
- previous_state = state;
- if (!(name = GetStateName (new_state))) {
- printf ("MediaElement::SetState (%d) state is not
valid.\n", new_state);
+ if (this->state != state) {
+ if (!(name = GetStateName (state))) {
+ printf ("MediaElement::SetState (%d) state is not
valid.\n", state);
return;
}
//printf ("MediaElement::SetState (%d): New state: %s\n",
new_state, state_name);
- state = new_state;
+ prev_state = this->state;
+ this->state = state;
+
media_element_set_current_state (this, name);
}
}
@@ -744,20 +751,19 @@
MediaElement::DataWrite (void *buf, int32_t offset, int32_t n)
{
//printf ("MediaElement::DataWrite (%p, %d, %d)\n", buf, offset, n);
-
+
if (downloaded_file != NULL) {
downloaded_file->Write (buf, offset, n);
-
+
// FIXME: How much do we actually have to download in order to
try to open the file?
- if (!tried_buffering && offset > 32000 && (part_name == NULL ||
part_name [0] == 0)) {
- tried_buffering = true;
+ if (!(flags & BufferingMedia) && offset > 1024 && (part_name ==
NULL || part_name[0] == 0))
TryOpen ();
- }
}
// Delay the propogating progress 1.0 until
// the downloader has notified us it is done.
double progress = downloader->GetValue
(Downloader::DownloadProgressProperty)->AsDouble ();
+
if (progress < 1.0)
UpdateProgress ();
}
@@ -792,11 +798,11 @@
return;
}
- switch (previous_state) {
+ switch (prev_state) {
case Opening: // Start playback
- if (media_element_get_auto_play (this) || play_pending)
+ if ((flags & PlayRequested) || media_element_get_auto_play
(this))
Play ();
- else
+ else
Pause ();
return;
case Playing: // Restart playback
@@ -809,7 +815,7 @@
case Buffering:
case Closed:
case Stopped: // This should not happen.
- printf ("MediaElement::BufferingComplete (): previous state is
invalid ('%s').\n", GetStateName (previous_state));
+ printf ("MediaElement::BufferingComplete (): previous state is
invalid ('%s').\n", GetStateName (prev_state));
return;
}
}
@@ -840,13 +846,13 @@
return;
}
- if (!loaded) {
+ if (!(flags & Loaded)) {
//printf ("MediaElement::TryOpen (): We're not loaded, so wait
until then.\n");
- waiting_for_loaded = true;
+ flags |= TryOpenOnLoaded;
return;
}
- if (download_complete) {
+ if (flags & DownloadComplete) {
char *filename = downloader_get_response_file (downloader,
part_name);
Media *media = new Media ();
IMediaSource *source;
@@ -860,7 +866,7 @@
SetState (Paused);
//printf ("MediaElement::TryOpen (): download
is complete and media opened successfully.\n");
- if (play_pending || media_element_get_auto_play
(this)) {
+ if ((flags & PlayRequested) ||
media_element_get_auto_play (this)) {
//printf ("MediaElement::TryOpen ():
we'll now start playing.\n");
Play ();
} else {
@@ -879,18 +885,19 @@
}
// If we have a downloaded file ourselves, delete it, we no
longer need it.
- delete downloaded_file;
- downloaded_file = NULL;
- } else if (part_name != NULL && part_name [0] != 0) {
+ if (downloaded_file) {
+ delete downloaded_file;
+ downloaded_file = NULL;
+ }
+ } else if (part_name != NULL && part_name[0] != 0) {
// PartName is set, we can't buffer, download the entire file.
- } else if (!tried_buffering) {
- // don't try to buffer again, wait until the file is downloaded.
- } else {
+ } else if (!(flags & BufferingMedia)) {
Media *media = new Media ();
if (MEDIA_SUCCEEDED (media->Open (downloaded_file))) {
-// printf ("MediaElement::TryOpen (): download is not
complete, but media was "
-// "opened successfully and we'll now start
buffering.\n");
+ //printf ("MediaElement::TryOpen (): download is not
complete, but media was "
+ // "opened successfully and we'll now start
buffering.\n");
+ flags |= BufferingMedia;
MediaOpened (media);
SetState (Buffering);
} else {
@@ -906,7 +913,7 @@
void
MediaElement::DownloaderComplete ()
{
- download_complete = true;
+ flags |= DownloadComplete;
UpdateProgress ();
@@ -925,7 +932,7 @@
case Buffering:
// Media finished downloading before the buffering time was
reached.
// Play it.
- if (media_element_get_auto_play (this) || play_pending)
+ if ((flags & PlayRequested) || media_element_get_auto_play
(this))
Play ();
else
Pause ();
@@ -946,9 +953,9 @@
MediaElement::SetSource (DependencyObject *dl, const char *PartName)
{
g_return_if_fail (dl->GetObjectType () == Type::DOWNLOADER);
-
- Cleanup ();
+ Reinitialize ();
+
downloader = (Downloader *) dl;
downloader->ref ();
part_name = g_strdup (PartName);
@@ -956,8 +963,11 @@
SetState (Opening);
if (downloader->Started ()) {
- disable_buffering = true;
- download_complete = downloader->Completed ();
+ flags |= DisableBuffering;
+
+ if (downloader->Completed ())
+ flags |= DownloadComplete;
+
TryOpen ();
} else {
downloaded_file = new ProgressiveSource (mplayer->media);
@@ -968,14 +978,14 @@
downloader->SetWriteFunc (data_write, size_notify, this);
}
- if (!download_complete)
+ if (!(flags & DownloadComplete))
downloader->AddHandler (downloader->CompletedEvent,
downloader_complete, this);
-
+
// This is what actually triggers the download
if (downloaded_file != NULL)
downloader->Send ();
- Invalidate ();
+ Invalidate ();
}
void
@@ -983,7 +993,7 @@
{
switch (state) {
case Opening:// docs: No specified behaviour
- play_pending = false; // This seems to be the actual behaviour
+ flags &= ~PlayRequested;
return;
case Closed: // docs: No specified behaviour
case Error: // docs: ? (says nothing)
@@ -998,7 +1008,6 @@
}
break;
}
-
}
void
@@ -1007,7 +1016,7 @@
switch (state) {
case Closed: // docs: No specified behaviour
case Opening:// docs: No specified behaviour
- play_pending = true; // This seems to be the actual behaviour
+ flags |= PlayRequested;
return;
case Error: // docs: ? (says nothing)
case Playing:// docs: no-op
@@ -1016,7 +1025,7 @@
case Paused:
case Stopped: // docs: start playing
mplayer->Play (media_element_advance_frame, this);
- play_pending = false;
+ flags &= ~PlayRequested;
SetState (Playing);
break;
}
@@ -1027,7 +1036,7 @@
{
switch (state) {
case Opening:// docs: No specified behaviour
- play_pending = false; // This seems to be the actual behaviour
+ flags &= ~PlayRequested;
return;
case Closed: // docs: No specified behaviour
case Error: // docs: ? (says nothing)
@@ -1050,9 +1059,9 @@
uint64_t position = mplayer->Position ();
Value v = Value (position * TIMESPANTICKS_IN_SECOND / 1000,
Type::TIMESPAN);
- updating = true;
+ flags |= UpdatingPosition;
SetValue (prop, &v);
- updating = false;
+ flags &= ~UpdatingPosition;
}
return MediaBase::GetValue (prop);
@@ -1069,7 +1078,10 @@
{
Value v;
- if (prop == MediaElement::PositionProperty && !updating) {
+ if (prop == MediaElement::PositionProperty && !(flags &
UpdatingPosition)) {
+ // Some outside source is updating the Position
+ // property which means we need to Seek
+
switch (state) {
case Opening:
case Closed:
@@ -1082,6 +1094,7 @@
case Stopped: // Paused
break;
}
+
// Buffering, Playing: playing
// Paused, Stopped: paused
@@ -1113,9 +1126,10 @@
void
MediaElement::OnLoaded ()
{
- if (!loaded) {
- loaded = true;
- if (waiting_for_loaded)
+ if (!(flags & Loaded)) {
+ flags |= Loaded;
+
+ if (flags & TryOpenOnLoaded)
TryOpen ();
}
@@ -1138,13 +1152,11 @@
DownloaderAbort ();
}
- recalculate_matrix = true;
+ flags |= RecalculateMatrix;
} else if (prop == MediaElement::AudioStreamCountProperty) {
// read-only property
} else if (prop == MediaElement::AudioStreamIndexProperty) {
- if (!updating) {
- // FIXME: set the audio stream index
- }
+ // FIXME: set the audio stream index
} else if (prop == MediaElement::AutoPlayProperty) {
// no state to change
//printf ("AutoPlay set to %s\n", media_element_get_auto_play
(this) ? "true" : "false");
@@ -1153,9 +1165,7 @@
} else if (prop == MediaElement::BufferingProgressProperty) {
Emit (BufferingProgressChangedEvent);
} else if (prop == MediaElement::BufferingTimeProperty) {
- if (!updating) {
- // FIXME: set the buffering time
- }
+ // FIXME: set the buffering time
} else if (prop == MediaElement::CanPauseProperty) {
// read-only property
} else if (prop == MediaElement::CanSeekProperty) {
@@ -1170,10 +1180,10 @@
// read-only property
} else if (prop == MediaElement::NaturalVideoHeightProperty) {
// read-only property
- recalculate_matrix = true;
+ flags |= RecalculateMatrix;
} else if (prop == MediaElement::NaturalVideoWidthProperty) {
// read-only property
- recalculate_matrix = true;
+ flags |= RecalculateMatrix;
} else if (prop == MediaElement::PositionProperty) {
if (IsPlaying() && mplayer->HasVideo ())
Invalidate ();
@@ -1186,7 +1196,7 @@
} else {
// propagate to parent class
MediaBase::OnPropertyChanged (prop);
- recalculate_matrix = true;
+ flags |= RecalculateMatrix;
}
}
Modified: trunk/moon/src/media.h
===================================================================
--- trunk/moon/src/media.h 2008-01-25 21:27:30 UTC (rev 93962)
+++ trunk/moon/src/media.h 2008-01-25 22:24:01 UTC (rev 93963)
@@ -24,6 +24,7 @@
#include "brush.h"
#include "frameworkelement.h"
+
class MediaAttribute : public DependencyObject {
public:
static DependencyProperty *ValueProperty;
@@ -36,6 +37,7 @@
const char *media_attribute_get_value (MediaAttribute *attribute);
void media_attribute_set_value (MediaAttribute *attribute, const char *value);
+
class MediaBase : public FrameworkElement {
public:
static DependencyProperty *SourceProperty;
@@ -58,6 +60,7 @@
void media_base_set_download_progress (MediaBase *media, double progress);
double media_base_get_download_progress (MediaBase *media);
+
class Image : public MediaBase {
bool create_xlib_surface;
@@ -96,7 +99,8 @@
// pattern caching
cairo_pattern_t *pattern;
- public:
+
+public:
Image ();
virtual ~Image ();
@@ -127,6 +131,7 @@
Image *image_new (void);
void image_set_source (Image *img, DependencyObject *Downloader, const char
*PartName);
+
class MediaSource {
protected:
MediaElement *element;
@@ -154,13 +159,15 @@
static MediaSource *CreateSource (MediaElement *element, const char
*source_name, IMediaSource *source);
};
+
class SingleMedia : public MediaSource {
-private:
guint advance_frame_timeout_id;
void ClearTimeout ();
+
protected:
virtual bool OpenInternal ();
+
public:
SingleMedia (MediaElement *element, const char *source_name,
IMediaSource *source);
virtual ~SingleMedia ();
@@ -174,29 +181,10 @@
class MediaElement : public MediaBase {
public:
- // SetSource () is called
- // - We start downloading the content. => 'Opening'
- // When x bytes have been downloaded and there's no PartName
- // - try to open the media (i.e. read the header)
- // - if successful, emit MediaOpened, and do buffered download =>
'Buffering', otherwise normal download
- // When buffered download has finished
- // - start playing the file (if autoplay) => 'Playing', otherwise =>
'Paused'
- // When normal download has finished
- // - try to open the media and emit MediaOpened/MediaFailed => Error
- // - start playing the file (if autoplay) => 'Playing', otherwise =>
'Paused'
-
- //
- // Relevant links:
- // http://msdn2.microsoft.com/en-us/library/bb980165.aspx (MediaElement
States)
- enum State {
- // The default state
+ enum MediaElementState {
Closed,
- // After setting a source, and until we have enough data to
read the headers, we are 'Opening'
Opening,
- // When the headers are read, switch to 'Buffering' (unless the
entire file has been downloaded)
Buffering,
- // When finished buffering or downloading, start 'Playing'.
- // We might change automatically to 'Buffering' if we run out
of data.
Playing,
Paused,
Stopped,
@@ -204,79 +192,48 @@
};
private:
+
// The current state of the media element.
- State state;
+ MediaElementState state;
// this is used to know what to do after a Buffering state finishes
- State previous_state;
+ MediaElementState prev_state;
- // we can't do anything until OnLoaded has been called
- // so track if it has been called, and if we're waiting
- // for it to be called
- bool loaded;
- bool waiting_for_loaded;
+ uint32_t flags;
- // When enough of a file has been downloaded to try to open
- // and buffer it, and the open fails, don't try again.
- bool tried_buffering;
-
- // Don't try to buffer if the download is already finished.
- bool download_complete;
-
- // If SetSource is called with a Downloader that has started,
- // disable buffering (since can't get the start of the file).
- bool disable_buffering;
-
- // Halo seems to require this
- // set to true the Play () is called before the media has
- // been opened, and causes Play () to be called when the
- // media has been loaded.
- bool play_pending;
-
- // The position property is not
- // updated as we're playing, it's updated when
- // requested in GetValue, and only then the current
- // position is saved in SetValue.
- // This should however not cause SetValue's handling
- // of the position property to do anything, so keep
- // track of when we're setting the position property
- // ourselves.
- bool updating;
-
int64_t buffering_start;
- ProgressiveSource *downloaded_file;
- Media *media;
-
bool recalculate_matrix;
cairo_matrix_t matrix;
+ TimelineMarkerCollection *streamed_markers;
+
// When checking if a marker has been reached, we need to
// know the last time the check was made, to see if
// the marker's pts hit the region.
uint64_t previous_position;
- TimelineMarkerCollection *streamed_markers;
-
- virtual void OnLoaded ();
-
- void UpdateProgress ();
-
// downloader methods/data
+ ProgressiveSource *downloaded_file;
Downloader *downloader;
- //MediaSource *source;
char *part_name;
+ Media *media;
- void Cleanup ();
void DataWrite (void *data, int32_t offset, int32_t n);
void DownloaderAbort ();
void DownloaderComplete ();
void BufferingComplete ();
+ void UpdateProgress ();
+ void Reinitialize ();
+ virtual void OnLoaded ();
+
// Try to open the media (i.e. read the headers).
void TryOpen ();
+
// Fill in all information from the opened media and raise
MediaOpenedEvent. Does not change any state.
void MediaOpened (Media *media);
+
// Reset all information to defaults, set state to 'Error' and raise
MediaFailedEvent
void MediaFailed ();
@@ -347,10 +304,11 @@
bool IsPaused () { return state == Paused; }
bool IsStopped () { return state == Stopped; }
- void SetState (State new_state);
- State GetState () { return state; }
- static const char *GetStateName (State state);
+ static const char *GetStateName (MediaElementState state);
+ MediaElementState GetState () { return state; }
+ void SetState (MediaElementState state);
+
virtual bool EnableAntiAlias ()
{
return !(absolute_xform.xx == absolute_xform.yy /* no rotation
*/
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches