SecreTwit: Social Steganography

SecreTwit Logo

Here is another project I would like to share. As before, this is a project for faculty course Security in computer networks.

I read several good articles about steganography and got an idea to use tweets on Twitter to hide secret messages. Also, this was a great opportunity to do a little UI design in Swing after long time :) Continue reading

cljMovieIndexer: Revolución’s baby brother

As a task for exam I had to make something in Clojure. My idea was to do something similar to Revolución, just much simpler.

Clojure is a modern variant of Lisp that runs on the Java Virtual Machine. It’s designed for concurrent programming, has Lisp-like syntax, it’s built for Java Platform and it’s a functional language so it’s completely different style from Java, C#, C++ and similar languages. For me it wasn’t easy to switch to this style and logic, but once you are there it’s pretty much easy and fun :) Documentation could be more detailed. But there are few blogs/forums where you can find examples (now there is one more ;)).

The Idea

(… or how it works)

cljMovieIndexer runs from console. You specify the directory where your movies are, and it scans the directory and extracts movie names from sub-directory names. It will ignore unnecessary words like resolution, scene names, dots, release types etc. Using the extracted movie names cljMovieIndexer downloads movie info (stuff like release year, plot, actors, cover image) from TMDb and creates a movie description file (web archive format) which is saved in each movie directory. Continue reading

Revolución is here !

Introduction

Revolución Movie Library is a database software for organizing personal collection of movies. Simple and very easy to use with many advanced features, with accent on rich user interface.
The goal was and still is to make software that is simple and easy to use, that makes user feel good and that it does what it is supposed to be doing.

This is the first publicly available version. It’s a beta release of version 0.7 and it’s intended for testing purposes. I encourage you to download and try it. You can use this beta version for 30 days. Please feel free to leave a comment here or write me an email of what you think about it – what should be improved, what isn’t working as expected, is there some new feature that you would like to see in Revolución Movie Library etc. Any comments and suggestions would be greatly appreciated.

Features

  • Simple and easy to use
  • Get movie info and movie covers from online movie databases and link to the HD trailer from few movie trailer sites
  • Add movie in three steps
  • Easy catalogize all movies stored on your hard drive
  • Browse movies in three views (list view, table view and cover show)
  • Fast searching
  • Advanced filtering
  • Search and view movie trailers from Youtube
  • Capture frames from movies (so you can quickly remind without playing the movie)
  • Easily export to HTML, PDF, Excel or XML format or upload to Google Docs
  • View movie news like most popular upcoming movies and weekend box office
  • Automatically translate movie info to language you choose
  • Backup and restore database
  • … and many more :)

System requirements

  • Windows XP or Vista (May work on other Windows editions)
  • Java JRE 1.6 update 10 or newer (I suggest Java 1.6 update 14)
  • Good graphics card
  • At least 512MB RAM
  • Internet

Download

Revolución Movie Library 0.7 Beta
~ 17MB
download-icon

How It’s Made: Cover Gallery

Cover gallery or List View in Revolucion Library is a JList which dispays cover images. You can see it at the beginning of the Revolucion Library screencast.

First of all, we need to extend JList to achieve a selection change animation. In Revolucion Library I used TimingFramework, but here is the example of how to do the same with a great Trident animation library by Kirill.

ListSelectionListener is used to listen for changes in lists selection value, so we can start the animation when a cover is selected.
selectionBounds represent the current bounds of a selection rectangle, and selectionAlpha is used to control the visibility of the selection rectangle – when there is no items in the list, value is 0.0f.
timeline is the main timeline for animations. animationSpeed is actually a duration of the animation in milliseconds.

public class AnimatedList extends JList implements ListSelectionListener, ComponentListener {

	private float selectionAlpha = 0.0f;
	private float newSelectionAlpha = 1.0f;

	private Rectangle selectionBounds = new Rectangle(0, 0, 0, 0);
	private Rectangle currentSelectionBounds = new Rectangle(0, 0, 0, 0);
	private Rectangle newSelectionBounds = new Rectangle(0, 0, 0, 0);

