MythTV  0.26-pre
glsingleview.cpp
Go to the documentation of this file.
00001 /* ============================================================
00002  * File  : glsingleview.cpp
00003  * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
00004  * Date  : 2004-01-13
00005  * Description :
00006  *
00007  * Copyright 2004 by Renchi Raju
00008  *
00009  * This program is free software; you can redistribute it
00010  * and/or modify it under the terms of the GNU General
00011  * Public License as published bythe Free Software Foundation;
00012  * either version 2, or (at your option)
00013  * any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * ============================================================ */
00021 
00022 // Include own header first to catch missing includes
00023 #include "glsingleview.h"
00024 
00025 // ANSI C headers
00026 #include <cmath>
00027 
00028 // C++ headers
00029 #include <algorithm>
00030 using namespace std;
00031 
00032 // Qt headers
00033 #include <QTimer>
00034 #include <QImage>
00035 #include <QDir>
00036 #include <QPainter>
00037 #include <qbuffer.h>
00038 
00039 // MythTV plugin headers
00040 #include <mythcontext.h>
00041 #include <mythmiscutil.h>
00042 #include <mythuihelper.h>
00043 #include "mythlogging.h"
00044 
00045 // MythGallery headers
00046 #include "galleryutil.h"
00047 
00048 #define LOC QString("GLView: ")
00049 
00050 GLSDialog::GLSDialog(const ThumbList& itemList,
00051                      int *pos, int slideShow, int sortOrder,
00052                      MythMainWindow *parent, const char *name)
00053     : MythDialog(parent, name)
00054 {
00055     QBoxLayout *l = new QVBoxLayout(this);
00056     l->setContentsMargins(0, 0, 0, 0);
00057     m_view = new GLSingleView(itemList, pos, slideShow, sortOrder, this);
00058     l->addWidget(m_view);
00059 
00060     setFocusProxy(m_view);
00061     m_view->setFocus();
00062 }
00063 
00064 // Have to clean up with this dirty hack because
00065 // qglwidget segfaults with a destructive close
00066 
00067 void GLSDialog::closeEvent(QCloseEvent *e)
00068 {
00069     m_view->CleanUp();
00070     e->accept();
00071 
00072     accept();
00073 }
00074 
00075 GLSingleView::GLSingleView(ThumbList itemList, int *pos, int slideShow,
00076                            int sortorder, QWidget *parent)
00077     : QGLWidget(parent),
00078       ImageView(itemList, pos, slideShow, sortorder),
00079       // General
00080       m_source_x(0.0f),
00081       m_source_y(0.0f),
00082       m_scaleMax(kScaleToFit),
00083 
00084       // Texture variables (for display and effects)
00085       m_texMaxDim(512),
00086       m_texSize(512,512),
00087       m_texCur(0),
00088       m_tex1First(true),
00089 
00090       // Info variables
00091       m_texInfo(0),
00092 
00093       // Common effect state variables
00094       m_effect_rotate_direction(0),
00095       m_effect_transition_timeout(2000),
00096       m_effect_transition_timeout_inv(1.0f / m_effect_transition_timeout),
00097 
00098       // Unshared effect state variables
00099       m_effect_cube_xrot(0.0f),
00100       m_effect_cube_yrot(0.0f),
00101       m_effect_cube_zrot(0.0f),
00102       m_effect_kenBurns_image_ready(true),
00103       m_effect_kenBurns_initialized(false),
00104       m_effect_kenBurns_new_image_started(true)
00105 {
00106     m_scaleMax = (ScaleMax) gCoreContext->GetNumSetting("GalleryScaleMax", 0);
00107 
00108     m_slideshow_timer = new QTimer(this);
00109     RegisterEffects();
00110 
00111     // --------------------------------------------------------------------
00112 
00113     setFocusPolicy(Qt::WheelFocus);
00114 
00115     // --------------------------------------------------------------------
00116 
00117     QString transType = gCoreContext->GetSetting("SlideshowOpenGLTransition");
00118     if (!transType.isEmpty() && m_effect_map.contains(transType))
00119         m_effect_method = m_effect_map[transType];
00120 
00121     if (m_effect_method.isEmpty() || transType == QString("random (gl)"))
00122     {
00123         m_effect_method = GetRandomEffect();
00124         m_effect_random = true;
00125     }
00126 
00127     SetTransitionTimeout(gCoreContext->GetNumSetting(
00128                              "SlideshowOpenGLTransitionLength", 2000));
00129 
00130     // --------------------------------------------------------------------
00131 
00132     connect(m_slideshow_timer, SIGNAL(timeout()), this, SLOT(SlideTimeout()));
00133 
00134     // --------------------------------------------------------------------
00135 
00136     if (slideShow)
00137     {
00138         m_slideshow_running = true;
00139         m_slideshow_timer->stop();
00140         m_slideshow_timer->setSingleShot(true);
00141         m_slideshow_timer->start(m_slideshow_frame_delay_state);
00142         GetMythUI()->DisableScreensaver();
00143     }
00144 }
00145 
00146 GLSingleView::~GLSingleView()
00147 {
00148     // save the current m_scaleMax setting so we can restore it later
00149     gCoreContext->SaveSetting("GalleryScaleMax", m_scaleMax);
00150     CleanUp();
00151 }
00152 
00153 void GLSingleView::CleanUp(void)
00154 {
00155     makeCurrent();
00156 
00157     if (m_slideshow_timer)
00158     {
00159         m_slideshow_timer->stop();
00160         m_slideshow_timer->deleteLater();
00161         m_slideshow_timer = NULL;
00162     }
00163 
00164     m_texItem[0].Deinit();
00165     m_texItem[1].Deinit();
00166 
00167     if (m_texInfo)
00168         glDeleteTextures(1, &m_texInfo);
00169 }
00170 
00171 void GLSingleView::initializeGL(void)
00172 {
00173     // Enable Texture Mapping
00174     glEnable(GL_TEXTURE_2D);
00175     // Clear The Background Color
00176     glClearColor(0.0, 0.0, 0.0, 1.0f);
00177 
00178     // Turn Blending On
00179     glEnable(GL_BLEND);
00180     // Blending Function For Translucency Based On Source Alpha Value
00181     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00182 
00183     // Enable perspective vision
00184     glClearDepth(1.0f);
00185 
00186     GLint param;
00187     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &param);
00188     m_texMaxDim = param;
00189 
00190     Load();
00191 }
00192 
00193 void GLSingleView::resizeGL(int w, int h)
00194 {
00195     // Reset The Current Viewport And Perspective Transformation
00196     glViewport(0, 0, (GLint)w, (GLint)h);
00197 
00198     glMatrixMode(GL_PROJECTION);
00199     glLoadIdentity();
00200 }
00201 
00202 void GLSingleView::paintGL(void)
00203 {
00204     if (1 == m_movieState)
00205     {
00206         m_movieState = 2;
00207 
00208         ThumbItem *item = m_itemList.at(m_pos);
00209 
00210         if (item)
00211             GalleryUtil::PlayVideo(item->GetPath());
00212 
00213         if (!m_slideshow_running && item)
00214         {
00215             QImage image;
00216             GetScreenShot(image, item);
00217             if (image.isNull())
00218                 return;
00219 
00220             image = image.scaled(800, 600);
00221 
00222             // overlay "Press SELECT to play again" text
00223             QPainter p(&image);
00224             QRect rect = QRect(20, image.height() - 100,
00225                                image.width() - 40, 80);
00226             p.fillRect(rect, QBrush(QColor(0,0,0,100)));
00227             p.setFont(QFont("Arial", 25, QFont::Bold));
00228             p.setPen(QColor(255,255,255));
00229             p.drawText(rect, Qt::AlignCenter, tr("Press SELECT to play again"));
00230             p.end();
00231 
00232             m_texSize = QSize(
00233                 GetNearestGLTextureSize(image.size().width()),
00234                 GetNearestGLTextureSize(image.size().height()));
00235             int a = m_tex1First ? 0 : 1;
00236             m_texItem[a].SetItem(item, image.size());
00237             m_texItem[a].ScaleTo(m_screenSize, m_scaleMax);
00238             m_texItem[a].Init(convertToGLFormat(
00239                                   image.scaled(m_texSize,
00240                                                Qt::IgnoreAspectRatio,
00241                                                Qt::SmoothTransformation)));
00242         }
00243     }
00244 
00245     glDisable(GL_DEPTH_TEST);
00246 
00247     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00248     glLoadIdentity();
00249 
00250     glMatrixMode(GL_PROJECTION);
00251     glLoadIdentity();
00252 
00253     glMatrixMode(GL_MODELVIEW);
00254     glLoadIdentity();
00255 
00256     if (m_effect_running && !m_effect_method.isEmpty())
00257     {
00258         RunEffect(m_effect_method);
00259     }
00260     else
00261     {
00262         paintTexture();
00263     }
00264 
00265     if (glGetError())
00266         LOG(VB_GENERAL, LOG_ERR, LOC + "OpenGL error detected");
00267 }
00268 
00269 void GLSingleView::keyPressEvent(QKeyEvent *e)
00270 {
00271     bool handled    = false;
00272 
00273     bool wasRunning = m_slideshow_running;
00274     m_slideshow_timer->stop();
00275     m_slideshow_running = false;
00276     GetMythUI()->RestoreScreensaver();
00277     m_effect_running = false;
00278     m_slideshow_frame_delay_state = m_slideshow_frame_delay * 1000;
00279 
00280     bool wasInfo = m_info_show;
00281     m_info_show = false;
00282     bool wasInfoShort = m_info_show_short;
00283     m_info_show_short = false;
00284 
00285     QStringList actions;
00286     handled = GetMythMainWindow()->TranslateKeyPress("Gallery", e, actions);
00287 
00288     float scrollX = 0.2f;
00289     float scrollY = 0.2f;
00290 
00291     for (int i = 0; i < actions.size() && !handled; i++)
00292     {
00293         QString action = actions[i];
00294         handled = true;
00295 
00296         if (action == "LEFT" || action == "UP")
00297         {
00298             m_info_show = wasInfo;
00299             m_slideshow_running = wasRunning;
00300             DisplayPrev(true, true);
00301         }
00302         else if (action == "RIGHT" || action == "DOWN")
00303         {
00304             m_info_show = wasInfo;
00305             m_slideshow_running = wasRunning;
00306             DisplayNext(true, true);
00307         }
00308         else if (action == "ZOOMOUT")
00309         {
00310             if (m_zoom > 0.5f)
00311             {
00312                 SetZoom(m_zoom - 0.5f);
00313                 if (m_zoom > 1.0f)
00314                 {
00315                     m_source_x   -= m_source_x / ((m_zoom + 0.5) * 2.0f);
00316                     m_source_y   -= m_source_y / ((m_zoom + 0.5) * 2.0f);
00317 
00318                     checkPosition();
00319                 }
00320                 else
00321                 {
00322                     m_source_x = 0;
00323                     m_source_y = 0;
00324                 }
00325             }
00326         }
00327         else if (action == "ZOOMIN")
00328         {
00329             if (m_zoom < 4.0f)
00330             {
00331                 SetZoom(m_zoom + 0.5f);
00332                 if (m_zoom > 1.0f)
00333                 {
00334                     m_source_x   += m_source_x / (m_zoom * 2.0f);
00335                     m_source_y   += m_source_y / (m_zoom * 2.0f);
00336 
00337                     checkPosition();
00338                 }
00339                 else
00340                 {
00341                     m_source_x = 0;
00342                     m_source_y = 0;
00343                 }
00344             }
00345         }
00346         else if (action == "FULLSIZE")
00347         {
00348             m_source_x = 0;
00349             m_source_y = 0;
00350             if (m_zoom != 1)
00351                 SetZoom(1.0f);
00352         }
00353         else if (action == "SCROLLLEFT")
00354         {
00355             if (m_zoom > 1.0f && m_source_x < m_zoom - 1.0f)
00356             {
00357                 m_source_x += scrollX;
00358                 m_source_x  = min(m_source_x, m_zoom - 1.0f);
00359             }
00360         }
00361         else if (action == "SCROLLRIGHT")
00362         {
00363             if (m_zoom > 1.0f && m_source_x > -m_zoom + 1.0f)
00364             {
00365                 m_source_x -= scrollX;
00366                 m_source_x  = max(m_source_x, -m_zoom + 1.0f);
00367             }
00368         }
00369         else if (action == "SCROLLDOWN")
00370         {
00371             if (m_zoom > 1.0f && m_source_y <  m_zoom - 1.0f)
00372             {
00373                 m_source_y += scrollY;
00374                 m_source_y  = min(m_source_y,  m_zoom - 1.0f);
00375             }
00376         }
00377         else if (action == "SCROLLUP")
00378         {
00379             if (m_zoom > 1.0f && m_source_y > -m_zoom + 1.0f)
00380             {
00381                 m_source_y -= scrollY;
00382                 m_source_y  = max(m_source_y, -m_zoom + 1.0f);
00383             }
00384         }
00385         else if (action == "RECENTER")
00386         {
00387             if (m_zoom > 1.0f)
00388             {
00389                 m_source_x = 0.0f;
00390                 m_source_y = 0.0f;
00391             }
00392         }
00393         else if (action == "UPLEFT")
00394         {
00395             if (m_zoom > 1.0f)
00396             {
00397                 m_source_x  =  1.0f;
00398                 m_source_y  = -1.0f;
00399             }
00400         }
00401         else if (action == "LOWRIGHT")
00402         {
00403             if (m_zoom > 1.0f)
00404             {
00405                 m_source_x = -1.0f;
00406                 m_source_y =  1.0f;
00407             }
00408         }
00409         else if (action == "ROTRIGHT")
00410         {
00411             m_source_x = 0;
00412             m_source_y = 0;
00413             Rotate(90);
00414         }
00415         else if (action == "ROTLEFT")
00416         {
00417             m_source_x = 0;
00418             m_source_y = 0;
00419             Rotate(-90);
00420         }
00421         else if (action == "DELETE")
00422         {
00423             ThumbItem *item = m_itemList.at(m_pos);
00424             if (item && GalleryUtil::Delete(item->GetPath()))
00425             {
00426                 item->SetPixmap(NULL);
00427                 DisplayNext(true, true);
00428             }
00429             m_info_show = wasInfo;
00430             m_slideshow_running = wasRunning;
00431         }
00432         else if ((action == "PLAY" || action == "SELECT") && m_movieState == 2)
00433         {
00434             m_movieState = 1;
00435         }
00436         else if (action == "PLAY" || action == "SLIDESHOW" ||
00437                  action == "RANDOMSHOW")
00438         {
00439             m_source_x   = 0;
00440             m_source_y   = 0;
00441             SetZoom(1.0f);
00442             m_info_show = wasInfo;
00443             m_info_show_short = true;
00444             m_slideshow_running = !wasRunning;
00445         }
00446         else if (action == "INFO")
00447         {
00448             m_info_show = !wasInfo && !wasInfoShort;
00449             m_slideshow_running = wasRunning;
00450         }
00451         else if (action == "FULLSCREEN")
00452         {
00453             m_scaleMax = (ScaleMax) ((m_scaleMax + 1) % kScaleMaxCount);
00454             m_source_x = 0;
00455             m_source_y = 0;
00456             SetZoom(1.0f);
00457 
00458             int a = m_tex1First ? 0 : 1;
00459             m_texItem[a].ScaleTo(m_screenSize, m_scaleMax);
00460         }
00461         else
00462         {
00463             handled = false;
00464         }
00465     }
00466 
00467     if (m_slideshow_running || m_info_show_short)
00468     {
00469         m_slideshow_timer->stop();
00470         m_slideshow_timer->setSingleShot(true);
00471         m_slideshow_timer->start(m_slideshow_frame_delay_state);
00472     }
00473 
00474     if (m_slideshow_running)
00475     {
00476         GetMythUI()->DisableScreensaver();
00477     }
00478 
00479     updateGL();
00480 
00481     if (handled)
00482     {
00483         e->accept();
00484     }
00485     else {
00486         e->ignore();
00487     }
00488 }
00489 
00490 void  GLSingleView::checkPosition(void)
00491 {
00492     m_source_x = max(m_source_x, -m_zoom + 1.0f);
00493     m_source_y = max(m_source_y, -m_zoom + 1.0f);
00494     m_source_x = min(m_source_x, m_zoom - 1.0f);
00495     m_source_y = min(m_source_y, m_zoom - 1.0f);
00496 }
00497 
00498 void GLSingleView::paintTexture(void)
00499 {
00500     glMatrixMode(GL_MODELVIEW);
00501     glLoadIdentity();
00502 
00503     glTranslatef(m_source_x, m_source_y, 0.0f);
00504     glScalef(m_zoom, m_zoom, 1.0f);
00505 
00506     m_texItem[m_texCur].MakeQuad();
00507 
00508     if (m_info_show || m_info_show_short)
00509     {
00510         createTexInfo();
00511 
00512         glMatrixMode(GL_MODELVIEW);
00513         glLoadIdentity();
00514 
00515         glMatrixMode(GL_TEXTURE);
00516         glLoadIdentity();
00517 
00518         glBindTexture(GL_TEXTURE_2D, m_texInfo);
00519         glBegin(GL_QUADS);
00520         {
00521             glColor4f(1.0f, 1.0f, 1.0f, 0.72f);
00522             glTexCoord2f(0.0f, 0.0f);
00523             glVertex3f(-0.75f, -0.75f, 0.0f);
00524 
00525             glTexCoord2f(1.0f, 0.0f);
00526             glVertex3f(+0.75f, -0.75f, 0.0f);
00527 
00528             glTexCoord2f(1.0f, 1.0f);
00529             glVertex3f(+0.75f, +0.75f, 0.0f);
00530 
00531             glTexCoord2f(0.0f, 1.0f);
00532             glVertex3f(-0.75f, +0.75f, 0.0f);
00533         }
00534         glEnd();
00535     }
00536 }
00537 
00538 void GLSingleView::DisplayNext(bool reset, bool loadImage)
00539 {
00540     if (reset)
00541     {
00542         m_zoom     = 1.0f;
00543         m_source_x = 0.0f;
00544         m_source_y = 0.0f;
00545     }
00546 
00547     // Search for next item that hasn't been deleted.
00548     // Close viewer if none remain.
00549     ThumbItem *item;
00550     int oldpos = m_pos;
00551 
00552     while (true)
00553     {
00554         m_pos = m_slideshow_sequence->next();
00555         item = m_itemList.at(m_pos);
00556         if (item)
00557         {
00558             if (QFile::exists(item->GetPath()))
00559             {
00560                 break;
00561             }
00562         }
00563         if (m_pos == oldpos)
00564         {
00565             // No valid items!!!
00566             close();
00567         }
00568     }
00569 
00570     m_tex1First = !m_tex1First;
00571     m_texCur      = (m_texCur) ? 0 : 1;
00572 
00573     if (loadImage)
00574         Load();
00575 }
00576 
00577 void GLSingleView::DisplayPrev(bool reset, bool loadImage)
00578 {
00579     if (reset)
00580     {
00581         m_zoom     = 1.0f;
00582         m_source_x = 0.0f;
00583         m_source_y = 0.0f;
00584     }
00585 
00586     // Search for next item that hasn't been deleted.
00587     // Close viewer in none remain.
00588     int oldpos = m_pos;
00589     while (true)
00590     {
00591         m_pos = m_slideshow_sequence->prev();
00592 
00593         ThumbItem *item = m_itemList.at(m_pos);
00594         if (item && QFile::exists(item->GetPath()))
00595             break;
00596 
00597         if (m_pos == oldpos)
00598         {
00599             // No valid items!!!
00600             close();
00601         }
00602     };
00603 
00604     m_tex1First = !m_tex1First;
00605     m_texCur    = (m_texCur) ? 0 : 1;
00606 
00607     if (loadImage)
00608         Load();
00609 }
00610 
00611 void GLSingleView::Load(void)
00612 {
00613     m_movieState = 0;
00614     ThumbItem *item = m_itemList.at(m_pos);
00615     if (!item)
00616     {
00617         LOG(VB_GENERAL, LOG_ERR, LOC + QString("No item at %1").arg(m_pos));
00618         return;
00619     }
00620 
00621     if (GalleryUtil::IsMovie(item->GetPath()))
00622     {
00623         m_movieState = 1;
00624         return;
00625     }
00626 
00627     QImage image(item->GetPath());
00628     if (image.isNull())
00629         return;
00630 
00631     m_texSize = QSize(GetNearestGLTextureSize(image.size().width()),
00632                       GetNearestGLTextureSize(image.size().height()));
00633     int a = m_tex1First ? 0 : 1;
00634     m_texItem[a].SetItem(item, image.size());
00635     m_texItem[a].ScaleTo(m_screenSize, m_scaleMax);
00636     m_texItem[a].Init(convertToGLFormat(
00637         image.scaled(m_texSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)));
00638 
00639     UpdateLCD(item);
00640 }
00641 
00642 void GLSingleView::Rotate(int angle)
00643 {
00644     int ang = m_texItem[m_texCur].GetAngle() + angle;
00645 
00646     ang = (ang >= 360) ? ang - 360 : ang;
00647     ang = (ang < 0)    ? ang + 360 : ang;
00648 
00649     m_texItem[m_texCur].SetAngle(ang);
00650 
00651     ThumbItem *item = m_itemList.at(m_pos);
00652     if (item)
00653         item->SetRotationAngle(ang);
00654 
00655     m_texItem[m_texCur].SwapWidthHeight();
00656     m_texItem[m_texCur].ScaleTo(m_screenSize, m_scaleMax);
00657 }
00658 
00659 void GLSingleView::SetZoom(float zoom)
00660 {
00661     m_zoom = zoom;
00662 }
00663 
00664 void GLSingleView::SetTransitionTimeout(int timeout)
00665 {
00666     m_effect_transition_timeout = timeout;
00667     m_effect_transition_timeout_inv = 1.0f;
00668     if (timeout)
00669         m_effect_transition_timeout_inv = 1.0f / timeout;
00670 }
00671 
00672 int GLSingleView::GetNearestGLTextureSize(int v) const
00673 {
00674     int n = 0, last = 0;
00675     int s;
00676 
00677     for (s = 0; s < 32; ++s)
00678     {
00679         if (((v >> s) & 1) == 1)
00680         {
00681             ++n;
00682             last = s;
00683         }
00684     }
00685 
00686     if (n > 1)
00687         s = 1 << (last + 1);
00688     else
00689         s = 1 << last;
00690 
00691     return min(s, m_texMaxDim);
00692 }
00693 
00694 void GLSingleView::RegisterEffects(void)
00695 {
00696     m_effect_map.insert("none",            "EffectNone");
00697     m_effect_map.insert("blend (gl)",      "EffectBlend");
00698     m_effect_map.insert("zoom blend (gl)", "EffectZoomBlend");
00699     m_effect_map.insert("fade (gl)",       "EffectFade");
00700     m_effect_map.insert("rotate (gl)",     "EffectRotate");
00701     m_effect_map.insert("bend (gl)",       "EffectBend");
00702     m_effect_map.insert("inout (gl)",      "EffectInOut");
00703     m_effect_map.insert("slide (gl)",      "EffectSlide");
00704     m_effect_map.insert("flutter (gl)",    "EffectFlutter");
00705     m_effect_map.insert("cube (gl)",       "EffectCube");
00706     m_effect_map.insert("Ken Burns (gl)",  "EffectKenBurns");
00707 }
00708 
00709 void GLSingleView::RunEffect(const QString &effect)
00710 {
00711     if (effect == "EffectBlend")
00712         EffectBlend();
00713     else if (effect == "EffectZoomBlend")
00714         EffectZoomBlend();
00715     else if (effect == "EffectFade")
00716         EffectFade();
00717     else if (effect == "EffectRotate")
00718         EffectRotate();
00719     else if (effect == "EffectBend")
00720         EffectBend();
00721     else if (effect == "EffectInOut")
00722         EffectInOut();
00723     else if (effect == "EffectSlide")
00724         EffectSlide();
00725     else if (effect == "EffectFlutter")
00726         EffectFlutter();
00727     else if (effect == "EffectCube")
00728         EffectCube();
00729     else if (effect == "EffectKenBurns")
00730         EffectKenBurns();
00731     else //if (effect == "EffectNone")
00732         EffectNone();
00733 }
00734 
00735 void GLSingleView::EffectNone(void)
00736 {
00737     paintTexture();
00738     m_effect_running = false;
00739     m_slideshow_frame_delay_state = -1;
00740     return;
00741 }
00742 
00743 void GLSingleView::EffectBlend(void)
00744 {
00745     if (m_effect_frame_time.elapsed() > m_effect_transition_timeout)
00746     {
00747         paintTexture();
00748         m_effect_running = false;
00749         m_slideshow_frame_delay_state = -1;
00750         return;
00751     }
00752 
00753     float t = m_effect_frame_time.elapsed() * m_effect_transition_timeout_inv;
00754 
00755     m_texItem[(m_texCur) ? 0 : 1].MakeQuad();
00756 
00757     glBegin(GL_QUADS);
00758     {
00759         glColor4f(0.0f, 0.0f, 0.0f, 1.0f * t);
00760         glVertex3f(-1.0f, -1.0f, 0.0f);
00761         glVertex3f(+1.0f, -1.0f, 0.0f);
00762         glVertex3f(+1.0f, +1.0f, 0.0f);
00763         glVertex3f(-1.0f, +1.0f, 0.0f);
00764     }
00765     glEnd();
00766 
00767     m_texItem[m_texCur].MakeQuad(t);
00768 
00769     m_effect_current_frame++;
00770 }
00771 
00772 void GLSingleView::EffectZoomBlend(void)
00773 {
00774     if (m_effect_frame_time.elapsed() > m_effect_transition_timeout)
00775     {
00776         paintTexture();
00777         m_effect_running = false;
00778         m_slideshow_frame_delay_state = -1;
00779         return;
00780     }
00781 
00782     float t = m_effect_frame_time.elapsed() * m_effect_transition_timeout_inv;
00783 
00784     m_texItem[m_texCur ? 0 : 1].MakeQuad(1.0f - t, 1.0f + (0.75 * t));
00785     m_texItem[m_texCur].MakeQuad(t);
00786 
00787     m_effect_current_frame++;
00788 }
00789 
00790 void GLSingleView::EffectRotate(void)
00791 {
00792     if (m_effect_frame_time.elapsed() > m_effect_transition_timeout)
00793     {
00794         paintTexture();
00795         m_effect_running = false;
00796         m_slideshow_frame_delay_state = -1;
00797         return;
00798     }
00799 
00800     if (m_effect_current_frame == 0)
00801         m_effect_rotate_direction = (int)((2.0*random()/(RAND_MAX+1.0)));
00802 
00803     float t = m_effect_frame_time.elapsed() * m_effect_transition_timeout_inv;
00804 
00805     m_texItem[m_texCur].MakeQuad();
00806 
00807     glMatrixMode(GL_MODELVIEW);
00808     glLoadIdentity();
00809     float rotate = 360.0f * t;
00810     glRotatef(((m_effect_rotate_direction == 0) ? -1 : 1) * rotate,
00811               0.0f, 0.0f, 1.0f);
00812     float scale = 1.0f * (1.0f - t);
00813     glScalef(scale, scale, 1.0f);
00814 
00815     m_texItem[(m_texCur) ? 0 : 1].MakeQuad();
00816 
00817     m_effect_current_frame++;
00818 }
00819 
00820 void GLSingleView::EffectBend(void)
00821 {
00822     if (m_effect_frame_time.elapsed() > m_effect_transition_timeout)
00823     {
00824         paintTexture();
00825         m_effect_running = false;
00826         m_slideshow_frame_delay_state = -1;
00827         return;
00828     }
00829 
00830     if (m_effect_current_frame == 0)
00831         m_effect_rotate_direction = (int)((2.0f*random()/(RAND_MAX+1.0f)));
00832 
00833     float t = m_effect_frame_time.elapsed() * m_effect_transition_timeout_inv;
00834 
00835     m_texItem[m_texCur].MakeQuad();
00836 
00837     glMatrixMode(GL_MODELVIEW);
00838     glLoadIdentity();
00839     glRotatef(90.0f * t,
00840               (m_effect_rotate_direction == 0) ? 1.0f : 0.0f,
00841               (m_effect_rotate_direction == 1) ? 1.0f : 0.0f,
00842               0.0f);
00843 
00844     m_texItem[(m_texCur) ? 0 : 1].MakeQuad();
00845 
00846     m_effect_current_frame++;
00847 }
00848 
00849 void GLSingleView::EffectFade(void)
00850 {
00851     if (m_effect_frame_time.elapsed() > m_effect_transition_timeout)
00852     {
00853         paintTexture();
00854         m_effect_running = false;
00855         m_slideshow_frame_delay_state = -1;
00856         return;
00857     }
00858 
00859     float t = m_effect_frame_time.elapsed() * m_effect_transition_timeout_inv;
00860 
00861     if (m_effect_frame_time.elapsed() <= m_effect_transition_timeout / 2)
00862         m_texItem[(m_texCur) ? 0 : 1].MakeQuad(1.0f - (2.0f * t));
00863     else
00864         m_texItem[m_texCur].MakeQuad(2.0f * (t - 0.5f));
00865 
00866     m_effect_current_frame++;
00867 }
00868 
00869 void GLSingleView::EffectInOut(void)
00870 {
00871     if (m_effect_frame_time.elapsed() > m_effect_transition_timeout)
00872     {
00873         paintTexture();
00874         m_effect_running = false;
00875         m_slideshow_frame_delay_state = -1;
00876         return;
00877     }
00878 
00879     if (m_effect_current_frame == 0)
00880     {
00881         m_effect_rotate_direction = 1 + (int)((4.0f*random()/(RAND_MAX+1.0f)));
00882     }
00883 
00884     int  texnum  = m_texCur;
00885     bool fadeout = false;
00886     if (m_effect_frame_time.elapsed() <= m_effect_transition_timeout / 2)
00887     {
00888         texnum  = (m_texCur) ? 0 : 1;
00889         fadeout = true;
00890     }
00891 
00892     glMatrixMode(GL_MODELVIEW);
00893     glLoadIdentity();
00894 
00895     float tt = m_effect_frame_time.elapsed() * m_effect_transition_timeout_inv;
00896     float t = 2.0f / ((fadeout) ? (0.5f - tt) : (tt - 0.5f));
00897 
00898     glScalef(t, t, 1.0f);
00899     t = 1.0f - t;
00900     glTranslatef((m_effect_rotate_direction % 2 == 0) ? ((m_effect_rotate_direction == 2)? 1 : -1) * t : 0.0f,
00901                  (m_effect_rotate_direction % 2 == 1) ? ((m_effect_rotate_direction == 1)? 1 : -1) * t : 0.0f,
00902                  0.0f);
00903 
00904     m_texItem[texnum].MakeQuad();
00905 
00906     m_effect_current_frame++;
00907 }
00908 
00909 void GLSingleView::EffectSlide(void)
00910 {
00911     if (m_effect_frame_time.elapsed() > m_effect_transition_timeout)
00912     {
00913         paintTexture();
00914         m_effect_running = false;
00915         m_slideshow_frame_delay_state = -1;
00916         return;
00917     }
00918 
00919     if (m_effect_current_frame == 0)
00920         m_effect_rotate_direction = 1 + (int)((4.0f * random() / (RAND_MAX + 1.0f)));
00921 
00922     m_texItem[m_texCur].MakeQuad();
00923 
00924     glMatrixMode(GL_MODELVIEW);
00925     glLoadIdentity();
00926     float t = m_effect_frame_time.elapsed() * m_effect_transition_timeout_inv;
00927     float trans = 2.0f * t;
00928     glTranslatef((m_effect_rotate_direction % 2 == 0) ? ((m_effect_rotate_direction == 2)? 1 : -1) * trans : 0.0f,
00929                  (m_effect_rotate_direction % 2 == 1) ? ((m_effect_rotate_direction == 1)? 1 : -1) * trans : 0.0f,
00930                  0.0f);
00931 
00932     m_texItem[(m_texCur) ? 0 : 1].MakeQuad();
00933 
00934     m_effect_current_frame++;
00935 }
00936 
00937 void GLSingleView::EffectFlutter(void)
00938 {
00939     if (m_effect_frame_time.elapsed() > m_effect_transition_timeout)
00940     {
00941         paintTexture();
00942         m_effect_running = false;
00943         m_slideshow_frame_delay_state = -1;
00944         return;
00945     }
00946 
00947     GLTexture &ta = m_texItem[(m_texCur) ? 0 : 1];
00948 
00949     if (m_effect_current_frame == 0)
00950     {
00951         for (int x = 0; x < 40; x++)
00952         {
00953             for (int y = 0; y < 40; y++)
00954             {
00955                 m_effect_flutter_points[x][y][0] =
00956                     (float) (x / 20.0f - 1.0f) * ta.GetTextureX();
00957                 m_effect_flutter_points[x][y][1] =
00958                     (float) (y / 20.0f - 1.0f) * ta.GetTextureY();
00959                 m_effect_flutter_points[x][y][2] =
00960                     (float) sin((x / 20.0f - 1.0f) * M_PI * 2.0f) / 5.0;
00961             }
00962         }
00963     }
00964 
00965     m_texItem[m_texCur].MakeQuad();
00966 
00967     float t      = m_effect_frame_time.elapsed() * m_effect_transition_timeout_inv;
00968     float rotate = 60.0f * t;
00969     float scale  = 1.0f  - t;
00970 
00971     glMatrixMode(GL_MODELVIEW);
00972     glLoadIdentity();
00973     glRotatef(rotate, 1.0f, 0.0f, 0.0f);
00974     glScalef(scale, scale, scale);
00975     glTranslatef(t, t, 0.0f);
00976 
00977     ta.Bind();
00978 
00979     glBegin(GL_QUADS);
00980     {
00981         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
00982 
00983         float float_x, float_y, float_xb, float_yb;
00984         int x, y;
00985 
00986         for (x = 0; x < 39; x++)
00987         {
00988             for (y = 0; y < 39; y++)
00989             {
00990                 float_x = (float) x / 40.0f;
00991                 float_y = (float) y / 40.0f;
00992                 float_xb = (float) (x + 1) / 40.0f;
00993                 float_yb = (float) (y + 1) / 40.0f;
00994                 glTexCoord2f(float_x, float_y);
00995                 glVertex3f(m_effect_flutter_points[x][y][0],
00996                            m_effect_flutter_points[x][y][1],
00997                            m_effect_flutter_points[x][y][2]);
00998                 glTexCoord2f(float_x, float_yb);
00999                 glVertex3f(m_effect_flutter_points[x][y + 1][0],
01000                            m_effect_flutter_points[x][y + 1][1],
01001                            m_effect_flutter_points[x][y + 1][2]);
01002                 glTexCoord2f(float_xb, float_yb);
01003                 glVertex3f(m_effect_flutter_points[x + 1][y + 1][0],
01004                            m_effect_flutter_points[x + 1][y + 1][1],
01005                            m_effect_flutter_points[x + 1][y + 1][2]);
01006                 glTexCoord2f(float_xb, float_y);
01007                 glVertex3f(m_effect_flutter_points[x + 1][y][0],
01008                            m_effect_flutter_points[x + 1][y][1],
01009                            m_effect_flutter_points[x + 1][y][2]);
01010             }
01011         }
01012     }
01013     glEnd();
01014 
01015     // wave every two iterations
01016     if (m_effect_current_frame%2 == 0)
01017     {
01018 
01019         float hold;
01020         int x, y;
01021         for (y = 0; y < 40; y++)
01022         {
01023             hold = m_effect_flutter_points[0][y][2];
01024             for (x = 0; x < 39; x++)
01025             {
01026                 m_effect_flutter_points[x][y][2] = m_effect_flutter_points[x + 1][y][2];
01027             }
01028             m_effect_flutter_points[39][y][2] = hold;
01029         }
01030     }
01031     m_effect_current_frame++;
01032 }
01033 
01034 void GLSingleView::EffectCube(void)
01035 {
01036     float tot      = m_effect_transition_timeout ? m_effect_transition_timeout : 1.0f;
01037     float rotStart = 0.25f * m_effect_transition_timeout;
01038 
01039     if (m_effect_frame_time.elapsed() > m_effect_transition_timeout)
01040     {
01041         paintTexture();
01042         m_effect_running = false;
01043         m_slideshow_frame_delay_state = -1;
01044         return;
01045     }
01046 
01047     // Enable perspective vision
01048     glEnable(GL_DEPTH_TEST);
01049     glDepthFunc(GL_LEQUAL);
01050     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
01051 
01052     GLTexture &ta = m_texItem[(m_texCur) ? 0 : 1];
01053     GLTexture &tb = m_texItem[m_texCur];
01054 
01055     glMatrixMode(GL_PROJECTION);
01056     glLoadIdentity();
01057 
01058 //    float PI = 4.0f * atan(1.0f);
01059     float znear = 3.0f;
01060 //     float theta = 2.0f * atan2(2.0f / 2.0f, znear);
01061 //     theta = theta * 180.0f/PI;
01062 
01063     glFrustum(-1.0f, 1.0f, -1.0f, 1.0f, znear - 0.01f, 10.0f);
01064 
01065     if (m_effect_current_frame == 0)
01066     {
01067         m_effect_cube_xrot = 0.0f;
01068         m_effect_cube_yrot = 0.0f;
01069         m_effect_cube_zrot = 0.0f;
01070     }
01071 
01072     glMatrixMode(GL_MODELVIEW);
01073     glLoadIdentity();
01074 
01075     float elapsed = (float) m_effect_frame_time.elapsed();
01076     float tmp     = ((elapsed <= tot * 0.5) ? elapsed : tot - elapsed);
01077     float trans   = 5.0f * tmp / tot;
01078 
01079     glTranslatef(0.0f, 0.0f, -znear - 1.0f - trans);
01080 
01081     glRotatef(m_effect_cube_xrot, 1.0f, 0.0f, 0.0f);
01082     glRotatef(m_effect_cube_yrot, 0.0f, 1.0f, 0.0f);
01083 
01084     glBindTexture(GL_TEXTURE_2D, 0);
01085 
01086     glBegin(GL_QUADS);
01087     {
01088         glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
01089 
01090         /* Front Face */
01091         glVertex3f(-1.00f, -1.00f,  0.99f);
01092         glVertex3f( 1.00f, -1.00f,  0.99f);
01093         glVertex3f( 1.00f,  1.00f,  0.99f);
01094         glVertex3f(-1.00f,  1.00f,  0.99f);
01095 
01096         /* Back Face */
01097         glVertex3f(-1.00f, -1.00f, -0.99f);
01098         glVertex3f(-1.00f,  1.00f, -0.99f);
01099         glVertex3f( 1.00f,  1.00f, -0.99f);
01100         glVertex3f( 1.00f, -1.00f, -0.99f);
01101 
01102         /* Top Face */
01103         glVertex3f(-1.00f,  0.99f, -1.00f);
01104         glVertex3f(-1.00f,  0.99f,  1.00f);
01105         glVertex3f( 1.00f,  0.99f,  1.00f);
01106         glVertex3f( 1.00f,  0.99f, -1.00f);
01107 
01108         /* Bottom Face */
01109         glVertex3f(-1.00f, -0.99f, -1.00f);
01110         glVertex3f( 1.00f, -0.99f, -1.00f);
01111         glVertex3f( 1.00f, -0.99f,  1.00f);
01112         glVertex3f(-1.00f, -0.99f,  1.00f);
01113 
01114         /* Right face */
01115         glVertex3f(0.99f, -1.00f, -1.00f);
01116         glVertex3f(0.99f,  1.00f, -1.00f);
01117         glVertex3f(0.99f,  1.00f,  1.00f);
01118         glVertex3f(0.99f, -1.00f,  1.00f);
01119 
01120         /* Left Face */
01121         glVertex3f(-0.99f, -1.00f, -1.00f);
01122         glVertex3f(-0.99f, -1.00f,  1.00f);
01123         glVertex3f(-0.99f,  1.00f,  1.00f);
01124         glVertex3f(-0.99f,  1.00f, -1.00f);
01125 
01126     }
01127     glEnd();
01128 
01129     ta.Bind();
01130 
01131     glBegin(GL_QUADS);
01132     {
01133         glColor4d(1.0f, 1.0f, 1.0f, 1.0f);
01134 
01135         // Front Face
01136         glTexCoord2f(0.0f, 0.0f);
01137         glVertex3f(-ta.GetTextureX(), -ta.GetTextureY(),  1.00f);
01138         glTexCoord2f(1.0f, 0.0f);
01139         glVertex3f(+ta.GetTextureX(), -ta.GetTextureY(),  1.00f);
01140         glTexCoord2f(1.0f, 1.0f);
01141         glVertex3f(+ta.GetTextureX(), +ta.GetTextureY(),  1.00f);
01142         glTexCoord2f(0.0f, 1.0f);
01143         glVertex3f(-ta.GetTextureX(), +ta.GetTextureY(),  1.00f);
01144 
01145         // Top Face
01146         glTexCoord2f(1.0f, 1.0f);
01147         glVertex3f(-ta.GetTextureX(),  1.00f, -ta.GetTextureY());
01148         glTexCoord2f(1.0f, 0.0f);
01149         glVertex3f(-ta.GetTextureX(),  1.00f, +ta.GetTextureY());
01150         glTexCoord2f(0.0f, 0.0f);
01151         glVertex3f(+ta.GetTextureX(),  1.00f, +ta.GetTextureY());
01152         glTexCoord2f(0.0f, 1.0f);
01153         glVertex3f(+ta.GetTextureX(),  1.00f, -ta.GetTextureY());
01154 
01155         // Bottom Face
01156         glTexCoord2f(0.0f, 1.0f);
01157         glVertex3f(-ta.GetTextureX(), -1.00f, -ta.GetTextureY());
01158         glTexCoord2f(1.0f, 1.0f);
01159         glVertex3f(+ta.GetTextureX(), -1.00f, -ta.GetTextureY());
01160         glTexCoord2f(1.0f, 0.0f);
01161         glVertex3f(+ta.GetTextureX(), -1.00f, +ta.GetTextureY());
01162         glTexCoord2f(0.0f, 0.0f);
01163         glVertex3f(-ta.GetTextureX(), -1.00f, +ta.GetTextureY());
01164 
01165         // Right face
01166         glTexCoord2f(0.0f, 0.0f);
01167         glVertex3f(1.00f, -ta.GetTextureX(), -ta.GetTextureY());
01168         glTexCoord2f(0.0f, 1.0f);
01169         glVertex3f(1.00f, -ta.GetTextureX(), +ta.GetTextureY());
01170         glTexCoord2f(1.0f, 1.0f);
01171         glVertex3f(1.00f, +ta.GetTextureX(), +ta.GetTextureY());
01172         glTexCoord2f(1.0f, 0.0f);
01173         glVertex3f(1.00f, +ta.GetTextureX(), -ta.GetTextureY());
01174 
01175         // Left Face
01176         glTexCoord2f(1.0f, 0.0f);
01177         glVertex3f(-1.00f, -ta.GetTextureX(), -ta.GetTextureY());
01178         glTexCoord2f(0.0f, 0.0f);
01179         glVertex3f(-1.00f, +ta.GetTextureX(), -ta.GetTextureY());
01180         glTexCoord2f(0.0f, 1.0f);
01181         glVertex3f(-1.00f, +ta.GetTextureX(), +ta.GetTextureY());
01182         glTexCoord2f(1.0f, 1.0f);
01183         glVertex3f(-1.00f, -ta.GetTextureX(), +ta.GetTextureY());
01184     }
01185     glEnd();
01186 
01187     tb.Bind();
01188 
01189     glBegin(GL_QUADS);
01190     {
01191         glColor4d(1.0f, 1.0f, 1.0f, 1.0f);
01192 
01193         // Back Face
01194         glTexCoord2f(1.0f, 0.0f);
01195         glVertex3f(-tb.GetTextureX(), -tb.GetTextureY(), -1.00f);
01196         glTexCoord2f(1.0f, 1.0f);
01197         glVertex3f(-tb.GetTextureX(), +tb.GetTextureY(), -1.00f);
01198         glTexCoord2f(0.0f, 1.0f);
01199         glVertex3f(+tb.GetTextureX(), +tb.GetTextureY(), -1.00f);
01200         glTexCoord2f(0.0f, 0.0f);
01201         glVertex3f(+tb.GetTextureX(), -tb.GetTextureY(), -1.00f);
01202     }
01203     glEnd();
01204 
01205     if ((elapsed >= rotStart) && (elapsed < (tot - rotStart)))
01206     {
01207         m_effect_cube_xrot = 360.0f * (elapsed - rotStart) / (tot - 2 * rotStart);
01208         m_effect_cube_yrot = 0.5f * m_effect_cube_xrot;
01209     }
01210 
01211     m_effect_current_frame++;
01212 }
01213 
01214 void GLSingleView::EffectKenBurns(void)
01215 {
01216 
01217     float single_image_pct = 0.75;
01218     float trans_pct = 1.0 - single_image_pct;
01219     float scale_max, x_loc, y_loc;
01220     float scale_factor = 0;
01221 
01222     //initialize effect
01223     if (!m_effect_kenBurns_initialized)
01224     {
01225 
01226         m_effect_kenBurns_initialized = !m_effect_kenBurns_initialized;
01227         m_effect_kenBurns_item = NULL;
01228         // Need to load images in the background to keep effect smooth
01229         m_effect_kenBurns_imageLoadThread = new KenBurnsImageLoader(this, m_itemList, m_texSize, m_screenSize);
01230         //Since total image time is longer/different than effect time, create image timers
01231         m_effect_kenBurns_image_time[m_texCur ? 0 : 1].restart();
01232         // Pan image to a random location
01233         FindRandXY(m_effect_kenBurns_location_x[0], m_effect_kenBurns_location_y[0]);
01234         // Since first two images are preloaded, hardcode  them to zoom in
01235         m_effect_kenBurns_projection[0] = 1;
01236         m_effect_kenBurns_projection[1] = 1;
01237         m_effect_kenBurns_image_timeout = m_effect_transition_timeout +
01238                 (m_effect_transition_timeout * trans_pct);
01239     }
01240 
01241     if (m_effect_frame_time.elapsed() >= m_effect_transition_timeout)
01242     {
01243         // Effect timed out, move new image to old image but don't load new image yet...
01244         m_tex1First = !m_tex1First;
01245         m_texCur      = (m_texCur) ? 0 : 1;
01246         m_effect_current_frame  = 0;
01247         m_effect_frame_time.restart();
01248 
01249         m_effect_kenBurns_image_ready = false;
01250 
01251         // Find next image to be loaded
01252         int oldpos = m_pos;
01253 
01254         while (true)
01255         {
01256             m_pos = m_slideshow_sequence->next();
01257             m_effect_kenBurns_item = m_itemList.at(m_pos);
01258             if (m_effect_kenBurns_item)
01259             {
01260                 // Skip movies
01261                 if (QFile::exists(m_effect_kenBurns_item->GetPath()) && !GalleryUtil::IsMovie(m_effect_kenBurns_item->GetPath()))
01262                 {
01263                     break;
01264                 }
01265             }
01266             if (m_pos == oldpos)
01267             {
01268                 // No valid items!!!
01269                 close();
01270             }
01271         }
01272         m_effect_kenBurns_imageLoadThread->Initialize(m_pos);
01273         m_effect_kenBurns_imageLoadThread->start();
01274     }
01275 
01276     float t[2], elapsed[2], s[2], effect_pct;
01277     elapsed[m_texCur] = m_effect_kenBurns_image_time[m_texCur].elapsed();
01278     elapsed[m_texCur ? 0 : 1] = m_effect_kenBurns_image_time[m_texCur ? 0 : 1].elapsed();
01279     //progress linearly
01280     t[m_texCur] = elapsed[m_texCur] / m_effect_kenBurns_image_timeout;
01281     t[m_texCur ? 0 : 1] = elapsed[m_texCur ? 0 : 1] / m_effect_kenBurns_image_timeout;
01282     //progress faster initially then slowing down- this is needed to ensure images zoom faster than they pan and
01283     //therefore stay completely on the screen
01284     s[m_texCur] = sqrt(elapsed[m_texCur]) / sqrt(m_effect_kenBurns_image_timeout);
01285     s[m_texCur ? 0 : 1] = sqrt(elapsed[m_texCur ? 0 : 1]) / sqrt(m_effect_kenBurns_image_timeout);
01286 
01287     effect_pct = m_effect_frame_time.elapsed() *  m_effect_transition_timeout_inv;
01288 
01289     // Load new image if its ready
01290     if (effect_pct > single_image_pct && m_effect_kenBurns_image_ready)
01291     {
01292         if (!m_effect_kenBurns_new_image_started)
01293         {
01294             if (m_effect_kenBurns_item) //Do not create textures for first two images, since they are preloaded
01295             {
01296                 m_texItem[!m_tex1First].SetItem(m_effect_kenBurns_item, m_effect_kenBurns_orig_image_size);
01297                 m_texItem[!m_tex1First].ScaleTo(m_screenSize, m_scaleMax);
01298                 m_texItem[!m_tex1First].Init(m_effect_kenBurns_image);
01299                 UpdateLCD(m_effect_kenBurns_item);
01300 
01301                 //choose the location and projection (zoom in or out) randomly
01302                 FindRandXY(m_effect_kenBurns_location_x[m_texCur],
01303                            m_effect_kenBurns_location_y[m_texCur]);
01304                 m_effect_kenBurns_projection[m_texCur] =
01305                     1 + (int)((2.0f * random() / (RAND_MAX + 1.0f)));
01306             }
01307             else  //No item, must be 1 of the first two preloaded items
01308             {
01309                 //start at random location and zoom out to face in center
01310                 FindRandXY(m_effect_kenBurns_location_x[m_texCur], m_effect_kenBurns_location_y[m_texCur]);
01311                 m_effect_kenBurns_projection[m_texCur] = 1;
01312             }
01313 
01314             m_effect_kenBurns_image_time[m_texCur].restart();
01315             m_effect_kenBurns_new_image_started = true;
01316         }
01317         if (m_effect_kenBurns_projection[m_texCur] == 1) // Zoom in image
01318         {
01319             // Start in center and pan out
01320             x_loc = m_effect_kenBurns_location_x[m_texCur] * t[m_texCur];
01321             y_loc = m_effect_kenBurns_location_y[m_texCur] * t[m_texCur];
01322             scale_max = FindMaxScale(x_loc,y_loc);
01323             scale_factor =     1.0f + (scale_max * s[m_texCur]);
01324         }
01325         else // Zoom out image
01326         {
01327             // Start at random location and pan to center
01328             x_loc = m_effect_kenBurns_location_x[m_texCur] -  m_effect_kenBurns_location_x[m_texCur] * t[m_texCur];
01329             y_loc = m_effect_kenBurns_location_y[m_texCur] -  m_effect_kenBurns_location_y[m_texCur] * t[m_texCur];
01330             scale_max = FindMaxScale(x_loc,y_loc);
01331             scale_factor =     1.0f + scale_max -  (scale_max * t[m_texCur]);
01332         }
01333 
01334         glMatrixMode(GL_MODELVIEW);
01335         glLoadIdentity();
01336         glTranslatef(x_loc, y_loc, 0.0f);
01337 
01338         m_texItem[m_texCur].MakeQuad((effect_pct-single_image_pct)*4, scale_factor);
01339     }
01340 
01341     //Load old picture
01342     if (m_effect_kenBurns_projection[m_texCur ? 0 : 1] == 1)// Zoom in image
01343     {
01344         x_loc = m_effect_kenBurns_location_x[m_texCur ? 0 : 1] * t[m_texCur ? 0 : 1];
01345         y_loc = m_effect_kenBurns_location_y[m_texCur ? 0 : 1] * t[m_texCur ? 0 : 1];
01346         scale_max = FindMaxScale(x_loc,y_loc);
01347         scale_factor =     1.0f + (scale_max * s[m_texCur ? 0 : 1]);
01348     }
01349     else // Zoom out image
01350     {
01351         x_loc = m_effect_kenBurns_location_x[m_texCur ? 0 : 1] -
01352             m_effect_kenBurns_location_x[m_texCur ? 0 : 1] * t[m_texCur ? 0 : 1];
01353         y_loc = m_effect_kenBurns_location_y[m_texCur ? 0 : 1] -
01354             m_effect_kenBurns_location_y[m_texCur ? 0 : 1] * t[m_texCur ? 0 : 1];
01355         scale_max = FindMaxScale(x_loc,y_loc);
01356         scale_factor =     1.0f + scale_max -  (scale_max * t[m_texCur ? 0 : 1]);
01357     }
01358 
01359     glMatrixMode(GL_MODELVIEW);
01360     glLoadIdentity();
01361     glTranslatef(x_loc, y_loc, 0.0f);
01362 
01363     if (effect_pct<= single_image_pct)
01364     {
01365         m_effect_kenBurns_new_image_started=false;
01366         m_texItem[m_texCur ? 0 : 1].MakeQuad(1.0f, scale_factor); //
01367     }
01368     else // Fade out image
01369     {
01370         m_texItem[m_texCur ? 0 : 1].MakeQuad(1.0f - ((effect_pct-single_image_pct)*4), scale_factor);
01371 
01372     }
01373 
01374     m_effect_current_frame++;
01375 }
01376 
01377 void GLSingleView::SlideTimeout(void)
01378 {
01379     bool wasMovie = false, isMovie = false;
01380     if (m_effect_method.isEmpty())
01381     {
01382         LOG(VB_GENERAL, LOG_ERR, LOC + "No transition method");
01383         return;
01384     }
01385 
01386     if (m_effect_running)
01387     {
01388         m_slideshow_frame_delay_state = 10;
01389     }
01390     else
01391     {
01392         if (m_slideshow_frame_delay_state == -1)
01393         {
01394             // effect was running and is complete now
01395             // run timer while showing current image
01396             m_slideshow_frame_delay_state = m_slideshow_frame_delay * 1000;
01397             m_effect_current_frame     = 0;
01398         }
01399         else
01400         {
01401             // timed out after showing current image
01402             // load next image and start effect
01403 
01404             if (m_slideshow_running)
01405             {
01406                 if (m_effect_random)
01407                     m_effect_method = GetRandomEffect();
01408 
01409                 DisplayNext(false, false);
01410 
01411                 wasMovie = m_movieState > 0;
01412                 Load();
01413                 isMovie = m_movieState > 0;
01414                 // If transitioning to/from a movie, don't do an effect,
01415                 // and shorten timeout
01416                 if (wasMovie || isMovie)
01417                 {
01418                     m_slideshow_frame_delay_state = 1;
01419                 }
01420                 else
01421                 {
01422                     m_slideshow_frame_delay_state = 10;
01423                     m_effect_running = true;
01424                     m_effect_current_frame = 0;
01425                 }
01426                 m_effect_frame_time.restart();
01427             }
01428             m_info_show_short = false;
01429         }
01430     }
01431 
01432     updateGL();
01433     if (m_slideshow_running)
01434     {
01435         m_slideshow_timer->stop();
01436         m_slideshow_timer->setSingleShot(true);
01437         m_slideshow_timer->start(max(0, m_slideshow_frame_delay_state));
01438 
01439         // If transitioning to/from a movie, no effect is running so
01440         // next timeout should trigger proper immage delay.
01441         if (wasMovie || isMovie)
01442         {
01443             m_slideshow_frame_delay_state = -1;
01444         }
01445     }
01446 }
01447 
01448 void GLSingleView::createTexInfo(void)
01449 {
01450     if (m_texInfo)
01451         glDeleteTextures(1, &m_texInfo);
01452 
01453     QString info = m_texItem[m_texCur].GetDescription(GetDescriptionStatus());
01454     if (info.isEmpty())
01455         return;
01456 
01457     QPixmap pix(512, 512);
01458 
01459     QPainter p(&pix);
01460     p.initFrom(this);
01461     p.fillRect(0, 0, pix.width(), pix.height(), Qt::black);
01462     p.setPen(Qt::white);
01463 
01464     p.drawText(10, 10, pix.width() - 20, pix.height() - 20,
01465                Qt::AlignLeft, info);
01466     p.end();
01467 
01468     QImage img = pix.toImage();
01469     img = img.convertToFormat(QImage::Format_ARGB32);
01470 
01471     QImage tex = convertToGLFormat(img);
01472 
01473     /* create the texture */
01474     glGenTextures(1, &m_texInfo);
01475     glBindTexture(GL_TEXTURE_2D, m_texInfo);
01476     /* actually generate the texture */
01477     glTexImage2D(GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0,
01478                  GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
01479     /* enable linear filtering  */
01480     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01481     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01482 }
01483 
01484 void GLSingleView::LoadImage(QImage image, QSize origSize)
01485 {
01486     m_effect_kenBurns_image = image;
01487     m_effect_kenBurns_orig_image_size = origSize;
01488 }
01489 
01490 float GLSingleView::FindMaxScale(float x_loc, float y_loc)
01491 {
01492     // Zoom big enough to keep the entire image on screen when we pan
01493     if (abs(x_loc) > abs(y_loc))
01494         return abs(x_loc) * 2;
01495     else
01496         return abs(y_loc) * 2;
01497 }
01498 
01499 void GLSingleView::FindRandXY(float &x_loc, float &y_loc)
01500 {
01501     // Random number between .25 and .75
01502     x_loc = (0.5 * random() / (RAND_MAX + 1.0f)) + 0.25;
01503     if ((int)(2.0 * random() / (RAND_MAX + 1.0f)) == 0)
01504         x_loc = -1 * x_loc;
01505     // Random number between .25 and .75
01506     y_loc = (0.5 * random() / (RAND_MAX + 1.0f)) + 0.25;
01507     if ((int)(2.0 * random() / (RAND_MAX + 1.0f)) == 0)
01508         y_loc = -1 * y_loc;
01509 }
01510 
01511 KenBurnsImageLoader::KenBurnsImageLoader(GLSingleView *singleView,
01512                                          ThumbList &itemList,
01513                                          QSize texSize, QSize screenSize) :
01514     MThread("KenBurnsImageLoader"),
01515     m_singleView(singleView),
01516     m_itemList(itemList),
01517     m_pos(0),
01518     m_tex1First(false),
01519     m_screenSize(screenSize),
01520     m_texSize(texSize)
01521 {
01522 }
01523 
01524 void KenBurnsImageLoader::Initialize(int pos)
01525 {
01526     m_pos = pos;
01527 }
01528 
01529 void KenBurnsImageLoader::run()
01530 {
01531     RunProlog();
01532     ThumbItem *item = m_itemList.at(m_pos);
01533     if (!item)
01534     {
01535         LOG(VB_GENERAL, LOG_ERR, LOC + QString("No item at %1").arg(m_pos));
01536         RunEpilog();
01537         return;
01538     }
01539     QImage image(item->GetPath());
01540     if (image.isNull())
01541     {
01542         RunEpilog();
01543         return;
01544     }
01545 
01546     image = image.scaled(m_texSize, Qt::IgnoreAspectRatio,
01547                          Qt::SmoothTransformation);
01548     QImage glimage = QGLWidget::convertToGLFormat(image);
01549 
01550     m_singleView->LoadImage(glimage, glimage.size());
01551     m_singleView->Ready();
01552 
01553     RunEpilog();
01554 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends