Wednesday, January 13, 2010

Post's prior to December can all be found at

http://students.gctaa.net/~rbrooke/year2/index.html
I went to activities.sugarlabs.org

And repackaged TimeLapse on the XO with all of the changes that we have made. Then I uploaded the repackaged TimeLapse and finally published the activity, with all of the information about it filled in. This also included a screenshot of TimeLapse in action.

http://activities.sugarlabs.org/en-US/sugar/addon/4270

Is the link to where TimeLapse is available for experimental download.
Tuesday, December 8, 2009

Going to Frank's House

Today, after quickly fixing a bug in TimeLapse at the career center, I went with Peter to Frank's house. The entire thing ran very smoothly and Frank was impressed with the changes we had made, especially the improved sound!! He also had some suggestions about changes that we could make to improve TimeLapse.

1) Have items play when they are double-clicked
2) Enable items that do not have a picture to play
3) Create a confirmation window for the delete all button

Hopefully, we will be able to make this changes without a hitch!

Old TimeLapse

Old TimeLapse

Tuesday, December 15, 2009


Have item play when it is double clicked

@glade_callback
    def doubleclicked(self, data, third):
        if os.path.isfile(os.path.abspath(self.soundfile)):
            self.player.set_property("uri", "file://" +
                                     os.path.abspath(self.soundfile))
        self.player.set_state(gst.STATE_PLAYING)
        else:
           pass


Fix bug where data can not be selected if it does not have a picture  

def itemSelected(self,data):
        self.timestamp = data.get_cells()[0].get_property("text")
        def datum_by_tag(tag):
            return xmlhelper.get_datum_by_timestamp(self.timestamp, tag)
        self.filepath = datum_by_tag("filepath")
        try:
            image = datum_by_tag("image")
        except:
            image = "noImage.jpg"
        myPixbuf = gtk.gdk.pixbuf_new_from_file_at_size(image, 400, 400)
        self.MainImage.set_from_pixbuf(myPixbuf)
        self.soundfile = datum_by_tag("sound")
        if self.soundfile is not None:
            self.interface.get_widget("play_button").set_sensitive(True)
        else:
            self.interface.get_widget("play_button").set_sensitive(False)

Confirmation Window for Delete All button
    
    @glade_callback
    def deleteAllClicked(self, data):
        self.interface.get_widget("delete_confirmation").show()

    @glade_callback
    def deleteAllConfirmed(self, data):
        print "all deleted"
        self.update_pixbuf()
        shutil.rmtree("data/")
        os.mkdir("data")
        xmlhelper.remove_all_data()
        self.update_pixbuf()
        self.interface.get_widget("delete_confirmation").hide()
    
    @glade_callback
    def deleteAllCanceled(self, data):
        self.interface.get_widget("delete_confirmation").hide()



Today I worked on the canvas.glade to fix some of the minor glade problems that were plaguing it.

The first thing that I fixed was the spacing and placement of each collection.

The next thing that I did was add a horizontal and vertical scroll bar to the window where the collections were being displayed.

Creating An .xo file

Creating An .xo file

Step 1

Create setup.py in the same directory that the Activity program is in and copy the lines below into it.

#!/usr/bin/env python

# Copyright (C) 2006, Red Hat, Inc.
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

from sugar.activity import bundlebuilder

bundlebuilder.start()

Step 2

Next create a directory within the one that the program is in and name it Activity.


Step 3


Create a file named activity.info within the Activity directory and copy the lines below into it (replace example and ex with the name of your activity)




[Activity]
name = (name of your activity)
bundle_id = example
icon = exampleicon
exec = sugar-activity exActivity.exampleActivity
show_launcher = yes
activity_version = 1
license = GPLv2+




name


The name of your Activity as it will appear to the user.


bundle_id or service_name


A unique name that Sugar will use to refer to your Activity.  Any Journal entry created by your Activity will have this name stored in its metadata, so that when someone resumes the Journal entry Sugar knows to use the program that created it to read it.

icon


The name of the icon file you have created for the Activity.  Since icons are always .svg files the icon file in the example is named example.svg.