	private Timeline timeline;
	private int animationSpeed = 400;

	private int selectionBorderWidth = 1;
	private int selectionBorderRoundness = 10;
	private Color selectionBorderColor = Color.gray;

	public AnimatedList() {
		setSelectionBackground(new Color(255, 255, 255, 60));
		setSelectionForeground(Color.black);
		setOpaque(false);
		setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		setLayoutOrientation(JList.HORIZONTAL_WRAP);
		setVisibleRowCount(-1);

		addListSelectionListener(this);
		addComponentListener(this);

		initAnimation();
	}

Next we need to setup the Timeline …
Every time timeline.play() is called, selectionBounds will change from currentSelectionBounds to newSelectionBounds, and selectionAlpha from it’s current value to a newSelectionAlpha value. And we add Repaint callback so JList is repainted when these properties change.


private void initAnimation() {
 	timeline = new Timeline(this);
 	timeline.setDuration(animationSpeed);
 	timeline.addPropertyToInterpolate("selectionBounds", currentSelectionBounds, newSelectionBounds);
 	timeline.addPropertyToInterpolateTo("selectionAlpha", newSelectionAlpha);
 	timeline.setEase(new Spline(0.8f));
 	timeline.addCallback(new Repaint(this));
 	timeline.addCallback(new TimelineCallbackAdapter() {
 		@Override
 		public void onTimelineStateChanged(TimelineState oldState, TimelineState newState, float durationFraction, float timelinePosition) {
 			if (newState.equals(TimelineState.DONE))
 				currentSelectionBounds.setBounds(newSelectionBounds);
 		}
 	});
 }

Then we implement ListSelectionListener and ComponentListener.


 @Override
 public void valueChanged(ListSelectionEvent e) {
 	if (!e.getValueIsAdjusting())
 		updateSelectionBounds();
 }

 @Override
 public void componentHidden(ComponentEvent e) {}

 @Override
 public void componentMoved(ComponentEvent e) {
 	updateSelectionBounds();
 }

 @Override
 public void componentResized(ComponentEvent e) {
 	updateSelectionBounds();
 }

 @Override
 public void componentShown(ComponentEvent e) {
 	updateSelectionBounds();
 }

And here is what updateSelectionBounds() method does:


 public void updateSelectionBounds() {
 	int index = getSelectedIndex();
 	// If there is something selected we set the selection bounds to the bounds of the selected cell ...
 	if (index > -1) {
 		newSelectionBounds.setBounds(getCellBounds(index, index));
 		newSelectionAlpha = 1.0f;
 	}
 	// ... or if there is no selection, we do this to simulate rectangle dissapearing ...
 	else {
 		newSelectionBounds.setBounds(getX() + getWidth() / 2, getY() + getHeight() / 2, 0, 0);
 		newSelectionAlpha = 0.0f;
 	}

 	// ... and than start the animation
 	if (!timeline.isDone())
 		timeline.cancel();
 	timeline.play();
 }

And finally, override the paintComponent() to do the selection rectangle painting.


@Override
 protected void paintComponent(Graphics g) {
 	super.paintComponent(g);

 	Graphics2D g2 = (Graphics2D) g.create();
 	g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, selectionAlpha));
 	g2.setColor(getSelectionBackground());
 	g2.fillRoundRect(selectionBounds.x, selectionBounds.y, selectionBounds.width, selectionBounds.height, selectionBorderRoundness, selectionBorderRoundness);
 	g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
 	g2.setColor(selectionBorderColor);
 	g2.setStroke(new BasicStroke(selectionBorderWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
 	g2.drawRoundRect(selectionBounds.x, selectionBounds.y, selectionBounds.width, selectionBounds.height, selectionBorderRoundness, selectionBorderRoundness);
 	g2.dispose();
 }

Add getters and setters for selectionBounds and selectionAlpha, and that’s it with animations.

To speed up image painting in the JList, I wrote a ListCellRenderer that will cache cover images.


public class CoverListCellRendererTest extends DefaultListCellRenderer {

 // http://java.sun.com/javase/6/docs/api/java/lang/ref/SoftReference.html
 private HashMap<String, SoftReference<ImageIcon>> thumbnails;

 public CoverListCellRendererTest() {
 	thumbnails = new HashMap<String, SoftReference<ImageIcon>>();

 	setOpaque(false);
 	setHorizontalAlignment(JLabel.CENTER);
 	setHorizontalTextPosition(JLabel.CENTER);
 	setVerticalTextPosition(JLabel.BOTTOM);
 }

 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
 	Movie movie = (Movie) value;

 	setText(movie.getTitle());

 	String coverFileName = movie.getCover();
 	if (coverFileName != null)
 		setIcon(getThumbnail(coverFileName));

 	return this;
 }

 private ImageIcon getThumbnail(String coverFileName) {
 	ImageIcon icon = null;

 	SoftReference<ImageIcon> reference = thumbnails.get(coverFileName);
 	if (reference != null)
 		icon = reference.get();

 	if (icon == null) {
 		try {
 			BufferedImage image = ImageUtils.getCoverThumb(coverFileName);
 			icon = new ImageIcon(image);
 			thumbnails.put(coverFileName, new SoftReference<ImageIcon>(icon));
 		}
 		catch (IOException e) {
 			icon = new ImageIcon(ImageUtils.getEmptyCover());
 		}
 	}

 	return icon;
 }
}

