Added support for strftime() format to creator name text
[harmattan/cameraplus] / lib / qtcammetadata.cpp
1 /*!
2  * This file is part of CameraPlus.
3  *
4  * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21 #include "qtcammetadata.h"
22 #include <gst/gsttaglist.h>
23 #include "qtcamdevice.h"
24 #include "qtcamdevice_p.h"
25 #include <QDebug>
26 #include <QDate>
27 #include <QTime>
28 #include <QDateTime>
29 #include <QPointer>
30 #include <ctime>
31
32 const char *orientations[] = {
33   "rotate-0",
34   "rotate-90",
35   "rotate-180",
36   "rotate-270"
37 };
38
39 class QtCamMetaDataPrivate {
40 public:
41   void addTag(const char *tag, const QString& value) {
42     GstTagSetter *s = setter();
43     if (!s) {
44       return;
45     }
46
47     gst_tag_setter_add_tags(s, GST_TAG_MERGE_REPLACE, tag, value.toUtf8().data(), NULL);
48
49     gst_object_unref(s);
50   }
51
52   void addTag(const char *tag, double value) {
53     GstTagSetter *s = setter();
54     if (!s) {
55       return;
56     }
57
58     gst_tag_setter_add_tags(s, GST_TAG_MERGE_REPLACE, tag, value, NULL);
59
60     gst_object_unref(s);
61   }
62
63   void addTag(const char *tag, GstDateTime *value) {
64     GstTagSetter *s = setter();
65     if (!s) {
66       return;
67     }
68
69     gst_tag_setter_add_tags(s, GST_TAG_MERGE_REPLACE, tag, value, NULL);
70
71     gst_object_unref(s);
72   }
73
74   GstTagSetter *setter() {
75     if (!device || !device->d_ptr->cameraBin) {
76       return 0;
77     }
78
79     if (!GST_IS_TAG_SETTER(device->d_ptr->cameraBin)) {
80       return 0;
81     }
82
83     return GST_TAG_SETTER(gst_object_ref(device->d_ptr->cameraBin));
84   }
85
86   QPointer<QtCamDevice> device;
87 };
88
89 QtCamMetaData::QtCamMetaData(QObject *parent) :
90   QObject(parent), d_ptr(new QtCamMetaDataPrivate) {
91 }
92
93 QtCamMetaData::~QtCamMetaData() {
94   setDevice(0);
95   delete d_ptr; d_ptr = 0;
96 }
97
98 void QtCamMetaData::setDevice(QtCamDevice *device) {
99   if (device != d_ptr->device) {
100     d_ptr->device = device;
101   }
102 }
103
104 void QtCamMetaData::setManufacturer(const QString& manufacturer) {
105   d_ptr->addTag(GST_TAG_DEVICE_MANUFACTURER, manufacturer);
106 }
107
108 void QtCamMetaData::setModel(const QString& model) {
109   d_ptr->addTag(GST_TAG_DEVICE_MODEL, model);
110 }
111
112 void QtCamMetaData::setCountry(const QString& country) {
113   d_ptr->addTag(GST_TAG_GEO_LOCATION_COUNTRY, country);
114 }
115
116 void QtCamMetaData::setCity(const QString& city) {
117   d_ptr->addTag(GST_TAG_GEO_LOCATION_CITY, city);
118 }
119
120 void QtCamMetaData::setSuburb(const QString& suburb) {
121   d_ptr->addTag(GST_TAG_GEO_LOCATION_SUBLOCATION, suburb);
122 }
123
124 void QtCamMetaData::setLongitude(double longitude) {
125   d_ptr->addTag(GST_TAG_GEO_LOCATION_LONGITUDE, longitude);
126 }
127
128 void QtCamMetaData::setLatitude(double latitude) {
129   d_ptr->addTag(GST_TAG_GEO_LOCATION_LATITUDE, latitude);
130 }
131
132 void QtCamMetaData::setElevation(double elevation) {
133   d_ptr->addTag(GST_TAG_GEO_LOCATION_ELEVATION, elevation);
134 }
135
136 void QtCamMetaData::setOrientation(Orientation orientation) {
137   int len = sizeof(orientations) / sizeof(orientations[0]);
138
139   if (orientation <= 0 || orientation >= len) {
140     orientation = Landscape;
141   }
142
143   d_ptr->addTag(GST_TAG_IMAGE_ORIENTATION, orientations[orientation]);
144 }
145
146 void QtCamMetaData::setArtist(const QString& artist) {
147   /* try the shortcut first */
148   if (!artist.contains('%')) {
149     d_ptr->addTag(GST_TAG_ARTIST, artist);
150     return;
151   }
152
153   std::vector<char> result(artist.size());
154   struct tm tm;
155   time_t t;
156   t = time(NULL);
157   if (t == -1) {
158     qWarning() << "Failed to get current time";
159     d_ptr->addTag(GST_TAG_ARTIST, artist);
160     return;
161   }
162
163   if (!localtime_r(&t, &tm)) {
164     qWarning() << "Failed to get local time";
165     d_ptr->addTag(GST_TAG_ARTIST, artist);
166     return;
167   }
168
169   while (!strftime(result.data(), result.size(), artist.toUtf8().constData(), &tm)) {
170     result.resize(result.size() * 2);
171   }
172
173   d_ptr->addTag(GST_TAG_ARTIST, QString::fromUtf8(result.data()));
174 }
175
176 void QtCamMetaData::setDateTime(const QDateTime& dateTime) {
177   QDate d = dateTime.date();
178   QTime t = dateTime.time();
179
180   int day = d.day();
181   int month = d.month();
182   int year = d.year();
183   int hour = t.hour();
184   int minute = t.minute();
185
186   // GstDateTime seconds expects microseconds to be there too :|
187   gdouble seconds = t.second();
188   seconds += t.msec()/(1000.0);
189
190   // Current UTC time. Created through string so that the link between
191   // current and utc is lost and secsTo returns non-zero values.
192   QDateTime utcTime = QDateTime::fromString(dateTime.toUTC().toString());
193   gfloat tzoffset = (utcTime.secsTo(dateTime)/3600.0);
194
195   GstDateTime *dt = gst_date_time_new(tzoffset, year, month, day,
196                                       hour, minute, seconds);
197
198   d_ptr->addTag(GST_TAG_DATE_TIME, dt);
199
200   gst_date_time_unref(dt);
201 }
202
203 void QtCamMetaData::setCaptureDirection(double direction) {
204   d_ptr->addTag(GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, direction);
205 }
206
207 void QtCamMetaData::setHorizontalError(double error) {
208   d_ptr->addTag(GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, error);
209 }
210
211 void QtCamMetaData::reset() {
212   GstTagSetter *s = d_ptr->setter();
213   if (!s) {
214     return;
215   }
216
217   gst_tag_setter_reset_tags(s);
218
219   gst_object_unref(s);
220 }