exec

This tells Sugar how to launch your Activity.  What it says is to create an instance of the class exampleActivity which it will find in file exampleActivity.py.

show_launcher

There are two ways to launch an Activity.  The first is to click on the icon in the Activity view.  The second is to resume an entry in the Journal. Activities that don't create Journal entries can only be resumed from the Journal, so there is no point in putting an icon in the Activity ring for them.

activity_version

An integer that represents the version number of your program.  The first version is 1, the next is 2, and so on.

license

With a computer program there is always a license that tells the person receiving the program what he or she is allowed to do with it.  GPLv2+ is a popular standard license that can be used for Activities.




Step 4

Create an icon that contains the same name as the one used in activity.info with .svg added on to it.
To make the icon, I would recommend using Inkscape.
In Inkscape, go to file, new and select icon_48x48.
This icon size drawing is ideal for sugar activities.

Step 5

Modify icon so it can
work with Sugar.

Specifically, make the icon show Sugar that Sugar can use
its own choice of stroke color and fill color.

(The SVG file format is
based on XML, which means it is a text file with some special tags in
it.)

Once Inkscapecan file is complete, load the file into any text editor and edit it as a text file.


Make the following changes:



Before:


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg


After:

<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
<!ENTITY stroke_color "#000000">
<!ENTITY fill_color "#FFFFFF">
]><svg

Now in the body of the document there are references to fill and stroke as part of an attribute called style.

Every line or shape that is drawn will have these something like this:


<rect
style="fill:#ffffff;stroke:#000000;stroke-opacity:1"
id="rect904"
width="36.142857"
height="32.142857"
x="4.1428571"
y="7.1428571" />

Change each one to look like this:


<rect
style="fill:&fill_color;;stroke:&stroke_color;;stroke-opacity:1"
id="rect904"
width="36.142857"
height="32.142857"
x="4.1428571"
y="7.1428571" />

(Note that &stroke_color; and &fill_color;
both end with semicolons (;), and semicolons are also used to separate
the properties for style.  Because of this it is an extremely common
beginner's mistake to leave off the trailing semicolon because two
semicolons in a row don't look right.  Be assured that the two
semicolons in a row are intentional and absolutely necessary!)


Step 6


Create a file called MANIFEST in the folder that contains the activity.

( Do not put the MANIFEST file in the activity folder in the activity)

The MANIFEST file should contain everything that is a part of the activity.


EX:


setup.py
example.py
activity/example.svg
activity/activity.info


Step 7

In home/Activities/example, type:

./setup.py dev


This is because,
the activity needs to be installed, which in this case means making a symbolic link between the directory that is being used for the code in the home/Activities/ directory.
A symbolic link is a way to make a file or directory appear to be located in more than one place without copying it.
By typing ./setup.py dev , this makes symbolic link by running setup.py again

Step 8

In home/Activities/example
type

./setup.py dist_xo

This will create the xo file and place it in a new folder called dist in the Activity directory.


Tuesday, January 12, 2010

Under the cameramic section in the computer post, you will notice that some sections are highlighted because these are the sections that I added coding to so that the quality tab would work with TimeLapse.

you will notice that width, height, and rate are all = %d, and right after each of them I have % qualitytab.tab.width or qualitytab.tab.height, qualitytab.tab.rate

This means that the value for what width, height, and rate are is based upon the values dictated in my qualitytab.py which is in-turn based upon where the slider is placed by the user.

You will also notice that at the end of each def, wrote print qualitytab.tab.width or qualitytab.tab.height, qualitytab.tab.rate, that way the developers can look at the terminal to see what values are actually being used in TimeLapse, helping anyone who wants to make changes to the existing qualitytab.py
after thursday, I worked on creating the double-click function and uploading our Activity to sugarlabs.

[the post below contains my code for the double-click function]

Today I worked on making the sliders actually do something in Timelapse. This led to me writing the code in the post below.

By the end of the day, I had created a quality tab that actually worked for TimeLapse.