How It’s Made: Youtube player in Java

Few of you asked, so here is how …

First of all, you need a way to search Youtube and get url of some video. And that is really simple since there is an official Google Data API for using some of the services Google offers, and there is an open source GData Java Client Library, and great tutorials and examples of how to use it.

So, for example, from a query for ‘Revolucion Movie Library’ you will get a List of VideoEntries. And from VideoEntry you can get stuff like video title, location, type, url, duration, thumbnails etc. Video location is a string like “http://www.youtube.com/v/9yi9EdbYaFc&…&#8221;. Remember that :)

Now we need to play that somehow …

If you have a right codec, youtube video can be played in probably any video player – try opening above url (that you remembered :)) in Windows Media Player. But there are problems, at least I had them. First, that seems now is gone (probably fixed in newer versions of WMP or Flash), you couldn’t interact with a video, so you couldn’t click ‘Play’. That can be resolved by appending “&autoplay=1″ to url, but than you can’t stop it. And, there comes a second problem – you can’t even really stop it with “Stop” button in your player. I first written a wrapper around WMP so I can use it in Swing, but that did’t work quite well. Also I tried JMC, but it crashed from time to time.

Other solution is playing Youtube videos in web browser. And this way you can even use a chromeless player (“… by definition, a YouTube video with no controls”), and control it using JavaScript. And if we had JWebPane this would be excellent. But since it isn’t finished yet … there are alternatives: WebBrowser from JDIC project, WebBrowser from JDICplus, …, and JWebBrowser from the DJ project. In Revolucion Library I used latter. It’s an SWT-based implementation of web browser component and under Windows it uses Internet Explorer or Mozilla and Mozilla on other platforms. Features that I liked – you can call JavaScript function in current page from Java, and can send commands from html page to Java application. And it works pretty good.

So I made a simple html page with chromeless Youtube player and, among few others, it contains following JavaScript functions:


function onYouTubePlayerReady(playerId) {
          ytplayer = document.getElementById("myytplayer");
  ...
          sendCommand("loaded");
        }

function loadNewVideo(id, startSeconds) {
          if (ytplayer) {
            ytplayer.loadVideoById(id, parseInt(startSeconds));
          }
        }

function closePlayer() {
            stop();
            clearVideo();
          	sendCommand('close');
        }
function sendCommand(command) {
          var s = 'command://' + encodeURIComponent(command);
          for(var i=1; i<arguments.length; s+='&'+encodeURIComponent(arguments[i++]));
          window.location = s;
        }

