blob: 382090b19dee9c38e597be3d63431cef446dfb3b [file] [log] [blame]
/*
* Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All rights reserved.
*
*/
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include "imxplayer.h"
#include "playlistbox.h"
static void playlist_set_file(ImxPlayer *player, gchar *filename)
{
gchar title[256];
player->playengine->stop(player->playengine);
player->playengine->set_file(player->playengine, filename);
gchar *file = strrchr(filename, '/');
if (file)
file++;
else
file = filename;
sprintf(title, "%s - %s", "IMXPlayer", file);
gtk_window_set_title(GTK_WINDOW(player->top_window), title);
player->playengine->play(player->playengine);
gtk_range_set_value(GTK_RANGE(player->ctrlbar.progress), 0);
gtk_label_set_text(GTK_LABEL(player->ctrlbar.current), "00:00");
gtk_label_set_text(GTK_LABEL(player->ctrlbar.duration), "00:00");
GtkWidget *image = gtk_image_new_from_file("./icons/pause.png");
gtk_button_set_image(GTK_BUTTON(player->ctrlbar.play_pause), image);
#ifdef ENABLE_STOP_BUTTON
image = gtk_image_new_from_file("./icons/stop.png");
gtk_button_set_image(GTK_BUTTON(player->ctrlbar.play_stop), image);
#endif
// player->metainfo_refresh = TRUE;
}
static void playlist_set_repeat(PlaylistBox *playlistbox, RepeatMode repeat)
{
if (repeat < REPEAT_MAX)
playlistbox->repeat = repeat;
else
playlistbox->repeat = REPEAT_OFF;
}
static RepeatMode playlist_get_repeat(PlaylistBox *playlistbox)
{
return playlistbox->repeat;
}
static void playlist_next_previous(PlaylistBox *playlistbox, gboolean next)
{
gboolean no_more = FALSE;
GtkTreeModel *model;
GtkTreeIter iter;
GtkWidget *image;
gchar *name;
gchar *folder;
gchar pathname[256];
gint num;
ImxPlayer *player = (ImxPlayer *)playlistbox->player;
if (playlistbox->count) {
if (playlistbox->repeat == REPEAT_ONE) {
// playlistbox->current no change
} else if (playlistbox->repeat == REPEAT_RANDOM) {
playlistbox->current = (random() % playlistbox->count) + 1;
} else {
if (next) {
playlistbox->current++;
if (playlistbox->current > playlistbox->count) {
if (playlistbox->repeat == REPEAT_ALL) {
playlistbox->current = 1;
} else {
playlistbox->current = playlistbox->count;
no_more = TRUE;
}
}
} else {
playlistbox->current--;
if (playlistbox->current <= 0) {
if (playlistbox->repeat == REPEAT_ALL) {
playlistbox->current = playlistbox->count;
} else {
playlistbox->current = 1;
no_more = TRUE;
}
}
}
}
if (no_more) {
//stop the playing
player->playengine->stop(player->playengine);
g_print("No more %s file, stopped\n", next ? "next": "previous");
#ifdef ENABLE_STOP_BUTTON
image = gtk_image_new_from_file("./icons/play.png");
gtk_button_set_image(GTK_BUTTON(player->ctrlbar.play_stop), image);
#endif
image = gtk_image_new_from_file("./icons/play.png");
gtk_button_set_image(GTK_BUTTON(player->ctrlbar.play_pause), image);
} else {
model = gtk_tree_view_get_model (GTK_TREE_VIEW (playlistbox->list));
gtk_tree_model_iter_nth_child(model, &iter, NULL, playlistbox->current-1);
gtk_tree_model_get(model, &iter, NUMBER, &num,
FILE_NAME, &name, FOLDER_PATH, &folder, -1);
sprintf(pathname, "%s/%s", folder, name);
g_print ("select and start play [%d]%s\n", num, pathname);
if (num == playlistbox->current) {
playlist_set_file(playlistbox->player, pathname);
} else {
g_print("Retrieve %s failed, index not match [%d:%d]\n",
next ? "next": "previous", num, playlistbox->current);
}
g_free(name);
g_free(folder);
}
} else {
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(player->top_window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_WARNING,
GTK_BUTTONS_OK,
"Playlist is empty");
gtk_window_set_title(GTK_WINDOW(dialog), "Warning");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
}
static void playlist_set_next(PlaylistBox *playlistbox)
{
playlist_next_previous(playlistbox, TRUE);
}
static void playlist_set_previous(PlaylistBox *playlistbox)
{
playlist_next_previous(playlistbox, FALSE);
}
static void playlist_add_file(PlaylistBox *playlistbox, gchar *file,
gboolean clear, gboolean play)
{
GtkListStore *store;
GtkTreeIter iter;
GtkTreeModel *model;
gchar pathname[256];
model = gtk_tree_view_get_model (GTK_TREE_VIEW (playlistbox->list));
store = GTK_LIST_STORE(model);
if (clear) {
playlistbox->count = 0;
playlistbox->current = 0;
if (gtk_tree_model_get_iter_first(model, &iter))
gtk_list_store_clear(store);
}
gtk_list_store_append(store, &iter);
strncpy(pathname, file, 255);
pathname[255] = 0;
playlistbox->count++;
gchar *filename = strrchr(pathname, '/');
if (!filename) {
filename = file;
gtk_list_store_set(store, &iter,
NUMBER, playlistbox->count,
FILE_NAME, filename,
FOLDER_PATH, "",
-1);
} else {
*filename = '\0';
filename++;
gtk_list_store_set(store, &iter,
NUMBER, playlistbox->count,
FILE_NAME, filename,
FOLDER_PATH, pathname,
-1);
}
if (play) {
playlist_set_file(playlistbox->player, file);
playlistbox->current = playlistbox->count;
}
}
static void playlist_add_folder(PlaylistBox *playlistbox, gchar *folder,
gboolean clear, gboolean play)
{
DIR *dir;
struct dirent *ent;
struct stat st;
GtkListStore *store;
GtkTreeModel *model;
GtkTreeIter iter;
gchar filename[256];
gboolean start_play = play;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (playlistbox->list));
store = GTK_LIST_STORE(model);
//gint n_rows = gtk_tree_model_iter_n_children(store, NULL) + 1;
if (clear) {
playlistbox->count = 0;
playlistbox->current = 0;
if (gtk_tree_model_get_iter_first(model, &iter))
gtk_list_store_clear(store);
}
gchar *folder_path = strchr(folder, ':');
if (!folder_path)
folder_path = folder;
else
folder_path++;
dir = opendir (folder_path);
if (dir) {
ent = readdir(dir);
while (ent) {
sprintf(filename, "%s/%s", folder_path, ent->d_name);
if (stat(filename, &st) == 0) {
if (S_ISREG(st.st_mode)) {
/*
// get the mime type
gboolean certain = FALSE;
char *content_type = g_content_type_guess (filename, NULL, 0, &certain);
if (content_type != NULL) {
char *mime_type = g_content_type_get_mime_type (content_type);
}
*/
playlistbox->count++;
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
NUMBER, playlistbox->count,
FILE_NAME, ent->d_name,
FOLDER_PATH, folder_path,
-1);
if (start_play) {
playlist_set_file(playlistbox->player, filename);
playlistbox->current = playlistbox->count;
start_play = FALSE;
}
}
}
ent = readdir(dir);
}
closedir(dir);
} else {
g_print("Open %s failed\n", folder_path);
}
}
static void add_item(GtkWidget *widget, gpointer data)
{
ImxPlayer *player = (ImxPlayer *)data;
GtkWidget *dialog = gtk_file_chooser_dialog_new ("Open File",
GTK_WINDOW(player->top_window),
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL,
GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN,
GTK_RESPONSE_ACCEPT,
NULL);
GtkFileFilter *filter = gtk_file_filter_new ();
gtk_file_filter_add_mime_type (filter, "video/*");
gtk_file_filter_add_mime_type (filter, "audio/*");
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog);
gchar *str = gtk_file_chooser_get_filename (chooser);
playlist_add_file(&player->playlistbox, str, FALSE, FALSE);
g_free (str);
}
gtk_widget_destroy (dialog);
}
static void add_dir_item(GtkWidget *widget, gpointer data)
{
ImxPlayer *player = (ImxPlayer *)data;
GtkWidget *dialog = gtk_file_chooser_dialog_new ("Open Folder",
GTK_WINDOW(player->top_window),
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
GTK_STOCK_CANCEL,
GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN,
GTK_RESPONSE_ACCEPT,
NULL);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog);
gchar *str = gtk_file_chooser_get_uri (chooser);
playlist_add_folder(&player->playlistbox, str, FALSE, FALSE);
g_free (str);
}
gtk_widget_destroy (dialog);
}
static void remove_item(GtkWidget *widget, gpointer data)
{
GtkListStore *store;
GtkTreeModel *model;
GtkTreeIter iter;
GtkTreeSelection *selection;
gint n_rows;
ImxPlayer *player = (ImxPlayer *)data;
selection = gtk_tree_view_get_selection(
GTK_TREE_VIEW(player->playlistbox.list));
store = GTK_LIST_STORE(gtk_tree_view_get_model(
GTK_TREE_VIEW (player->playlistbox.list)));
model = gtk_tree_view_get_model (GTK_TREE_VIEW (player->playlistbox.list));
if (gtk_tree_model_get_iter_first(model, &iter) == FALSE)
return;
if (gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection),
&model, &iter)) {
//update row number
GtkTreeIter new_iter = iter;
gtk_tree_model_get (model, &new_iter, NUMBER, &n_rows, -1);
while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &new_iter)) {
gtk_list_store_set(store, &new_iter, NUMBER, n_rows++, -1);
}
gtk_list_store_remove(store, &iter);
player->playlistbox.count--;
}
}
static void remove_all(GtkWidget *widget, gpointer data)
{
GtkListStore *store;
GtkTreeModel *model;
GtkTreeIter iter;
ImxPlayer *player = (ImxPlayer *)data;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (player->playlistbox.list));
store = GTK_LIST_STORE(model);
player->playlistbox.count = 0;
player->playlistbox.current = 0;
if (gtk_tree_model_get_iter_first(model, &iter) == FALSE)
return;
gtk_list_store_clear(store);
}
static void close_list(GtkWidget *widget, gpointer data)
{
ImxPlayer *player = (ImxPlayer *)data;
gtk_widget_hide(player->playlistbox.playlist_box);
player->show_playlist = FALSE;
if (player->video_w_pre > 0) {
player->video_w = player->video_w_pre;
player->video_w_pre = 0;
player->playengine->set_render_rect(player->playengine, 0, 0,
player->video_w, player->video_h);
player->playengine->expose_video(player->playengine);
subtitle_resize(player->fixed_ct, &player->subtitle, player->video_x,
player->video_y, player->video_w, player->video_h);
}
}
static void item_activate(GtkTreeView *treeview, GtkTreePath *path,
GtkTreeViewColumn *col, gpointer data)
{
GtkTreeIter iter;
GtkTreeModel *model = gtk_tree_view_get_model(treeview);
if (gtk_tree_model_get_iter(model, &iter, path)) {
gchar *name;
gchar *folder;
gchar pathname[256];
gint num;
ImxPlayer *player = (ImxPlayer *)data;
gtk_tree_model_get(model, &iter, NUMBER, &num,
FILE_NAME, &name, FOLDER_PATH, &folder, -1);
sprintf(pathname, "%s/%s", folder, name);
g_print ("select and start play [%d]%s\n", num, pathname);
playlist_set_file(player, pathname);
player->playlistbox.current = num;
g_free(name);
g_free(folder);
}
}
void playlistbox_create(void *imxplayer)
{
GtkWidget *sw;
GtkWidget *remove;
GtkWidget *add;
GtkWidget *adddir;
GtkWidget *removeAll;
GtkWidget *close;
GtkWidget *hbox;
GtkWidget *vbox;
ImxPlayer *player = (ImxPlayer *)imxplayer;
PlaylistBox *playlistbox = &player->playlistbox;
sw = gtk_scrolled_window_new(NULL, NULL);
playlistbox->playlist_box = gtk_event_box_new();
playlistbox->list = gtk_tree_view_new();
gtk_widget_set_size_request(playlistbox->playlist_box, PLAYLISTBOX_W,
PLAYLISTBOX_H);
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(playlistbox->playlist_box), vbox);
/*
gtk_widget_modify_bg(playlistbox->playlist_box, GTK_STATE_NORMAL,
&player->color_key);
gtk_fixed_put(GTK_FIXED(player->fixed_ct), playlistbox->playlist_box,
player->window_w-PLAYLISTBOX_W, INFO_BOX_H);
*/
hbox = gtk_hbox_new(TRUE, 1);
add = gtk_button_new_with_label("Add");
adddir = gtk_button_new_with_label("Add Folder");
remove = gtk_button_new_with_label("Remove");
removeAll = gtk_button_new_with_label("Remove All");
close = gtk_button_new_with_label("Close");
gtk_box_pack_start(GTK_BOX(hbox), add, FALSE, TRUE, 1);
gtk_box_pack_start(GTK_BOX(hbox), adddir, FALSE, TRUE, 1);
gtk_box_pack_start(GTK_BOX(hbox), remove, FALSE, TRUE, 1);
gtk_box_pack_start(GTK_BOX(hbox), removeAll, FALSE, TRUE, 1);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw),
GTK_SHADOW_ETCHED_IN);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (playlistbox->list), TRUE);
gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 1);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 1);
gtk_box_pack_end(GTK_BOX(vbox), close, FALSE, TRUE, 1);
gtk_container_add(GTK_CONTAINER(sw), playlistbox->list);
gtk_container_add(GTK_CONTAINER(player->fixed_ct), playlistbox->playlist_box);
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkListStore *store;
GtkTreeSelection *select;
/* --- Column #1 --- */
renderer = gtk_cell_renderer_text_new();
g_object_set(G_OBJECT(renderer), "foreground", "green", NULL);
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW (playlistbox->list),
-1, "No.", renderer, "text", NUMBER, NULL);
/* --- Column #2 --- */
renderer = gtk_cell_renderer_text_new();
g_object_set(G_OBJECT(renderer), "foreground", "green", NULL);
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW (playlistbox->list),
-1, "File Name", renderer, "text", FILE_NAME, NULL);
/* --- Column #3 --- */
renderer = gtk_cell_renderer_text_new();
g_object_set(G_OBJECT(renderer), "foreground", "green", NULL);
column = gtk_tree_view_column_new_with_attributes("Folder", renderer,
"text", FOLDER_PATH, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW (playlistbox->list), column);
gtk_tree_view_column_set_visible(column, FALSE);
store = gtk_list_store_new (NBR_COLUMNS, G_TYPE_UINT, G_TYPE_STRING,
G_TYPE_STRING);
gtk_tree_view_set_model(GTK_TREE_VIEW (playlistbox->list),
GTK_TREE_MODEL(store));
g_object_unref(store);
select = gtk_tree_view_get_selection(GTK_TREE_VIEW(playlistbox->list));
gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
g_signal_connect(G_OBJECT(add), "clicked",
G_CALLBACK(add_item), player);
g_signal_connect(G_OBJECT(adddir), "clicked",
G_CALLBACK(add_dir_item), player);
g_signal_connect(G_OBJECT(remove), "clicked",
G_CALLBACK(remove_item), player);
g_signal_connect(G_OBJECT(removeAll), "clicked",
G_CALLBACK(remove_all), player);
g_signal_connect(G_OBJECT(close), "clicked",
G_CALLBACK(close_list), player);
g_signal_connect(G_OBJECT(playlistbox->list), "row-activated",
G_CALLBACK (item_activate), player);
playlistbox->previous = playlist_set_previous;
playlistbox->next = playlist_set_next;
playlistbox->set_repeat = playlist_set_repeat;
playlistbox->get_repeat = playlist_get_repeat;
playlistbox->add_file = playlist_add_file;
playlistbox->add_folder = playlist_add_folder;
playlistbox->player = player;
playlistbox->repeat = REPEAT_OFF;
playlistbox->count = 0;
playlistbox->current = 0;
}
void playlistbox_show(PlaylistBox *playlistbox, gboolean show)
{
if (show)
gtk_widget_show(playlistbox->playlist_box);
else
gtk_widget_hide(playlistbox->playlist_box);
}
void playlistbox_resize(GtkWidget *container, PlaylistBox *playlistbox,
gint x, gint y, gint w, gint h)
{
gtk_widget_set_size_request(playlistbox->playlist_box, w, h);
gtk_fixed_move(GTK_FIXED(container), playlistbox->playlist_box, x, y);
}