To make the values for video, only input width x height ratios of 4:3 and for audio values, I only input rates based on a 6,000 scale.

Because the coding would be to complicated to have the slider stop at specific values, I just made Timelapse give a value based upon where the slider is in proximity with the closest value.

For example, if the slider goes to 2.76 then the code will use the value width = 256 & height = 192.

Computer

Double Click

def doubleclicked(self, data, third):
        if os.path.isfile(os.path.abspath(self.soundfile)):
            self.player.set_property("uri", "file://" +
                                     os.path.abspath(self.soundfile))
        self.player.set_state(gst.STATE_PLAYING)
        else:
           pass


Quality Tab

class Tab(interface.NewTab):
    def make(self):
        # change these to glade callbacks later.
        self.video, self.audio, self.image, self.lapse, self.width, self.height, self.rate = 4, 4, 4, 4, 100, 75, 12000

    def on_video_changed(self, widget):
        self.video = widget.get_value()
        print "video quality", self.video
    if self.video < 1.50:
        self.width = 100
        self.height = 75
    if self.video >= 1.50 and self.video < 2.50:
        self.width = 200
        self.height = 150
        print "optimal"
    if self.video >= 2.50 and self.video < 3.50:
        self.width = 256
        self.height = 192
    if self.video >= 3.50 and self.video < 4.50:
        self.width = 320
        self.height = 240
    if self.video >= 4.50 and self.video < 5.50:
        self.width = 400
        self.width = 300
    if self.video >= 5.50 and self.video <= 6.00:
        self.width = 512
        self.height = 384

    def on_audio_changed(self, widget):
        self.audio = widget.get_value()        
    print "audio quality", self.audio
    if self.audio < 1.50:
        self.rate = 12000
    if self.audio >= 1.50 and self.video < 2.50:
        self.rate = 18000
    if self.audio >= 2.50 and self.video < 3.50:
        self.rate = 24000
    if self.audio >= 3.50 and self.video < 4.50:
        self.rate = 30000
    if self.audio >= 4.50 and self.video < 5.50:
        self.rate = 36000
    if self.audio >= 5.50 and self.video <= 6.00:
        self.rate = 48000

Cameramic

 def video(self):
        VIDEO_GST_PIPE = ['v4l2src', 'queue', 'videorate',
                          'video/x-raw-yuv,framerate=15/1', 'videoscale',
                          'video/x-raw-yuv,width=%d,height=%d' % (qualitytab.tab.width, qualitytab.tab.height),
                          'ffmpegcolorspace', 'theoraenc', 'oggmux']
        pipe = VIDEO_GST_PIPE + ["filesink location=%s" % (self.video_temp)]
        self.video_pipe = gst.parse_launch('!'.join(pipe))
        self.video_pipe.set_state(gst.STATE_PLAYING)
    print qualitytab.tab.width
    print qualitytab.tab.height
            
    def audio(self):
        AUDIO_GST_PIPE = ["alsasrc",
                          "audio/x-raw-int,rate=%d,channels=1,depth=16" %
                          qualitytab.tab.rate, "audioconvert","flacenc"]
        pipe = AUDIO_GST_PIPE + ["filesink location=%s" % (self.audio_temp)]
        self.audio_pipe = gst.parse_launch('!'.join(pipe))
        self.audio_pipe.set_state(gst.STATE_PLAYING)
    print qualitytab.tab.rate        


Thursday, January 7, 2010

I just figure out how to make the sliders actual work, it all had to be done in glade and the answer came after thirty minutes of google searches.

http://tadeboro.blogspot.com/2009/09/glade3-tutorial-4-gtktreeview-data.html

I finally found this site, which told me to set the page_size = 0.00, after I did that and opened TimeLapse again, the sliders worked.
Worked on the slider bars under the quality tab today.
Making them functional and adding actual values to them.

For Video Quality, there will be six value:

