I thought I'd post some snapshots of the new timeline code. I wanted to test the dragging code independently of PiTiVi, so it is being run from an external script.
Timeline displaying some test items at their default size.
The Timeline can be enlarged, in which case the items inside are automatically enlarged. This takes advantage of goocanvas's scaling.
The timeline is now fully reorderable, though the interaction is far from perfect. It's not as smooth as it was in my early prototype, but my early prototype didn't handle items of varying widths. I'm anxious to move on, but I really want to make sure that this code works properly on its own before I throw in the added complexity of MVC.
One issue which I haven't yet decided how to handle is transitions. Should I allow multiple transitions to be moved next to each other on the timeline? What would that mean? I don't think there's a use case for multiple transitions in between two clips. If I'm not to allow multiple transitions, then I have to think of a way to prevent them from stacking against each other, which could get hairy.
Currently I have a SimpleTimeline which derives from Canvas(). This in turn uses a more general HList(), which I had hoped to make as general as possible. However, I think my goal of having a generic, re-orderable list class is not going to work. There is too much application-specific behavior in the timeline. Tomorrow, I'm going copy the list code directly into the SimpleTimeline class, which already implements the re-orderable portion of the list anyways.
Saturday, May 31, 2008
Friday, May 30, 2008
Implementing Reorderable List
pitivi.timeline.composition.Composition provides the following relevant methods:
When the user clicks on an item in the timeline, the source will be moved to the top layer of the canvas (so that it shows above other objects as it is moved. The user can then drag it freely in the x direction within the bounds of the canvas, but it will be completely constrained in the y direction.
If the object is moved beyond a certain threshold to the right or left, the position of the nearest object to the one being moved will be swapped (i.e. the order of the objects will change, but the object being dragged will still be under the control of the mouse). The operation finishes when the user releases the mouse.
Two ways to do this:
My goal for my first commit is to come up with a drop-in replacement for the existing timeline. But, in the interest of being forward thinking, there's a design constraint here I almost forgot to consider: Transition widgets. Handling child widgets of different sizes and aspect ratios will not be so hard, but transitions are only supposed to go between two sources. How can I easily enforce this constraint? Maybe by fiddling with the threshold values, but remember that transitions are optional. I could use a mandatory space between sources, but to be honest I really hate that idea. I'll sleep on it for now. One thing at a time.
getSimpleSourcePosition
addSource
appendSource
moveSource
removeSource
insertSourceAfter
condensed-list-changed
source-added
source-removed
- calls insertSourceAfter() when an user drops item to timeline
- calls removeSource() when user deletes item from timeline
- calls moveSource() when user moves a source to a new position
- responds to the "source_added" signal by creating a new source widget and adding it to the timeline
- responds to the "source_removed" signal by removing its widget from the timeline
- responds to the "condensed_list_changed" signal by updating items to their new position
When the user clicks on an item in the timeline, the source will be moved to the top layer of the canvas (so that it shows above other objects as it is moved. The user can then drag it freely in the x direction within the bounds of the canvas, but it will be completely constrained in the y direction.
If the object is moved beyond a certain threshold to the right or left, the position of the nearest object to the one being moved will be swapped (i.e. the order of the objects will change, but the object being dragged will still be under the control of the mouse). The operation finishes when the user releases the mouse.
Two ways to do this:
- When the threshold value is reached, simply call moveSource() to exchange the positions of both sources. The advantage of this approach is that the UI updates automatically when the composition emits the "condensed-list-changed" signal. One possibly negative side-effect is that the object the user is dragging will suddenly "jump" in to position. Another potential side-effect is that the "condensed-list-changed" signal might be delayed for some reason, leaving the timeline in a sorry state even after the user releases the mouse.
- When the threshold value is reached, only swap the sources visually. Save the proposed changes until after the user releases the mouse. Then call moveSource() to move the source. This avoids the "jumping" side effect, but introduces a different problem. The visual timeline and back end will be temporarily inconsistent. If the "consensed-list-changed" signal is delayed, then the user's changes are incorrectly displayed. We can get around this by automatically restoring the list to its original state after the user releases the mouse. This could also be confusing: the user sees their clips move into a new position, then move back to their original position after releasing the mouse, then move back to the new position after the signal arrives.
My goal for my first commit is to come up with a drop-in replacement for the existing timeline. But, in the interest of being forward thinking, there's a design constraint here I almost forgot to consider: Transition widgets. Handling child widgets of different sizes and aspect ratios will not be so hard, but transitions are only supposed to go between two sources. How can I easily enforce this constraint? Maybe by fiddling with the threshold values, but remember that transitions are optional. I could use a mandatory space between sources, but to be honest I really hate that idea. I'll sleep on it for now. One thing at a time.
Thursday, May 29, 2008
Distro Shopping
I spent the day distro shopping, but since I have not really found what I wanted, I have decided to stop worrying about it for the moment. Ubuntu's support of GStreamer isn't that bad. I have other beefs. On the other hand, the my criticisms of Ubuntu also apply to just about every other distribution out there. It's just that Ubuntu initially set the bar very high, and I have been really disappointed with the last two or three releases. I wait and wait, but the functionality doesn't improve, and even regresses. It's very frustrating. I figure that if I'm going to have to tinker with the OS, that I might as well use something much less restrictive. Something that really gives me what I want.
That having been said, enough of this. I can do a fair amount of PiTiVi development without up-to-date gstreamer installed. I have a job to do, and it's time to start doing it. So, for the next three days, I'm going to start working on things which do not depend on having up-to-date gstreamer libraries.
Switch Simple Timeline To Goocanvas
I've already got a prototype of this working, but there are a couple things that need to happen first.
Once I get gstreamer-cvs installed, I can start working on some other things.
That having been said, enough of this. I can do a fair amount of PiTiVi development without up-to-date gstreamer installed. I have a job to do, and it's time to start doing it. So, for the next three days, I'm going to start working on things which do not depend on having up-to-date gstreamer libraries.
Switch Simple Timeline To Goocanvas
I've already got a prototype of this working, but there are a couple things that need to happen first.
- I have a prototype container class that derives from goocanvas.Group which handles repositioning, adding, and deleting groups of items that I use in gst-editor.py. I want to re-factor this class so that it derives directly from goocanvas.Canvas.
- I have a prototype timeline implemented as a python script. It simulates a re-orderable list of canvas widgets. This code needs to be rewritten slightly so that it is more friendly to MVC. In particular, it needs to wait for signals from the model before anything in the UI is reordered.
- Merge the code from (2) above into (1)
- Test code independently with standard canvas objects of varying sizes
- Merge the external drag-and-drop support in from the existing PiTiVi timeline widget
- Test the code independently of pitivi using existing PiTiVi source widgets
- Merge the new code into PiTiVi
Once I get gstreamer-cvs installed, I can start working on some other things.
- Transitions
- Titling Support
- Still Image Support
Gah! Paperwork
No sooner do I have all my European flights and hotels booked than I realize I hadn't registered for guadec. And now registration is closed...Meanwhile I'm behind on sending in the tax forms to Google. I've moved out of my old cooperative and into this new one that doesn't have a house laser printer. I dug out my old inkjet and spent an hour struggling with CUPS to get it to print only to find that the ink has gone dry. Meanwhile I'm trying to send in the DMV paperwork for my two motorcycles that I'm selling. Combine that with the joys of moving, unpacking, throw in a visit to an ailing mother in a different town, add a spontaneous, free ticket to a rock concert, and you get a Summer of Code student who hasn't been able to write any code for two days =(
Meanwhile, Ubuntu has put the nail in the coffin in the form of an "update" they released today which uninstalled devhelp and prevents my reinstalling it. Seriously, Ubuntu is going downhill. I am done with their silliness. The real question is where to go next. Maybe gentoo, maybe arch, maybe something else.
Meanwhile, Ubuntu has put the nail in the coffin in the form of an "update" they released today which uninstalled devhelp and prevents my reinstalling it. Seriously, Ubuntu is going downhill. I am done with their silliness. The real question is where to go next. Maybe gentoo, maybe arch, maybe something else.
Wow! Comments!
Thanks, those of you who replied to the last posting. I agree, installing gentoo *on* the eeepc would be problematic. It just seems that, since eepc's are mostly the same hardware, that there ought to be an disk image of a functioning install that I could just dd onto my hard drive. Then all I have to worry about is setting up my development environment. Cross compilation isn't really a good idea because it seems like it would leave me without the ability to install software when away from my primary machine.
With regards to the SSD hardware, I have heard that it will take quite a few write cycles before one starts having problems. Unless you know about someone who killed their EeePC by trying to install gentoo, I'm not really worried about anything except running out of disk space. And I
With regards to the SSD hardware, I have heard that it will take quite a few write cycles before one starts having problems. Unless you know about someone who killed their EeePC by trying to install gentoo, I'm not really worried about anything except running out of disk space. And I
Tuesday, May 27, 2008
I promise to stop hacking and get to work
For the last couple of days i've been hacking pretty heavily on my gst-editor, another gstreamer project closely related to pitivi. I've made some serious progress in terems of UI, but there are some wierd bugs that have basically led to an impasse. In any case, it's time for me to start work on PiTiVi in earnest. Working on gst-editor has taught me what I need to know about gstreamer and goocanvas.
There is one main barrier to working on PiTiVi, and that is finding a reliable and efficient way of setting up a gstreamer development environment. Now that Edward has written his QA system for gstreamer, a large number of bugs are being fixed. This has led to rapid changes in gstreamer, which is on a monthly release cycle anyways. It's much too fast to rely on a distribution like Ubuntu to keep pace. I have been tinkering witht he idea of installing Gentoo or Arch linux, especially on my eeePc, which I'll be taking with me to europe. Holding me back is the knowledge that configuration will take a long time. I have grown used to the "it just works" nature of Ubuntu. For the most part, I want other people to make choices for me. There are only specific areas in which I want to override those choices: gstreamer, power management, network management. I don't care who makes the choices, as long as it works. I am suspicious that ubuntu doesn't include a complete gstreamer distribution, but I don't know how to check. Do I contact the package maintainers? Even if I build my own packges, I'm still limited by the dependencies that ubuntu includes. If there's some plugin which uses a library that ubuntu doesn't support, then it doesn't matter if I go to the trouble to build it myself.
Chicken an egg. I really wish I had a local gentoo guru who could get me past the initial setup quickly, so that I could concentrate on my work and not the system configuration. When I was using debian, nothing ever worked right. I can only imagine that gentoo would be similar in terms of leaving me a lot of work to do in order toget a user experience similar to what Ubuntu offers. On the other hand, ubuntu is p*ssing me off as of late: their power management system as of 8.04 is terrible, it's bloated, thunar *never* seems to be able to unmount disks, and 8.04's kernels don't support eeepc hardware out-of-the box. I had to go out of my way to set the machine up in the first place. If have to tinker with ubuntu, maybe I might as well just install a more flexible distribution. Sigh....
There is one main barrier to working on PiTiVi, and that is finding a reliable and efficient way of setting up a gstreamer development environment. Now that Edward has written his QA system for gstreamer, a large number of bugs are being fixed. This has led to rapid changes in gstreamer, which is on a monthly release cycle anyways. It's much too fast to rely on a distribution like Ubuntu to keep pace. I have been tinkering witht he idea of installing Gentoo or Arch linux, especially on my eeePc, which I'll be taking with me to europe. Holding me back is the knowledge that configuration will take a long time. I have grown used to the "it just works" nature of Ubuntu. For the most part, I want other people to make choices for me. There are only specific areas in which I want to override those choices: gstreamer, power management, network management. I don't care who makes the choices, as long as it works. I am suspicious that ubuntu doesn't include a complete gstreamer distribution, but I don't know how to check. Do I contact the package maintainers? Even if I build my own packges, I'm still limited by the dependencies that ubuntu includes. If there's some plugin which uses a library that ubuntu doesn't support, then it doesn't matter if I go to the trouble to build it myself.
Chicken an egg. I really wish I had a local gentoo guru who could get me past the initial setup quickly, so that I could concentrate on my work and not the system configuration. When I was using debian, nothing ever worked right. I can only imagine that gentoo would be similar in terms of leaving me a lot of work to do in order toget a user experience similar to what Ubuntu offers. On the other hand, ubuntu is p*ssing me off as of late: their power management system as of 8.04 is terrible, it's bloated, thunar *never* seems to be able to unmount disks, and 8.04's kernels don't support eeepc hardware out-of-the box. I had to go out of my way to set the machine up in the first place. If have to tinker with ubuntu, maybe I might as well just install a more flexible distribution. Sigh....
Friday, May 23, 2008
eeePc
I got an eeePc for traveling this summer. The following image documents a watershed moment: PiTiVi running on an eeePc. As you can see, there are some screen size issues to work out. But it does work, and I was able to make some editing actions. The eeePc seems to have some trouble playing back the high-res video I took from my friend's cannon powershot. After about 15 seconds, playback becomes jerky. This is in both PiTiVi and Totem. I'll try the same video on my thinkpad to make sure the file isn't corrupt in some way. In any case, I'll have to re-encode the video at a lower resolution / higher compression to save space. Hopefull the playback issues will be taken care of at the same time.
Wednesday, May 21, 2008
Corrections
Turns out a couple of the things I said about goocanvas don't make sense now that I've reread them. Goocanvas provides all kinds of support for dynamically resizing and repositioning individual elements: it'd doesn't provide so much support for notifying other parts of the program about those changes. And it only provides rudimentary support for hierarchical nesting of canvas items.
I don't want spend time writing custom canvas items because it's not necessary for PiTiVi: rectangles and text objects will be fine, or I'll embed some existing GTK+ widgets into the canvas. That having been said, I would like to be able to easily compose primitive objects together to make more complex ones: rectangle + text = labled box! I also want to be able to make container classes similar to GTK+s container classes, which dynamically grow and shrink as objects are added or deleted. I'd also like to be able to have the container's size update if any of the child objects change in size. In order to do that, those container classes need to know whenever one of the child objects moves or changes size.
Basically, you have simple items and you have groups. All objects have transform matrices and bounds, but you get no notification if any of these change. You have to use the gproperty interface if you want notifications of changes. This means you can't use the translation matrix portion of the API, since they won't be in sync. Goocanvas groups have no size or position properties either, so I have chosen to add this to a derived class I call a "smartgroup". The issue is that in order to calculate the size of the smartgroup, I need to know the size and relative position of all the children. And now we come to the crux of the matter: since there is no consistent property interface for size and position, I have to make some derived primitives to support this as well. Honestly, this feels like a design oversight within goocanvas. It seems like the stock items should do this for you.
That having been said, goocanvas is great. It's efficient, and the rendered output looks awesome. It's easy to build up the kind of functionality I want, so most of the above should prove to be relatively minor setbacks.
I don't want spend time writing custom canvas items because it's not necessary for PiTiVi: rectangles and text objects will be fine, or I'll embed some existing GTK+ widgets into the canvas. That having been said, I would like to be able to easily compose primitive objects together to make more complex ones: rectangle + text = labled box! I also want to be able to make container classes similar to GTK+s container classes, which dynamically grow and shrink as objects are added or deleted. I'd also like to be able to have the container's size update if any of the child objects change in size. In order to do that, those container classes need to know whenever one of the child objects moves or changes size.
Basically, you have simple items and you have groups. All objects have transform matrices and bounds, but you get no notification if any of these change. You have to use the gproperty interface if you want notifications of changes. This means you can't use the translation matrix portion of the API, since they won't be in sync. Goocanvas groups have no size or position properties either, so I have chosen to add this to a derived class I call a "smartgroup". The issue is that in order to calculate the size of the smartgroup, I need to know the size and relative position of all the children. And now we come to the crux of the matter: since there is no consistent property interface for size and position, I have to make some derived primitives to support this as well. Honestly, this feels like a design oversight within goocanvas. It seems like the stock items should do this for you.
That having been said, goocanvas is great. It's efficient, and the rendered output looks awesome. It's easy to build up the kind of functionality I want, so most of the above should prove to be relatively minor setbacks.
Turns out I HAVE a blog!
As you can see, I didn't get much use out of this account during the previous year. Well, Here I am again. I've been asked to set up a blog for SoC 2008, and this will do. I'd like to start the summer off with a brief discussion of the challenges that lay ahead for my SoC coding.
Bleeding Edge Gstreamer
The video editor relies on up-to-date gstreamer and gnonlin, sometimes even SVN. Installing these from source is kindof a pain. I tried installing gentoo in a chroot, and using this to build recent gstreamer. This is a great option on my thinkpad, but not so great on my eeePc, which I will be using in europe this summer. So, step one is to get both of my development machines ready to go with bleeding edge gstreamer libraries.
Limitations with Goocanvas
I have been tinkering with goocanvas for a couple of months now. I think it is a very useful library, but there are a couple of issues with it in its current form.
Goocanvas doesn't give a lot of help with interaction. There is a "container" class called Table, but this going to help me implement a re-orderable list for the simple timeline. Aside from the fact that goocanvas is based on gobject, there isn't much support for dynamically resizing and repositioning objects. I need to build up dynamic containers first, and then make the individual container items reorderable.
There is no consistent property interface between the stock canvas items. The majority support x, y, width, and height. But a few do not, namely Text, Circle, Polyline, and Path. Fortunately, I will only be using the Text object, so I think I can safely assume that all the widgets involved support those properties.
Relationship with Advanced Timeline
The simple timeline is both a simplification and an abstraction of the core objects. The advanced timeline maintains a closer mapping between PiTiVi core and the user interface features. This means that many things which can be done in the advanced timeline will not be visible in the simple timeline. So what happens if the user makes a change in the advanced timeline, then switches back to the simple timeline, and makes a change there? Will some data be lost in the translation? Should the simple timeline attempt to keep track of changes to the advanced view and prevent them from being lost?
The two main issues I can see are:
1) in the advaned view, sources may overlap each other
2) in the advanced view, source and effect properties will vary over time
Both of these can't be represented in the simple view. So what happens if you spend an hour carefully tuning volume settings in the advanced view, then switch to the simple view and move the volume slider? Does it amplify the whole curve? Does it flatten the curve? Do we even allow the volume slider to move after changing settings in the advanced view?
Bleeding Edge Gstreamer
The video editor relies on up-to-date gstreamer and gnonlin, sometimes even SVN. Installing these from source is kindof a pain. I tried installing gentoo in a chroot, and using this to build recent gstreamer. This is a great option on my thinkpad, but not so great on my eeePc, which I will be using in europe this summer. So, step one is to get both of my development machines ready to go with bleeding edge gstreamer libraries.
Limitations with Goocanvas
I have been tinkering with goocanvas for a couple of months now. I think it is a very useful library, but there are a couple of issues with it in its current form.
Goocanvas doesn't give a lot of help with interaction. There is a "container" class called Table, but this going to help me implement a re-orderable list for the simple timeline. Aside from the fact that goocanvas is based on gobject, there isn't much support for dynamically resizing and repositioning objects. I need to build up dynamic containers first, and then make the individual container items reorderable.
There is no consistent property interface between the stock canvas items. The majority support x, y, width, and height. But a few do not, namely Text, Circle, Polyline, and Path. Fortunately, I will only be using the Text object, so I think I can safely assume that all the widgets involved support those properties.
Relationship with Advanced Timeline
The simple timeline is both a simplification and an abstraction of the core objects. The advanced timeline maintains a closer mapping between PiTiVi core and the user interface features. This means that many things which can be done in the advanced timeline will not be visible in the simple timeline. So what happens if the user makes a change in the advanced timeline, then switches back to the simple timeline, and makes a change there? Will some data be lost in the translation? Should the simple timeline attempt to keep track of changes to the advanced view and prevent them from being lost?
The two main issues I can see are:
1) in the advaned view, sources may overlap each other
2) in the advanced view, source and effect properties will vary over time
Both of these can't be represented in the simple view. So what happens if you spend an hour carefully tuning volume settings in the advanced view, then switch to the simple view and move the volume slider? Does it amplify the whole curve? Does it flatten the curve? Do we even allow the volume slider to move after changing settings in the advanced view?
Subscribe to:
Posts (Atom)