mng_retcode mng_display_restart(mng_handle mngh) { mng_anim *mng = mng_get_userdata(mngh); mng->displayed_first = 0; return mng_display_reset(mngh); }
bool CMNGAnimation::ReadNextFrame(RGBA* frame_buffer) { if (m_first_display) { mng_display(m_stream); m_first_display = false; } else { if (mng_display_resume(m_stream) != MNG_NEEDTIMERWAIT) { mng_display_reset(m_stream); // repeat } } // convert the buffers into frame_buffer memcpy(frame_buffer, m_frame_buffer, m_width * m_height * sizeof(RGBA)); return true; }
/** * \brief MPlayer callback: Seek in MNG stream. * \param[in] demuxer demuxer structure * \param[in] rel_seek_secs relative seek time in seconds * \param[in] audio_delay unused, MNG does not contain audio * \param[in] flags bit flags, \p 1: absolute, \p 2: fractional position */ static void demux_mng_seek(demuxer_t * demuxer, float rel_seek_secs, float audio_delay, int flags) { mng_priv_t * mng_priv = demuxer->priv; mng_handle h_mng = mng_priv->h_mng; mng_retcode mng_ret; int seek_ms, pos_ms; // exit if not ready to seek (header not yet read or not yet displaying) if (!mng_priv->header_processed || !mng_priv->displaying) return; // get number of milliseconds to seek to if (flags & 2) // seek by fractional position (0.0 ... 1.0) seek_ms = (int)(rel_seek_secs * (float)mng_priv->total_time_ms); else // seek by time in seconds seek_ms = (int)(rel_seek_secs * 1000.0f + 0.5f); // get new position in milliseconds if (flags & 1) // absolute pos_ms = seek_ms; else // relative pos_ms = mng_priv->show_cur_time_ms + seek_ms; // fix position if (pos_ms < 0) pos_ms = 0; if (pos_ms > mng_priv->total_time_ms) pos_ms = mng_priv->total_time_ms; // FIXME // In principle there is a function to seek in MNG: mng_display_gotime(). // - Using it did not work out (documentation is very brief, // example code does not exist?). // - The following code works, but its performance is quite bad. // seeking forward if (pos_ms >= mng_priv->show_cur_time_ms) { // Simply advance show time to seek position. // - Everything else will be handled in demux_mng_fill_buffer(). mng_priv->show_next_time_ms = pos_ms; } // if (pos_ms > mng_priv->show_time_ms) // seeking backward else { // if (pos_ms > mng_priv->show_time_ms) // Clear variable MNG library will write number of milliseconds to // (via settimer callback). mng_priv->timer_ms = 0; // Restart displaying and advance show time to seek position. // - Everything else will be handled in demux_mng_fill_buffer(). mng_ret = mng_display_reset(h_mng); // If a timer wait is needed, fool libmng that requested time // passed and try again. if (mng_ret == MNG_NEEDTIMERWAIT) { mng_priv->global_time_ms += mng_priv->timer_ms; mng_ret = mng_display_reset(h_mng); } if (mng_ret) { mp_msg(MSGT_DEMUX, MSGL_ERR, "demux_mng: could not reset MNG display state: " "mng_retcode %d\n", mng_ret); return; } mng_priv->displaying = 0; mng_priv->finished = 0; mng_priv->anim_cur_time_ms = 0; mng_priv->anim_frame_duration_ms = 0; mng_priv->show_next_time_ms = pos_ms; } // if (pos_ms > mng_priv->show_time_ms) ... else }
/** ** Reset a MNG */ void Mng::Reset() { mng_display_reset(handle); iteration = 0; mng_display(handle); }
static void ContextMenu(PluginInstance *This, HWND hwnd) { int cmd; HMENU menu; POINT pt; unsigned char buf[MAX_PATH], buf2[200]; pt.x=0; pt.y=0; GetCursorPos(&pt); // create context menu dynamically menu=CreatePopupMenu(); if(This->errorflag) { AppendMenu(menu,MF_ENABLED,ID_SHOWERROR,"SHOW ERROR MESSAGE"); AppendMenu(menu,MF_SEPARATOR,0,NULL); } AppendMenu(menu,(This->loadstate>=STATE_LOADED?MF_ENABLED:MF_GRAYED),ID_SAVEAS,"Save Image &As..."); AppendMenu(menu,(This->lpdib?MF_ENABLED:MF_GRAYED),ID_COPYIMAGE,"&Copy Image"); AppendMenu(menu,MF_ENABLED,ID_COPYURL,"Cop&y Image Location"); if(This->islink) { AppendMenu(menu,MF_ENABLED,ID_COPYLINKLOC,"Copy Link Location"); } url2filename(buf,This->url); escapeformenu(buf); if(lstrlen(buf)) { wsprintf(buf2,"View Image (%s)",buf); } else { wsprintf(buf2,"View Image"); } AppendMenu(menu,MF_ENABLED,ID_VIEWIMAGE,buf2); AppendMenu(menu,MF_SEPARATOR,0,NULL); // AppendMenu(menu,(This->mng?MF_ENABLED:MF_GRAYED),ID_STOPANIM,"Stop Animation"); AppendMenu(menu,(This->mng?MF_ENABLED:MF_GRAYED)| (This->frozen?MF_CHECKED:MF_UNCHECKED),ID_FREEZE,"&Freeze Animation"); // AppendMenu(menu,(This->mng?MF_ENABLED:MF_GRAYED),ID_RESTARTANIM,"Restart Animation"); AppendMenu(menu,MF_SEPARATOR,0,NULL); AppendMenu(menu,MF_ENABLED,ID_PROPERTIES,"Properties..."); AppendMenu(menu,MF_ENABLED,ID_ABOUT,"About MNG Plug-in..."); cmd=TrackPopupMenuEx(menu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_NONOTIFY|TPM_RETURNCMD| TPM_RIGHTBUTTON,pt.x,pt.y,hwnd,NULL); DestroyMenu(menu); switch(cmd) { case ID_STOPANIM: if(This->mng) { KillTimer(This->fhWnd,1); This->timer_set=0; mng_display_freeze(This->mng); } break; case ID_FREEZE: This->frozen = !This->frozen; if(This->frozen) { KillTimer(This->fhWnd,1); This->timer_set=0; mng_display_freeze(This->mng); } else { handle_read_error(This, mng_display_resume(This->mng) ); } break; case ID_RESTARTANIM: if(!This->frozen) { KillTimer(This->fhWnd,1); This->timer_set=0; mng_display_freeze(This->mng); } This->frozen=1; mng_display_reset(This->mng); This->frozen=0; handle_read_error(This, mng_display_resume(This->mng) ); break; case ID_SAVEAS: SaveImage(This); break; case ID_COPYIMAGE: if(This->lpdib) { CopyToClipboard(This,(unsigned char*)This->lpdib,This->dibsize,CF_DIB); } else { warn(This,"No image to copy"); } break; case ID_COPYURL: CopyToClipboard(This,This->url,lstrlen(This->url)+1,CF_TEXT); break; case ID_COPYLINKLOC: if(This->islink) { CopyToClipboard(This,This->linkurl,lstrlen(This->linkurl)+1,CF_TEXT); } break; case ID_VIEWIMAGE: if(lstrlen(This->url)) NPN_GetURL(This->instance,This->url,"_self"); break; case ID_PROPERTIES: PropDialog(This); break; case ID_ABOUT: AboutDialog(This); break; case ID_SHOWERROR: display_last_error(This); break; } }