Value 1 = 200 x 150
Value 2 = 256 x 192
Value 3 = 320 x 240
Value 4 = 400 x 300
Value 5 = 512 x 384
Value 6 = 640 x 480
Because the def image was not creating a snapshot, I wondered if maybe it was because of the Video function which was maybe conflicting with image, because we never set an order for the program. This means that it was trying to take a snapshot and record video at the same time. So you can see where this might have cause problems. We ended up having the computer take a picture first then record video and sound. So we changed the order in which they ran, making image run first then video and audio at the same time.

Tuesday, January 5, 2010

This involved making the image button function, so that when data was collected and image was taken and not just a video and sound.

def image(self):
self.image_path = "/tmp/tmp" + str(time.time())

IMAGE_GST_PIPE = ['v4l2src', 'ffmpegcolorspace', 'pngenc']
pipe = IMAGE_GST_PIPE + ['filesink location=%s' % (self.image_path)]
self.bus = self.pipe.get_bus()
self.pipe.set_state(gst.STATE_PLAYING)
self.bus.poll(gst.MESSAGE_EOS, -1)

self.file_dsobject = datastore.create()
self.file_dsobject.metadata['title'] = "Image Sample"
self.file_dsobject.metadata['mime_type'] = 'image/png'
self.file_dsobject.set_file_path(self.image_path)
datastore.write(self.file_dsobject)
self.file_dsobject.destroy()
Peter ended up changing the entire interface but had not had time to actually make all of the buttons and objects functional. This meant I spent most of today fixing this problem when I was not working on the video issue.

Today

After finally getting internet after being on vacation for two weeks, I find myself scrambling to catch up on all the new emails and updates going around. I looked at the new code and immediately saw a problem with the video recordings. All of the video recordings came back very pixelated.

To fix this problem i went into cameramic.py and looked at

def video(self):
VIDEO_GST_PIPE = ['v4l2src', 'queue', 'videorate',
'video/x-raw-yuv,framerate=15/1', 'videoscale',
'video/x-raw-yuv,width=160,height=120',
'ffmpegcolorspace', 'theoraenc', 'oggmux']
pipe = VIDEO_GST_PIPE + ["filesink location=%s" % (self.video_path)]
self.video_pipe = gst.parse_launch('!'.join(pipe))
self.video_pipe.set_state(gst.STATE_PLAYING)

I had originally tried to up the video scale to

def video(self):
VIDEO_GST_PIPE = ['v4l2src', 'queue', 'videorate',
'video/x-raw-yuv,framerate=15/1', 'videoscale',
'video/x-raw-yuv,width=640,height=480',
'ffmpegcolorspace', 'theoraenc', 'oggmux']
pipe = VIDEO_GST_PIPE + ["filesink location=%s" % (self.video_path)]
self.video_pipe = gst.parse_launch('!'.join(pipe))
self.video_pipe.set_state(gst.STATE_PLAYING)

but it ended up creating a very crisp video but it was incredibaly choppy. I spent a long time fiddling with the video scale til I came up

def video(self):
VIDEO_GST_PIPE = ['v4l2src', 'queue', 'videorate',
'video/x-raw-yuv,framerate=15/1', 'videoscale',
'video/x-raw-yuv,width=200,height=150',
'ffmpegcolorspace', 'theoraenc', 'oggmux']
pipe = VIDEO_GST_PIPE + ["filesink location=%s" % (self.video_path)]
self.video_pipe = gst.parse_launch('!'.join(pipe))
self.video_pipe.set_state(gst.STATE_PLAYING)

Today

Hello All!!!

Yes I am a few weeks behind, but I am hoping that with some extra time and elbow grease, I will be able to fully update this sight.

Tuesday, June 9, 2009

Forgotten Work

Hey All,

I just found a bunch of old programs that i wrote at the beginning of the quarter and had forgotten to post them. So here they are...

Old Forgotten Programs

1. Pixmap - Pixmaps are data structures that contain pictures. These pictures can be used in various places, but most commonly as icons on the X desktop, or as cursors.

2. Ruler Grid - Ruler widgets are used to indicate the location of the mouse pointer in a given window. A window can have a horizontal ruler spanning across the width and a vertical ruler spanning down the height. A small triangular indicator on the ruler shows the exact location of the pointer relative to the ruler.

