Wednesday, June 10, 2009

About MediaScripting (Note 1)

The title for this 'blog comes from one of my main research projects, which I call MediaScript. The goals of this project are to explore the ways in which interactive scripting of media applications (and other applications) can improve the user’s experience. Our initial experiences with MediaScripting have been in the context of an interactive Scheme-based scripting environment for The GIMP as well as a prototype (and no-longer-working) environment for InkScape. (Yes, the GIMP comes with a Scheme-based scripting environment called ScriptFu. No, it's not very friendly. MediaScript is much friendlier.)

The GIMP-based environment is implemented using embedded PLT Scheme in a GTK+2 GUI, all glued together with C. (In an earlier post, I mention the problem of passing pointers between Scheme and C. This is where it's happening.)

Those experiences suggest a variety of reasons that a designer (that is, someone using one of these graphical design applications) might want to interactively script:
  • Scripting provides additional precision when such precision is appropriate. For example, one might want to write a script to draw a line from exactly here to exactly there.
  • Scripting makes it easier to repeat similar actions. After doing a sequence of operations, one might want to repeat the operations at a different location, in a different scale, or perhaps even at a different orientation.
  • Scripting makes it easier to explore design alternatives. Given an initial drawing, one can easily write a script to generate a variety of similar alternatives, either by varying the original drawing systematically (e.g., placing each component nearby) or randomly.
  • Scripting unlocks new capabilities. We’ve seen designers familiar with the GIMP get very excited after seeing how easy it is to make a brush that changes while they draw.
  • Scripting can open new perspectives. In the GIMP+MediaScript application, it is possible to represent an image as a function from position to color, which allows one to quickly produce interesting and novel color blends.
So, when I write about MediaScript (which will be just one of the topics for this 'blog), I'm talking about this system. I'll discuss the architecture (or parts thereof), our uses of MediaScript in teaching introductory computer science, and more.

Monday, June 8, 2009

The joy of group work

Today's Chronicle of Higher Education online edition has a short article about student reactions to group work. It begins ...
Speaking before a crowd of more than 500 people here on Saturday afternoon, three undergraduates made a plea to the world’s college instructors: no more group assignments—at least not until you figure out how to fairly grade each student’s individual contributions. [http://chronicle.com/daily/2009/06/19509n.htm]
Since I assign a lot of group work in my courses, I think a lot about group work. I also have some stories I tell my students.

But these students' concern is one that I hear a lot, and I think it reveals something important that we need to teach our students: Once you leave college (or high school, or whatever educational level you're at), you will regularly end up working in groups. And, whether you like it or not, you are often judged less on your contributions to the group than to the group's overall success. So, even if you're stuck with people who don't pull their weight (or, as problematically, people who think they need to do everything in the project, and won't let anyone else contribute), you still need to find a way to make your project succeed. College should therefore be a time you use to develop the skills to deal with these and other issues of group work.

I also tell my students that even though I am in a relatively individualistic profession, I still end up working on a lot of group projects. It's an important lesson for them to learn. Of course, I also admit to them that my wife hated group work and tell them a few stories about my own educational experiences with group work.
In junior high, I was in a class (some social studies class, if I remember correctly) in which the instructor gave us a choice of working together as a class or by ourselves. I was the only person who chose to work by himself. And it was clearly the right decision, since I scored better than the class.
Of course, that's not the form of group work we talk about these days, so I also give an example that is closer to home.
Toward the end of my undergraduate career (1985 or so), I took a course in artificial intelligence. That course had a large project component. (Our project had many issues, I may write about them another time.) At the end of the project, it seemed that one person had done about 90% of the work, another had done about 10% of the work, and the third had made the cover page for our report.
No, I wasn't the one who did the cover page. I also wasn't the one who did 90% of the work. Do I think I should have done more? Yes, but the person who did 90% of the work didn't seem to mind (or at least my memory is cloudy enough that I don't think he minded). I helped on the important parts and made good contributions to the project. And I learned an important lesson that's carried my through professional projects: If you're working with the right people and you trust each other, things balance out.

