4
#by Joel Auterson (joel.auterson@googlemail.com)
5
#http://www.launchpad.net/photostory
4
# Joel Auterson (joel.auterson@googlemail.com)
5
# http://launchpad.net/photostory
12
from time import strftime
7
import time, os, cPickle, gtk, gst, glib
17
8
from threading import Timer
28
self.adj = gtk.Adjustment(5, 1, 10, 1)
31
# If the `~/.photostory/photos` directory doesn't exist, create it:
32
if not os.path.exists(os.path.expanduser('~/.photostory/photos')):
33
os.makedirs(os.path.expanduser('~/.photostory/photos'))
35
# If the `~/.photostory/db` pickle doesn't exist, create it:
36
if not os.path.isfile(os.path.expanduser('~/.photostory/db')):
37
cPickle.dump({}, open(os.path.expanduser('~/.photostory/db'), 'w'))
39
# If the `~/.photostory/num` pickle doesn't exist, create it:
40
if not os.path.isfile(os.path.expanduser('~/.photostory/num')):
41
cPickle.dump(0, open(os.path.expanduser('~/.photostory/num'), 'w'))
43
# Load the `db` and `num` pickles:
44
self.db = cPickle.load(open(os.path.expanduser('~/.photostory/db'), 'rb'))
45
self.ind = int(cPickle.load(open(os.path.expanduser('~/.photostory/num'), 'rb')))
47
todayPicName = os.path.expanduser('~/.photostory/photos/') + str(self.ind) + ".png"
51
dateTuple = cal.get_date()
55
print 'ind ' + str(self.ind)
56
print 'db' + str(self.db)
57
cPickle.dump(self.db, open(os.path.expanduser('~/.photostory/db'), 'wb'))
58
cPickle.dump(self.ind, open(os.path.expanduser('~/.photostory/num'), 'wb'))
62
dAbout = gtk.AboutDialog()
63
dAbout.set_name("Photostory")
64
dAbout.set_comments("Photostory is an application that lets you tell the story of your life in photos, by taking a snapshot of you each day. You can then make these into a video to share with friends or on the internet.")
65
dAbout.set_artists(("Josh Brown", ""))
66
dAbout.set_authors(("Joel Auterson", "David Turner", "Josh Brown"))
67
dAbout.set_website("http://launchpad.net/photostory")
68
response = dAbout.run()
74
def movPick(movFileButton):
75
movPicker = gtk.FileChooserDialog(title="Choose a save location", parent=movDia, action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(("Save Here", -6)), backend=None)
76
movRes = movPicker.run()
78
self.movPath = movPicker.get_filename()
81
def movGen(movButton):
85
filmPipe = gst.Pipeline("filmPipe")
86
filmSrc = gst.element_factory_make("multifilesrc", "filmSrc")
87
filmSrc.set_property("location", os.path.expanduser("~/.photostory/photos/") + "%d.png")
88
filmFilt1 = gst.element_factory_make("capsfilter", "filmFilt1")
89
filmCap1 = gst.Caps("image/png,framerate=" + str(int(self.adj.get_value())) + "/1,pixel-aspect-ratio=1/1")
90
filmFilt1.set_property("caps", filmCap1)
91
filmPngDec = gst.element_factory_make("pngdec", "filmPngDec")
92
filmff = gst.element_factory_make("ffmpegcolorspace", "filmff")
93
filmFilt2 = gst.element_factory_make("capsfilter", "filmFilt2")
94
filmCap2 = gst.Caps("video/x-raw-yuv")
95
filmFilt2.set_property("caps", filmCap2)
96
filmTheora = gst.element_factory_make("xvidenc", "filmTheora")
97
filmOggmux = gst.element_factory_make("ffmux_mp4", "filmOggmux")
98
filmFilesink = gst.element_factory_make("filesink", "filmFilesink")
99
filmFilesink.set_property("location", self.movPath)
101
filmPipe.add(filmSrc, filmFilt1, filmPngDec, filmff, filmFilt2, filmTheora, filmOggmux, filmFilesink)
102
gst.element_link_many(filmSrc, filmFilt1, filmPngDec, filmff, filmFilt2, filmTheora, filmOggmux, filmFilesink)
103
filmPipe.set_state(gst.STATE_PLAYING)
105
filmBut.set_sensitive(True)
107
movDia = gtk.Window(gtk.WINDOW_TOPLEVEL)
108
movDia.set_title("Create Film")
109
movDia.set_resizable(False)
110
filmBut.set_sensitive(False)
111
movVbox = gtk.VBox(homogeneous=False, spacing=2)
112
movLabel = gtk.Label("Here you can create a video made up of all your photos. \n\nJust choose a save location and hit 'create'.\n\nRemember, the path must end in '.mp4'.\n")
113
movFileButton = gtk.Button(label="Choose a location")
114
movButton = gtk.Button(label="Create")
117
movSliderBox = gtk.HBox(homogeneous=False, spacing=3)
118
movSliderLabel = gtk.Label("FPS:")
119
movSlider = gtk.HScale(self.adj)
120
movSlider.set_digits(0)
121
movSliderBox.pack_start(movSliderLabel, expand=False)
122
movSliderBox.pack_start(movSlider, expand=True)
125
movVbox.pack_start(movLabel, expand=False)
126
movVbox.pack_start(movSliderBox, expand=False)
127
movVbox.pack_start(movFileButton, expand=False)
128
movVbox.pack_start(movButton, expand=False)
129
movButton.connect("clicked", movGen)
130
movFileButton.connect("clicked", movPick)
133
def capture(takeBut):
136
pipeline.set_state(gst.STATE_NULL)
137
stillPipe = gst.Pipeline("stillPipe")
138
stillCam = gst.element_factory_make("v4l2src", "stillPipe")
139
stillFilt = gst.element_factory_make("capsfilter", "stillFilt")
140
stillCap = gst.Caps("video/x-raw-yuv,width=640,height=480")
141
stillFilt.set_property("caps", stillCap)
142
ffmpegcolorspace = gst.element_factory_make("ffmpegcolorspace", "ffmpegcolorspace")
143
pngEnc = gst.element_factory_make("pngenc", "pngenc")
144
filesink = gst.element_factory_make("filesink", "filesink")
145
filesink.set_property("location", todayPicName)
146
self.db[todayDate] = todayPicName
148
cal.select_month(todayDate[1], todayDate[0])
149
cal.select_day(todayDate[2])
151
stillPipe.add(stillCam, stillFilt, ffmpegcolorspace, pngEnc, filesink)
152
gst.element_link_many(stillCam, stillFilt, ffmpegcolorspace, pngEnc, filesink)
153
stillPipe.set_state(gst.STATE_PLAYING)
155
stillPipe.set_state(gst.STATE_NULL)
156
xvimagesink.set_xwindow_id(movie.window.xid)
157
pipeline.set_state(gst.STATE_PLAYING)
161
def countdown(n = 3):
162
self.pic.set_markup("<span size='54000'>" + str(n) + "</span>")
164
else: glib.timeout_add(1000, countdown, n-1)
168
def deletePic(deleteBut):
169
def getKey(dic, val):
170
return [k for k, v in dic.iteritems() if v == val][0]
171
date = cal.get_date()
173
os.remove(self.db[date])
175
if date == todayDate:
176
takeBut.set_label("Take today's photo")
177
takeBut.set_sensitive(True)
180
for element in self.db:
181
oldPath = os.path.expanduser('~/.photostory/photos/') + str(i) + ".png"
182
if not os.path.exists(oldPath):
185
oldPath = os.path.expanduser('~/.photostory/photos/') + str(i) + ".png"
186
if os.path.exists(oldPath):
187
key = getKey(self.db, oldPath)
188
newPath = os.path.expanduser('~/.photostory/photos/') + str(i-gaps) + ".png"
189
os.rename(oldPath, newPath)
190
self.db[key] = newPath
197
vbox1.remove(self.pic)
200
self.pic = gtk.Image()
201
self.pic.set_from_file(self.db[date])
202
takeBut.set_label("Photo taken for this day.")
203
takeBut.set_sensitive(False)
205
if date == todayDate:
206
takeBut.set_label("Take today's photo")
207
takeBut.set_sensitive(True)
209
takeBut.set_label("Take today's photo")
210
takeBut.set_sensitive(False)
211
self.pic = gtk.Label()
212
self.pic.set_justify(gtk.JUSTIFY_CENTER)
213
self.pic.set_markup("<span size='54000'>No Photo\nToday</span>");
214
self.pic.set_size_request(640, 480)
215
vbox1.pack_start(self.pic)
216
vbox1.pack_start(hbox2)
220
self.win = gtk.Window(gtk.WINDOW_TOPLEVEL)
221
self.win.connect("destroy", closedown)
222
self.win.set_default_size(900, 600)
223
self.win.set_resizable(False)
224
self.win.set_title("Photostory")
225
if os.path.exists("photostory.svg"):
226
self.win.set_icon_from_file("photostory.svg")
227
movie = gtk.DrawingArea()
228
movie.set_size_request(320, 240)
229
hbox = gtk.HBox(homogeneous=False, spacing=3)
230
vbox1 = gtk.VBox(homogeneous=False)
231
vbox2 = gtk.VBox(homogeneous = False)
232
filmBut = gtk.Button(label="Create Film")
233
filmBut.connect("clicked", movify)
234
deleteBut = gtk.Button(label="Delete Photo")
235
deleteBut.connect("clicked", deletePic)
236
shareBut = gtk.Button(label="Share Video")
237
hbox2 = gtk.HBox(homogeneous=True)
238
aboutBut = gtk.Button(label="About")
239
aboutBut.connect("clicked", about)
242
todayDate = cal.get_date()
243
cal.connect("day-selected", chooseDay)
245
takeBut = gtk.Button(label="Take today's photo")
246
takeBut.connect("clicked", capture)
251
hbox.pack_start(vbox1, expand=False)
252
hbox2.pack_start(filmBut, expand=False)
253
hbox2.pack_start(deleteBut, expand=False)
254
#hbox2.pack_start(shareBut)
255
hbox2.pack_start(aboutBut)
256
vbox2.pack_start(movie)
257
vbox2.pack_start(cal, expand=False, padding=25)
258
vbox2.pack_start(takeBut, expand=False)
259
hbox.pack_start(vbox2)
263
#Pipeline stuff - feed
264
pipeline = gst.Pipeline("mypipeline")
266
camera = gst.element_factory_make("v4l2src", "camera")
267
camera.set_property("device", "/dev/video0")
269
caps = gst.Caps("video/x-raw-yuv,width=640,height=480,framerate=30/1")
270
filt = gst.element_factory_make("capsfilter", "filter")
271
filt.set_property("caps", caps)
273
xvimagesink = gst.element_factory_make("xvimagesink", "sink")
275
pipeline.add(camera, filt, xvimagesink)
276
gst.element_link_many(camera, filt, xvimagesink)
14
adj = gtk.Adjustment(5, 1, 10, 1)
17
# If the `~/.photostory/photos` directory doesn't exist, create it:
18
if not os.path.exists(os.path.expanduser('~/.photostory/photos')):
19
os.makedirs(os.path.expanduser('~/.photostory/photos'))
21
# If the `~/.photostory/db` pickle doesn't exist, create it:
22
if not os.path.isfile(os.path.expanduser('~/.photostory/db')):
23
cPickle.dump({}, open(os.path.expanduser('~/.photostory/db'), 'w'))
25
# If the `~/.photostory/num` pickle doesn't exist, create it:
26
if not os.path.isfile(os.path.expanduser('~/.photostory/num')):
27
cPickle.dump(0, open(os.path.expanduser('~/.photostory/num'), 'w'))
29
# Load the `db` and `num` pickles:
30
db = cPickle.load(open(os.path.expanduser('~/.photostory/db'), 'rb'))
31
ind = int(cPickle.load(open(os.path.expanduser('~/.photostory/num'), 'rb')))
33
todayPicName = os.path.expanduser('~/.photostory/photos/') + str(self.ind) + ".png"
37
dateTuple = cal.get_date()
41
print 'ind ' + str(ind)
43
cPickle.dump(db, open(os.path.expanduser('~/.photostory/db'), 'wb'))
44
cPickle.dump(ind, open(os.path.expanduser('~/.photostory/num'), 'wb'))
48
dAbout = gtk.AboutDialog()
49
dAbout.set_name("Photostory")
50
dAbout.set_comments("Photostory is an application that lets you tell the story of your life in photos, by taking a snapshot of you each day. You can then make these into a video to share with friends or on the internet.")
51
dAbout.set_artists(("Josh Brown"))
52
dAbout.set_authors(("Joel Auterson", "David Turner", "Josh Brown"))
53
dAbout.set_website("http://launchpad.net/photostory")
54
response = dAbout.run()
59
def movPick(movFileButton):
60
movPicker = gtk.FileChooserDialog(title="Choose a save location", parent=movDia, action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(("Save Here", -6)), backend=None)
61
movRes = movPicker.run()
63
movPath = movPicker.get_filename()
66
def movGen(movButton):
69
filmPipe = gst.Pipeline("filmPipe")
70
filmSrc = gst.element_factory_make("multifilesrc", "filmSrc")
71
filmSrc.set_property("location", os.path.expanduser("~/.photostory/photos/") + "%d.png")
72
filmFilt1 = gst.element_factory_make("capsfilter", "filmFilt1")
73
filmCap1 = gst.Caps("image/png,framerate=" + str(int(self.adj.get_value())) + "/1,pixel-aspect-ratio=1/1")
74
filmFilt1.set_property("caps", filmCap1)
75
filmPngDec = gst.element_factory_make("pngdec", "filmPngDec")
76
filmff = gst.element_factory_make("ffmpegcolorspace", "filmff")
77
filmFilt2 = gst.element_factory_make("capsfilter", "filmFilt2")
78
filmCap2 = gst.Caps("video/x-raw-yuv")
79
filmFilt2.set_property("caps", filmCap2)
80
filmTheora = gst.element_factory_make("xvidenc", "filmTheora")
81
filmOggmux = gst.element_factory_make("ffmux_mp4", "filmOggmux")
82
filmFilesink = gst.element_factory_make("filesink", "filmFilesink")
83
filmFilesink.set_property("location", movPath)
85
filmPipe.add(filmSrc, filmFilt1, filmPngDec, filmff, filmFilt2, filmTheora, filmOggmux, filmFilesink)
86
gst.element_link_many(filmSrc, filmFilt1, filmPngDec, filmff, filmFilt2, filmTheora, filmOggmux, filmFilesink)
87
filmPipe.set_state(gst.STATE_PLAYING)
89
filmBut.set_sensitive(True)
91
movDia = gtk.Window(gtk.WINDOW_TOPLEVEL)
92
movDia.set_title("Create Film")
93
movDia.set_resizable(False)
94
filmBut.set_sensitive(False)
95
movVbox = gtk.VBox(homogeneous=False, spacing=2)
96
movLabel = gtk.Label("Here you can create a video made up of all your photos. \n\nJust choose a save location and hit 'create'.\n\nRemember, the path must end in '.mp4'.\n")
97
movFileButton = gtk.Button(label="Choose a location")
98
movButton = gtk.Button(label="Create")
101
movSliderBox = gtk.HBox(homogeneous=False, spacing=3)
102
movSliderLabel = gtk.Label("FPS:")
103
movSlider = gtk.HScale(adj)
104
movSlider.set_digits(0)
105
movSliderBox.pack_start(movSliderLabel, expand=False)
106
movSliderBox.pack_start(movSlider, expand=True)
109
movVbox.pack_start(movLabel, expand=False)
110
movVbox.pack_start(movSliderBox, expand=False)
111
movVbox.pack_start(movFileButton, expand=False)
112
movVbox.pack_start(movButton, expand=False)
113
movButton.connect("clicked", movGen)
114
movFileButton.connect("clicked", movPick)
117
def capture(takeBut):
119
pipeline.set_state(gst.STATE_NULL)
120
stillPipe = gst.Pipeline("stillPipe")
121
stillCam = gst.element_factory_make("v4l2src", "stillPipe")
122
stillFilt = gst.element_factory_make("capsfilter", "stillFilt")
123
stillCap = gst.Caps("video/x-raw-yuv,width=640,height=480")
124
stillFilt.set_property("caps", stillCap)
125
ffmpegcolorspace = gst.element_factory_make("ffmpegcolorspace", "ffmpegcolorspace")
126
pngEnc = gst.element_factory_make("pngenc", "pngenc")
127
filesink = gst.element_factory_make("filesink", "filesink")
128
filesink.set_property("location", todayPicName)
129
db[todayDate] = todayPicName
131
cal.select_month(todayDate[1], todayDate[0])
132
cal.select_day(todayDate[2])
134
stillPipe.add(stillCam, stillFilt, ffmpegcolorspace, pngEnc, filesink)
135
gst.element_link_many(stillCam, stillFilt, ffmpegcolorspace, pngEnc, filesink)
136
stillPipe.set_state(gst.STATE_PLAYING)
138
stillPipe.set_state(gst.STATE_NULL)
278
139
xvimagesink.set_xwindow_id(movie.window.xid)
280
140
pipeline.set_state(gst.STATE_PLAYING)
144
def countdown(n = 3):
145
self.pic.set_markup("<span size='54000'>" + str(n) + "</span>")
147
else: glib.timeout_add(1000, countdown, n-1)
151
def deletePic(deleteBut):
152
def getKey(dic, val):
153
return [k for k, v in dic.iteritems() if v == val][0]
154
date = cal.get_date()
158
if date == todayDate:
159
takeBut.set_label("Take today's photo")
160
takeBut.set_sensitive(True)
164
oldPath = os.path.expanduser('~/.photostory/photos/') + str(i) + ".png"
165
if not os.path.exists(oldPath):
168
oldPath = os.path.expanduser('~/.photostory/photos/') + str(i) + ".png"
169
if os.path.exists(oldPath):
170
key = getKey(db, oldPath)
171
newPath = os.path.expanduser('~/.photostory/photos/') + str(i-gaps) + ".png"
172
os.rename(oldPath, newPath)
185
pic.set_from_file(db[date])
186
takeBut.set_label("Photo taken for this day.")
187
takeBut.set_sensitive(False)
189
if date == todayDate:
190
takeBut.set_label("Take today's photo")
191
takeBut.set_sensitive(True)
193
takeBut.set_label("Take today's photo")
194
takeBut.set_sensitive(False)
196
pic.set_justify(gtk.JUSTIFY_CENTER)
197
pic.set_markup("<span size='54000'>No Photo\nToday</span>");
198
pic.set_size_request(640, 480)
199
vbox1.pack_start(pic)
200
vbox1.pack_start(hbox2)
204
self.win = gtk.Window(gtk.WINDOW_TOPLEVEL)
205
self.win.connect("destroy", closedown)
206
self.win.set_default_size(900, 600)
207
self.win.set_resizable(False)
208
self.win.set_title("Photostory")
209
if os.path.exists("photostory.svg"):
210
self.win.set_icon_from_file("photostory.svg")
211
movie = gtk.DrawingArea()
212
movie.set_size_request(320, 240)
213
hbox = gtk.HBox(homogeneous=False, spacing=3)
214
vbox1 = gtk.VBox(homogeneous=False)
215
vbox2 = gtk.VBox(homogeneous = False)
216
filmBut = gtk.Button(label="Create Film")
217
filmBut.connect("clicked", movify)
218
deleteBut = gtk.Button(label="Delete Photo")
219
deleteBut.connect("clicked", deletePic)
220
shareBut = gtk.Button(label="Share Video")
221
hbox2 = gtk.HBox(homogeneous=True)
222
aboutBut = gtk.Button(label="About")
223
aboutBut.connect("clicked", about)
226
todayDate = cal.get_date()
227
cal.connect("day-selected", chooseDay)
229
takeBut = gtk.Button(label="Take today's photo")
230
takeBut.connect("clicked", capture)
235
hbox.pack_start(vbox1, expand=False)
236
hbox2.pack_start(filmBut, expand=False)
237
hbox2.pack_start(deleteBut, expand=False)
238
#hbox2.pack_start(shareBut)
239
hbox2.pack_start(aboutBut)
240
vbox2.pack_start(movie)
241
vbox2.pack_start(cal, expand=False, padding=25)
242
vbox2.pack_start(takeBut, expand=False)
243
hbox.pack_start(vbox2)
247
#Pipeline stuff - feed
248
pipeline = gst.Pipeline("mypipeline")
249
camera = gst.element_factory_make("v4l2src", "camera")
250
camera.set_property("device", "/dev/video0")
251
caps = gst.Caps("video/x-raw-yuv,width=640,height=480,framerate=30/1")
252
filt = gst.element_factory_make("capsfilter", "filter")
253
filt.set_property("caps", caps)
254
xvimagesink = gst.element_factory_make("xvimagesink", "sink")
255
pipeline.add(camera, filt, xvimagesink)
256
gst.element_link_many(camera, filt, xvimagesink)
257
xvimagesink.set_xwindow_id(movie.window.xid)
258
pipeline.set_state(gst.STATE_PLAYING)