3. Status Bar - Statusbars are simple widgets used to display a text message. They keep a stack of the messages pushed onto them, so that popping the current message will re-display the previous text message. In order to allow different parts of an application to use the same statusbar to display messages, the statusbar widget issues Context Identifiers which are used to identify different "users". The message on top of the stack is the one displayed, no matter what context it is in. Messages are stacked in last-in-first-out order, not context identifier order.

4. Text Entry - The Entry widget allows text to be typed and displayed in a single line text box. The text may be set with method calls that allow new text to replace, prepend or append the current contents of the Entry widget.

5. Spin Buttons - The SpinButton widget is generally used to allow the user to select a value from a range of numeric values. It consists of a text entry box with up and down arrow buttons attached to the side. Selecting one of the buttons causes the value to "spin" up and down the range of possible values. The entry box may also be edited directly to enter a specific value. The SpinButton allows the value to have zero or more decimal places and to be incremented/decremented in configurable steps. The action of holding down one of the buttons optionally results in an acceleration of change in the value according to how long it is depressed.

6. Calendar - The Calendar widget is an effective way to display and retrieve monthly date related information.

7. Color Selection - The color selection widget is, not surprisingly, a widget for interactive selection of colors. This composite widget lets the user select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue, Saturation, Value) triples. This is done either by adjusting single values with sliders or entries, or by picking the desired color from a hue-saturation wheel/value bar. Optionally, the opacity of the color can also be set. The color selection widget currently emits only one signal, "color_changed", which is emitted whenever the current color in the widget changes, either when the user changes it or if it's set explicitly through the set_color() method.

8. File Selection - The file selection widget is a quick and simple way to display a File dialog box. It comes complete with Ok, Cancel, and Help buttons, a great way to cut down on programming time.

9. Action (Event) Box - At first glance, the EventBox widget might appear to be totally useless. It draws nothing on the screen and responds to no events. However, it does serve a function - it provides an X window for its child widget. This is important as many GTK widgets do not have an associated X window. Not having an X window saves memory and improves performance, but also has some drawbacks. A widget without an X window cannot receive events, does not perform any clipping on its contents and cannot set its background color. Although the name EventBox emphasizes the event-handling function, the widget can also be used for clipping.

10. Scroll Window - Scrolled windows are used to create a scrollable area with another widget inside it. You may insert any type of widget into a scrolled window, and it will be accessible regardless of the size by using the scrollbars.

11. Button Box - ButtonBoxes are a convenient way to quickly layout a group of buttons. They come in both horizontal and vertical flavors.

12. Toolbar - Toolbars are usually used to group some number of widgets in order to simplify customization of their look and layout. Typically a toolbar consists of buttons with icons, labels and tooltips, but any other widget can also be put inside a toolbar. Finally, items can be arranged horizontally or vertically and buttons can be displayed with icons, labels, or both.

13. Notebook - The NoteBook Widget is a collection of "pages" that overlap each other; each page contains different information with only one page visible at a time. This widget has become more common lately in GUI programming, and it is a good way to show blocks of similar information that warrant separation in their display.

Friday, June 5, 2009

This Week

Thursday - Friday
Arranged days next week to meet with James.
-Discuss how GVR works
-Discuss what James has accomplished so far
-Discuss what I am attempting to fix
-Discuss program that i have written and how to translate it into the fabric of GVR

Screen Following Program

Monday - Wednesday
I have formulated my questions to ask Stas and James

Stas
-Since the size of the GVR window depends upon the actual screen of the computer how is the grid created?

James
-I realize that the background image will have to do the inverse of the commands inputed to give the allusion of movement to the player, but where is the code that recieves these commands from the player?

Python Joke



Funny python joke from xkcd.com

Wednesday, June 3, 2009

This Week

Friday
I began to formulate questions for Stas about GVR and the code that i will have to fix. I hope to finish formulated all of my questions by the end of next week and submit them to Stas.

Monday-Thursday
I successfully finished writing the code for the pygame program in which the screen moved and not the player, or in this case a circle.
Screen Following Program