These days, I end up on lots of committees with lots of projects. On some projects, I do more than what is officially my share. On others, I don't always have the time (or inclination) to do everything I should. I don't get extra credit when I do extra work and I don't get penalized when I do less than I should. The important thing is that these committees are successful at accomplishing a wide variety of tasks. It seems to work itself out naturally that people pick up the slack when they can. Maybe I'm just lucky to work with good people. Maybe we all learned some group work skills over the years. Whatever the reason, it's clear to me that these groups do succeed, and they succeed, in part, because we all care about the success of the group rather than our "individual grade".

Monday, June 1, 2009

Can I dereference this pointer?

As part of the core MediaScript project, we end up revealing some pointers from behind the scenes C code to the client programmer, who is programming in Scheme. For example, we may give the client a pointer to a GtkTextBuffer, so that she can write things like
(gtk-text-buffer-append LOG-BUFFER "Hello")
Within Scheme, the pointers get treated as integers.

One problem with this approach is that the client programmer can type in any integer and we need to figure out whether or not it's a reasonable integer. (Yeah, that's a good excuse for doing some sensible wrapping, but, hey, I"m lazy.) For example, the client might write
(gtk-text-buffer-append 23 "Hello")
So, we need a way (in C) to check whether this integer value can reasonably be interpreted as a pointer to a particular type of datum. The second half of the predicate isn't bad, because GObjects typically provide reasonable predicates, such as GTK_IS_TEXT_BUFFER. Unfortunately, these only work correctly if they are given valid pointers (that is, things that can be safely dereferenced).

So, I was asking myself How do I determine if a pointer can be safely dereferenced? As far as I can tell, there are a few basic options:
  • Write your own memory management system, and use the information from that system to determine whether something you've allocated is still allocated.
  • Determine the layout of memory, and check whether the value falls in the heap or on the stack. There are some tips for doing this somewhere on the Web, but they generally require that you run code at the start of a program.
  • Try dereferencing the pointer, and set up a SIGSEG handler.
As you can guess, I went for the third option. Of course, it's supposed to be dangerous to restart after a SIGSEG, but, hey, this seems to be a pretty safe one. The best part was finding a way to return false (0) after the SIGSEG, but that's what gotos are for.

So, here's what I've come up with.

/**
* pointer-hack.c
* A hack that we use to determine whether a pointer can be safely
* dereferenced.
*
* Background: At times, we have something that *appears* to be a pointer,
* but which may not be a pointer. Most typically, this happens when
* we've converted a pointer to an integer for sending to a language
* module (e.g., Scheme), and the language can potentially pass back
* something else. If we have a valid pointer, in many cases, we can
* use the GObject type predicates to check that it's the right type.
* However, those predicates will cause a segfault if the pointer cannot
* be dereferenced. This module provides one procedure,
* gpointer_can_deref (gpointer p),
* that checks whether we can safely derefence the pointer.
*
* Copyright (c) 2008-2009 Samuel A. Rebelsky
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

// +-------+----------------------------------------------------------
// | Notes |
// +-------+


/*
There are a few possible strategies that one can use to determine whether
a pointer can be safely dereferenced. One is to figure out the structure
of memory - anything on the stack or the heap can be derefenced.

This code takes a more straightforward, but potentially dangerous, approach:
It sets up a signal handler for a segmentation fault, tries to dereference the
pointer, and, if it gets a segmentation fault, reports that the pointer cannot
be dereferenced.

Unfortunately, the signal handling standard suggests that it can be dangerous
to continue executing after a segmentation fault. Since we've tried to limit
the effects of the segfault, things *should* be safe.

Note that we recover from the segmentation fault by using setjmp/longjmp. That
is, prior to the attempt to dereference, we set a goto point with setjmp. The
segfault signal handler then does a longjmp back to that point (otherwise, we
seem to get into a loop of segfaults).
*/

// +---------+--------------------------------------------------------
// | Headers |
// +---------+

#include <signal.h>
#include <setjmp.h>

#include <gtk/gtk.h>


