[niepce] Basic video thumbnailing Rudimentary caching for thumbnails.
- From: Hubert FiguiÃre <hub src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [niepce] Basic video thumbnailing Rudimentary caching for thumbnails.
- Date: Sat, 12 Nov 2011 06:16:55 +0000 (UTC)
commit f9c6d4760b4905a0e96b3bf29595daf8e2ddefa1
Author: Hub Figuiere <hub figuiere net>
Date: Sun Nov 6 16:52:52 2011 -0800
Basic video thumbnailing
Rudimentary caching for thumbnails.
src/engine/library/thumbnailcache.cpp | 230 ++++++++++++++++++++-------------
src/engine/library/thumbnailcache.hpp | 79 +++++++-----
src/fwk/toolkit/Makefile.am | 1 +
src/fwk/toolkit/movieutils.cpp | 47 +++++++
src/fwk/toolkit/movieutils.hpp | 43 ++++++
5 files changed, 278 insertions(+), 122 deletions(-)
---
diff --git a/src/engine/library/thumbnailcache.cpp b/src/engine/library/thumbnailcache.cpp
index 7503482..cb0be65 100644
--- a/src/engine/library/thumbnailcache.cpp
+++ b/src/engine/library/thumbnailcache.cpp
@@ -1,7 +1,7 @@
/*
* niepce - library/thumbnailcache.cpp
*
- * Copyright (C) 2007-2008 Hubert Figuiere
+ * Copyright (C) 2007-2008,2011 Hubert Figuiere
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,111 +22,163 @@
#include <functional>
#include <boost/bind.hpp>
#include <boost/any.hpp>
+#include <boost/lexical_cast.hpp>
#include <gdkmm/pixbuf.h>
#include <libopenraw-gnome/gdkpixbuf.h>
#include "niepce/notifications.hpp"
#include "fwk/base/debug.hpp"
+#include "fwk/utils/pathutils.hpp"
#include "fwk/toolkit/mimetype.hpp"
#include "fwk/toolkit/gdkutils.hpp"
+#include "fwk/toolkit/movieutils.hpp"
#include "thumbnailcache.hpp"
#include "thumbnailnotification.hpp"
namespace eng {
- ThumbnailCache::ThumbnailCache(const std::string & dir,
- const fwk::NotificationCenter::Ptr & nc)
- : m_cacheDir(dir),
- m_notif_center(nc)
- {
- }
-
- ThumbnailCache::~ThumbnailCache()
- {
- }
-
- void ThumbnailCache::request(const LibFile::ListPtr & fl)
- {
- clear();
- std::for_each(fl->begin(), fl->end(),
- boost::bind(&ThumbnailCache::requestForFile, this,
- _1));
- }
-
- void ThumbnailCache::requestForFile(const LibFile::Ptr & f)
- {
- ThumbnailTask::Ptr task(new ThumbnailTask(f, 160, 160));
- schedule( task );
- }
-
-
- void ThumbnailCache::execute(const ThumbnailTask::Ptr & task)
- {
- const std::string & filename = task->file()->path();
- DBG_OUT("creating thumbnail for %s",filename.c_str());
+ThumbnailCache::ThumbnailCache(const std::string & dir,
+ const fwk::NotificationCenter::Ptr & nc)
+ : m_cacheDir(dir),
+ m_notif_center(nc)
+{
+}
+
+ThumbnailCache::~ThumbnailCache()
+{
+}
+
+void ThumbnailCache::request(const LibFile::ListPtr & fl)
+{
+ clear();
+ std::for_each(fl->begin(), fl->end(),
+ boost::bind(&ThumbnailCache::requestForFile, this,
+ _1));
+}
+
+void ThumbnailCache::requestForFile(const LibFile::Ptr & f)
+{
+ ThumbnailTask::Ptr task(new ThumbnailTask(f, 160, 160));
+ schedule( task );
+}
+
+namespace {
+
+// TODO see about 1. moving this out 2. abstracting the type away from Gdk::Pixbuf
+// Gdk does not belong to eng.
+Glib::RefPtr<Gdk::Pixbuf> getThumbnail(const LibFile::Ptr & f, int w, int h, const std::string & cached)
+{
+ if(ThumbnailCache::is_thumbnail_cached(f->path(), cached)) {
+ DBG_OUT("cached!");
+ return Gdk::Pixbuf::create_from_file(cached);
+ }
+ const std::string & filename = f->path();
+ DBG_OUT("creating thumbnail for %s",filename.c_str());
+
+ fwk::MimeType mime_type(filename);
+
+
+ DBG_OUT("MIME type %s", mime_type.string().c_str());
+
+ Glib::RefPtr<Gdk::Pixbuf> pix;
+
+ if(mime_type.isUnknown()) {
+ DBG_OUT("unknown file type %s", filename.c_str());
+ }
+ // TODO: what about videos?
+ else if(mime_type.isMovie()) {
+ if(fwk::thumbnail_movie(filename, w, h, cached)) {
+ pix = Gdk::Pixbuf::create_from_file(cached, w, h, true);
+ }
+ }
+ else if(!mime_type.isImage()) {
+ DBG_OUT("not an image type");
+ }
+ else if(!mime_type.isDigicamRaw()) {
+ DBG_OUT("not a raw type, trying GdkPixbuf loaders");
+ try {
+ pix = Gdk::Pixbuf::create_from_file(filename, w, h, true);
+ if(pix) {
+ pix = fwk::gdkpixbuf_exif_rotate(pix, f->orientation());
+ }
+ }
+ catch(const Glib::Error & e) {
+ ERR_OUT("exception %s", e.what().c_str());
+ }
+ }
+ else {
+ GdkPixbuf *pixbuf = or_gdkpixbuf_extract_rotated_thumbnail(filename.c_str(),
+ std::min(w, h));
+ if(pixbuf) {
+ pix = Glib::wrap(pixbuf, true); // take ownership
+ }
+ if((w < pix->get_width()) || (h < pix->get_height())) {
+ pix = fwk::gdkpixbuf_scale_to_fit(pix, std::min(w,h));
+ }
+ }
+ if(pix)
+ {
+ pix->save(cached, "png");
+ }
+ else {
+ DBG_OUT("couldn't get the thumbnail for %s", filename.c_str());
+ }
+ return pix;
+}
+
+}
+
+void ThumbnailCache::execute(const ThumbnailTask::Ptr & task)
+{
int w, h;
w = task->width();
h = task->height();
- fwk::MimeType mime_type(filename);
-
-
- DBG_OUT("MIME type %s", mime_type.string().c_str());
-
- if(mime_type.isUnknown()) {
- DBG_OUT("unknown file type %s", filename.c_str());
- return;
- }
- if(!mime_type.isImage()) {
- DBG_OUT("not an image type");
- return;
- }
-
- Glib::RefPtr<Gdk::Pixbuf> pix;
- if(!mime_type.isDigicamRaw()) {
- DBG_OUT("not a raw type, trying GdkPixbuf loaders");
- try {
- pix = Gdk::Pixbuf::create_from_file(filename, w, h, true);
- if(pix) {
- pix = fwk::gdkpixbuf_exif_rotate(pix, task->file()->orientation());
+ Glib::RefPtr<Gdk::Pixbuf> pix;
+
+ std::string dest = path_for_thumbnail(task->file()->path(), std::max(w,h));
+ DBG_OUT("cached thumbnail %s", dest.c_str());
+
+ pix = getThumbnail(task->file(), w, h, dest);
+
+ if(pix) {
+ fwk::NotificationCenter::Ptr nc(m_notif_center);
+ if(nc) {
+ // pass the notification
+ fwk::Notification::Ptr n(new fwk::Notification(niepce::NOTIFICATION_THUMBNAIL));
+ ThumbnailNotification tn;
+ tn.id = task->file()->id();
+ tn.width = pix->get_width();
+ tn.height = pix->get_height();
+ tn.pixmap = pix;
+ n->setData(boost::any(tn));
+ DBG_OUT("notify thumbnail for id=%d", tn.id);
+ nc->post(n);
}
- }
- catch(const Glib::Error & e)
- {
- ERR_OUT("exception %s", e.what().c_str());
- }
- }
- else {
- GdkPixbuf *pixbuf = or_gdkpixbuf_extract_rotated_thumbnail(filename.c_str(),
- std::min(w, h));
- if(pixbuf) {
- pix = Glib::wrap(pixbuf, true); // take ownership
- }
- }
- if(pix)
- {
- if((w < pix->get_width()) || (h < pix->get_height())) {
- pix = fwk::gdkpixbuf_scale_to_fit(pix, std::min(w,h));
- }
- fwk::NotificationCenter::Ptr nc(m_notif_center);
- if(nc) {
- // pass the notification
- fwk::Notification::Ptr n(new fwk::Notification(niepce::NOTIFICATION_THUMBNAIL));
- ThumbnailNotification tn;
- tn.id = task->file()->id();
- tn.width = pix->get_width();
- tn.height = pix->get_height();
- tn.pixmap = pix;
- n->setData(boost::any(tn));
- DBG_OUT("notify thumbnail for id=%d", tn.id);
- nc->post(n);
- }
- }
- else
- {
- DBG_OUT("couldn't get the thumbnail for %s", filename.c_str());
- }
- }
+ }
+}
+std::string ThumbnailCache::path_for_thumbnail(const std::string & filename, int size) const
+{
+ std::string subdir = size ? boost::lexical_cast<std::string>(size) : "full";
+ // todo compute a hash
+ return m_cacheDir + "/" + subdir + "/" + fwk::path_basename(filename) + ".png";
}
+
+bool ThumbnailCache::is_thumbnail_cached(const std::string & /*file*/, const std::string & thumb)
+{
+ return fwk::path_exists(thumb);
+}
+
+
+}
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0))
+ indent-tabs-mode:nil
+ fill-column:80
+ End:
+*/
diff --git a/src/engine/library/thumbnailcache.hpp b/src/engine/library/thumbnailcache.hpp
index c3c2a2a..001cd2e 100644
--- a/src/engine/library/thumbnailcache.hpp
+++ b/src/engine/library/thumbnailcache.hpp
@@ -1,7 +1,7 @@
/*
* niepce - library/thumbnailcache.h
*
- * Copyright (C) 2007 Hubert Figuiere
+ * Copyright (C) 2007,2011 Hubert Figuiere
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,46 +30,59 @@
namespace eng {
- class ThumbnailTask
- {
- public:
- typedef std::tr1::shared_ptr< ThumbnailTask > Ptr;
+class ThumbnailTask
+{
+public:
+ typedef std::tr1::shared_ptr< ThumbnailTask > Ptr;
- ThumbnailTask(const LibFile::Ptr & f, int w, int h)
- : m_file(f), m_width(w), m_height(h)
- { }
+ ThumbnailTask(const LibFile::Ptr & f, int w, int h)
+ : m_file(f), m_width(w), m_height(h)
+ { }
- const LibFile::Ptr & file()
- { return m_file; }
- int width() const
- { return m_width; }
- int height() const
- { return m_height; }
- private:
- const LibFile::Ptr m_file;
- int m_width;
- int m_height;
- };
+ const LibFile::Ptr & file()
+ { return m_file; }
+ int width() const
+ { return m_width; }
+ int height() const
+ { return m_height; }
+private:
+ const LibFile::Ptr m_file;
+ int m_width;
+ int m_height;
+};
- class ThumbnailCache
- : private fwk::Worker< ThumbnailTask::Ptr >
- {
- public:
- ThumbnailCache(const std::string & dir,
- const fwk::NotificationCenter::Ptr & nc);
- ~ThumbnailCache();
+class ThumbnailCache
+ : private fwk::Worker< ThumbnailTask::Ptr >
+{
+public:
+ ThumbnailCache(const std::string & dir,
+ const fwk::NotificationCenter::Ptr & nc);
+ ~ThumbnailCache();
- void request(const LibFile::ListPtr & fl);
- void requestForFile(const LibFile::Ptr & f);
+ void request(const LibFile::ListPtr & fl);
+ void requestForFile(const LibFile::Ptr & f);
- protected:
- virtual void execute(const ThumbnailTask::Ptr & task);
- private:
+ static bool is_thumbnail_cached(const std::string & file, const std::string & thumb);
+
+protected:
+ virtual void execute(const ThumbnailTask::Ptr & task);
+private:
std::string m_cacheDir;
- std::tr1::weak_ptr<fwk::NotificationCenter> m_notif_center;
- };
+ std::tr1::weak_ptr<fwk::NotificationCenter> m_notif_center;
+
+ std::string path_for_thumbnail(const std::string & filename, int size) const;
+};
}
#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0))
+ indent-tabs-mode:nil
+ fill-column:80
+ End:
+*/
diff --git a/src/fwk/toolkit/Makefile.am b/src/fwk/toolkit/Makefile.am
index 6976c18..10850f5 100644
--- a/src/fwk/toolkit/Makefile.am
+++ b/src/fwk/toolkit/Makefile.am
@@ -22,6 +22,7 @@ libniepceframework_a_SOURCES = configuration.hpp configuration.cpp \
uicontroller.hpp uicontroller.cpp \
notification.hpp \
mimetype.hpp mimetype.cpp \
+ movieutils.hpp movieutils.cpp \
imageloader.hpp imageloader.cpp \
notificationcenter.hpp notificationcenter.cpp \
configdatabinder.hpp configdatabinder.cpp \
diff --git a/src/fwk/toolkit/movieutils.cpp b/src/fwk/toolkit/movieutils.cpp
new file mode 100644
index 0000000..79cd6d5
--- /dev/null
+++ b/src/fwk/toolkit/movieutils.cpp
@@ -0,0 +1,47 @@
+/*
+ * niepce - fwk/movieutils.cpp
+ *
+ * Copyright (C) 2011 Hub Figuiere
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <stdlib.h>
+
+#include <boost/format.hpp>
+
+
+namespace fwk {
+
+ // TODO don't harcode command
+ // TODO check errors
+ // TODO be smarter
+bool thumbnail_movie(const std::string &src, int w, int h, const std::string &dest)
+{
+ std::string command = str(boost::format("totem-video-thumbnailer -s %1% %2% %3%")
+ % std::max(w,h) % src % dest);
+ return system(command.c_str()) != -1;
+}
+
+}
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0))
+ indent-tabs-mode:nil
+ fill-column:80
+ End:
+*/
diff --git a/src/fwk/toolkit/movieutils.hpp b/src/fwk/toolkit/movieutils.hpp
new file mode 100644
index 0000000..936030e
--- /dev/null
+++ b/src/fwk/toolkit/movieutils.hpp
@@ -0,0 +1,43 @@
+/*
+ * niepce - fwk/movieutils.hpp
+ *
+ * Copyright (C) 2011 Hub Figuiere
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FWK_MOVIEUTILS_HPP_
+#define __FWK_MOVIEUTILS_HPP_
+
+#include <string>
+
+namespace fwk {
+
+/** Make a thumbnail for a movie. */
+bool thumbnail_movie(const std::string &movie, int w, int h, const std::string &thumbnail);
+
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0))
+ indent-tabs-mode:nil
+ fill-column:80
+ End:
+*/
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]