Also I written a YouTube player component:


 public class YouTubePlayer extends JPanel {

 private JWebBrowser webBrowser;
 private String videoId;

 public YouTubePlayer(String videoId) {
 	this.videoId = videoId;

 	init();
 }

 private void init() {
 	webBrowser = new JWebBrowser();
 	webBrowser.setBarsVisible(false);
 	webBrowser.setButtonBarVisible(false);
 	webBrowser.setLocationBarVisible(false);
 	webBrowser.setMenuBarVisible(false);
 	webBrowser.setStatusBarVisible(false);
 	webBrowser.setBackground(Color.black);
 	webBrowser.getNativeComponent().setBackground(Color.black);
 	webBrowser.setFocusable(false);

 	webBrowser.setHTMLContent(generateHtmlPlayer());

 	webBrowser.addWebBrowserListener(new WebBrowserAdapter() {
 		@Override
 		public void commandReceived(WebBrowserEvent e, String command, String[] args) {
 			if (command.equals("close"))
 				firePropertyChange("action", null, "close");
 			else if (command.equals("loaded"))
 				webBrowser.executeJavascript("loadNewVideo(\"" + videoId + "\", \"0\")");
 		}
 	});

 	setBackground(Color.black);
 	setLayout(new BorderLayout());

 	add(webBrowser, BorderLayout.CENTER);
 }

 private String generateHtmlPlayer() {
 	String html = null;
 	try {
 		html = FileUtils.readFileToString(new File(getClass().getResource("resources/player_html.html").toURI()));
 	}
 	catch (Exception e) {}

 	return html;
 }
}

Explanation:

When the “player_html.html” page is opened in the browser and then Youtube player is loaded it will invoke the onYouTubePlayerReady function and it will send command to my YouTubePlayer component. WebBrowserListener receives the command and using the executeJavascript method calls the loadNewVideo function with videoId as a parameter. VideoId is a part of video url after “/v/” that you might remember from above :) When user clicks “close” button in the html page, closePlayer() function is called and command sent to application.

So, this is it. All in all, this is not the best solution, you must include SWT jar with your application, but it works for now.

I’m desperately waiting for JWebPane …

Added day later:

I forgot to mention WebKit4Java by Genuitec which is currently available for SWT, but there is also going to be a Swing version.

P.S. My english isn’t excellent so I’m sorry for grammatical and other mistakes I made.

Begin the Revolución …

Two years ago I started writing a program that will allow me to catalog my movies. I called it Revolucion Movie Library.

There are many programs out there that can do this, but non of them suited me. Some are too complicated, have many useless features and make simple things hard to do. And most of them are … ugly.

In meantime I changed it many times, optimized, polished the interface, added few interesting features that friends requested and improved it and improved it again. And, of course, fixed bugs I created. The goal was and still is to make software that is simple and easy to use, that makes user feel good and that it does what it is supposed to be doing.

Revolucion Library - Main view

So, it’s not completely finished yet, but here are some of the current features and screenshots.

Features:

  • Simple and easy to use
  • Get movie info and movie covers from online movie databases
  • Add movie in three steps
  • Easy catalogize all movies stored on your hard drive
  • Browse movies in three views (list view, table view and cover show)
  • Fast searching
  • Advanced filtering
  • Search and view movie trailers from Youtube
  • Capture frames from movies (so you can quickly remind without playing the movie)
  • Easily export to HTML, PDF or Excel format
  • View movie news like most popular upcoming movies and weekend box office
  • Automatically translate movie info to language you choose
  • Backup and restore database
  • … and other that I currently can’t remember …

Demonstration video:

Watch in HD: http://www.vimeo.com/3373420 (use full screen option).

Screenshots:

Revolucion Library - Main View Revolucion Library - Cover Show
Revolucion Library - List View Revolucion Library - Table View - Details
Revolucion Library - Trailer View Revolucion Library - Edit movie

The Revolucion Library is still in development, but the first beta version will probably be available in next few weeks.

For all developers out there, Revolucion Library is written completely in Java with custom Swing components and few open source libraries, backed by Hibernate and HSQL database. For details, ask.

Please do tell me what you think about all this. Do you like it or not, and why ? What features do you think this type of software needs to have ? Any comments and suggestions would be greatly appreciated.