// +---------+--------------------------------------------------------
// | Globals |
// +---------+

/**
* A stored location for setjmp/longjmp.
*/
static jmp_buf jmploc;

/**
* A pointer, converted to an integer. (Exists mostly so that
* the optimizer won't attempt to elide the dereference.)
*/
int dereferenced;


// +-----------------+------------------------------------------------
// | Local Functions |
// +-----------------+

/**
* A signal handler for a segmentation fault.
*/
static void
temp_segv_handler (int i)
{
longjmp (jmploc, i);
} // temp_segv_handler


// +--------------------+---------------------------------------------
// | Exported Functions |
// +--------------------+

/**
* Determine if it is safe to dereference a pointer (that is,
* it doesn't throw a SIGSEGV when we dereference it).
*/
gboolean
gpointer_can_deref (gpointer ptr)
{
// Assume we can dereference the pointer
gboolean ok = TRUE;
// Temporary replace the segfault handler.
gpointer segv_handler = signal (SIGSEGV, temp_segv_handler);
// Prepare for error handling
if (! setjmp (jmploc))
{
// Attempt to dereference the pointer.
dereferenced = *((int *) ptr);
}
else
{
// Whoops! We go here through the longjmp in the segv handler.
// That means the dereference failed.
ok = FALSE;
}
// Restore the segfault handler
signal (SIGSEGV, segv_handler);
// And we're done
return ok;
} // gpointer_can_deref
Beautiful, isn't it? Well, I like it.

The Web is Us/ing Us

So, I'm signed up for the summer 2009 POSSE (Professors Open Source Summer Experience, I think). I'm looking forward to a focused week of working on open-source stuff. (More on those plans later.)

In preparation for POSSE, we're supposed to read and view a variety of things, many of which I've at least looked at before. One new thing to me is The Web is Us/ing Us, a short (5 minute) video about Web 2.0.

I'm trying to decide what I think about it (and why we were asked to watch it). Parts of it are stunning: I love the presentation style in which the author types and erases text to make a point. I like the general point that structural markup buys (and has bought us) a lot.

But I worry that some of it is shallow. Yeah, XML gives us separation of structural markup and formatting, but so did SGML, which predates HTML. Certainly, many of the "it's friendly for novices" stuff, such as 'blog authoring (and probably even 'blog aggregating) could have been done without XML. Wikis, for example, predate XML. And, as importantly, it's not XML that gives us all of those wonderful features, it's the document types that are built on top of XML. (We needed an RSS feed DTD before we could get many of the suggested features.) I worry that those kinds of things are lost in the hype.

Still, a spectacular presentation of what people can mean when they say Web 2.0.

Friday, March 20, 2009

Welcome to the Media Scripting 'blog

This 'blog will be the repository of computing-related ramblings by Samuel A. Rebelsky. Many of the posts will be related to my primary project, Media Scripting (interactive scripting of media applications and other aplications). Others will be about other topics in computer science, programming, or teaching of computer science.

A Hack: Web-based Texting to AT&T Phones

So, Michelle and I bought iPhones yesterday. While we're having fun with them, we did notice a problem: Our old phones were on Sprint, and Sprint provides a Web-based interface for sending text messages. AT&T seems to want you to log in to their system to send text messages. Since Michelle's work needs to text her regularly, that didn't seem to be a good solution.

Fortunately, AT&T does provide email-based texting (1234567890@txt.att.net). So, I taught myself some PHP, built a small Web interface to the PHP email function, and, voila, her work can now text to her. All in under an hour of time.

The script is appended. The HTML-based UI should be obvious. Comments are appreciated.
<?php
$phone = $_GET['phone'];
if (!$phone)
{
echo 'No phone number specified.';
exit(1);
}
$to = "$phone@txt.att.net";

$subject = $_GET['subject'];
$body = $_GET['body'];

if (!$body)
{
echo 'No body specified.';
exit (1);
}

$headers = "From: $to";

$mail_sent = @mail( $to, $subject, $body, $headers );
echo $mail_sent ? "Message sent" : "Message failed";
?>