? libmuine/a ? libmuine/a.c ? libmuine/gst-inspect.c ? libmuine/kk.mp3 ? libmuine/recorder-marshal.c ? libmuine/recorder-marshal.h ? libmuine/test ? libmuine/test.c ? src/a.cs Index: ChangeLog =================================================================== RCS file: /cvs/gnome/muine/ChangeLog,v retrieving revision 1.339 diff -u -u -r1.339 ChangeLog --- ChangeLog 16 Oct 2004 17:34:03 -0000 1.339 +++ ChangeLog 30 Oct 2004 19:36:07 -0000 @@ -1,3 +1,32 @@ +2004-10-30 Fernando Herrera + + * configure.in: + * data/glade/BurnPrefs.glade: + * data/glade/Makefile.am: + * data/glade/PlaylistWindow.glade: + * data/glade/ProgressWindow.glade: + * data/glade/WarningDialog.glade: + * libmuine/Makefile.am: + * libmuine/metadata.c: (metadata_load): + * libmuine/recorder-gst.c: + * libmuine/recorder-marshal.list: + * libmuine/recorder.h: + * src/Album.cs: + * src/BurnPrefs.cs: + * src/CdUnit.cs: + * src/Makefile.am: + * src/NotificationAreaIcon.cs: (NotificationAreaIcon), + (NotificationAreaIcon.CreatePopupMenu): + * src/Player.cs: (Player): + * src/PlaylistWindow.cs: (PlaylistWindow), + (PlaylistWindow...HandleDragDataReceived), + (PlaylistWindow...CheckFirstStartUp): + * src/ProgressWindow.cs: (ProgressWindow), + (ProgressWindow.ProgressWindow), (ProgressWindow.ReportFile): + * src/Recorder.cs: + * src/WarningDialog.cs: (WarningDialog), (WarningDialog.Setup), + (WarningDialog.WarningDialog): Add Playlist burn support. + 2004-10-16 Hasbullah Bin Pit * configure.in: Added "ms" (Malay) to ALL_LINGUAS Index: configure.in =================================================================== RCS file: /cvs/gnome/muine/configure.in,v retrieving revision 1.73 diff -u -u -r1.73 configure.in --- configure.in 16 Oct 2004 17:34:03 -0000 1.73 +++ configure.in 30 Oct 2004 19:36:07 -0000 @@ -48,7 +48,10 @@ gdk-pixbuf-2.0 \ gnome-vfs-2.0 \ gtk+-2.0 \ + libnautilus-burn \ libgnome-2.0 \ + gstreamer-0.8 \ + gstreamer-play-0.8 \ $audio_pkgconfig) AC_SUBST(MUINE_CFLAGS) AC_SUBST(MUINE_LIBS) Index: data/glade/BurnPrefs.glade =================================================================== RCS file: data/glade/BurnPrefs.glade diff -N data/glade/BurnPrefs.glade --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ data/glade/BurnPrefs.glade 30 Oct 2004 19:36:09 -0000 @@ -0,0 +1,119 @@ + + + + + + + + 7 + + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + False + + + + True + False + 6 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + + True + True + True + _Burn + True + GTK_RELIEF_NORMAL + True + -5 + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 6 + + + + True + Select CD Drive: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + -1 + + + 0 + False + False + + + + + 0 + True + True + + + + + + + Index: data/glade/Makefile.am =================================================================== RCS file: /cvs/gnome/muine/data/glade/Makefile.am,v retrieving revision 1.9 diff -u -u -r1.9 Makefile.am --- data/glade/Makefile.am 15 Apr 2004 19:31:31 -0000 1.9 +++ data/glade/Makefile.am 30 Oct 2004 19:36:09 -0000 @@ -4,10 +4,12 @@ SkipToWindow.glade \ NoMusicFoundWindow.glade \ ErrorDialog.glade \ + WarningDialog.glade \ YesNoDialog.glade \ ProgressWindow.glade \ InfoWindow.glade \ PlaylistFilling.glade \ - GroupEditor.glade + GroupEditor.glade \ + BurnPrefs.glade EXTRA_DIST = $(noinst_DATA) Index: data/glade/PlaylistWindow.glade =================================================================== RCS file: /cvs/gnome/muine/data/glade/PlaylistWindow.glade,v retrieving revision 1.27 diff -u -u -r1.27 PlaylistWindow.glade --- data/glade/PlaylistWindow.glade 9 May 2004 13:17:47 -0000 1.27 +++ data/glade/PlaylistWindow.glade 30 Oct 2004 19:36:15 -0000 @@ -108,6 +108,29 @@ + + True + Burn Play list to a CD + True + + + + + + True + gtk-cdrom + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + True Index: data/glade/ProgressWindow.glade =================================================================== RCS file: /cvs/gnome/muine/data/glade/ProgressWindow.glade,v retrieving revision 1.5 diff -u -u -r1.5 ProgressWindow.glade --- data/glade/ProgressWindow.glade 15 Feb 2004 00:27:42 -0000 1.5 +++ data/glade/ProgressWindow.glade 30 Oct 2004 19:36:16 -0000 @@ -88,7 +88,7 @@ True - Loading: + False False GTK_JUSTIFY_LEFT @@ -134,6 +134,20 @@ 0 True True + + + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.1 + + + 0 + False + False Index: data/glade/WarningDialog.glade =================================================================== RCS file: data/glade/WarningDialog.glade diff -N data/glade/WarningDialog.glade --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ data/glade/WarningDialog.glade 30 Oct 2004 19:36:16 -0000 @@ -0,0 +1,111 @@ + + + + + + + + 7 + Error + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + True + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + False + + + + True + False + 6 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + 0 + False + True + GTK_PACK_END + + + + + + 5 + True + False + 12 + + + + True + gtk-dialog-warning + 6 + 0.5 + 0 + 0 + 0 + + + 0 + False + True + + + + + + True + True + + False + False + GTK_JUSTIFY_LEFT + False + True + 0 + 0.5 + 0 + 0 + + + 0 + True + True + + + + + 0 + False + False + + + + + + + Index: libmuine/Makefile.am =================================================================== RCS file: /cvs/gnome/muine/libmuine/Makefile.am,v retrieving revision 1.11 diff -u -u -r1.11 Makefile.am --- libmuine/Makefile.am 28 Sep 2004 17:54:45 -0000 1.11 +++ libmuine/Makefile.am 30 Oct 2004 19:36:17 -0000 @@ -20,18 +20,29 @@ muinelibdir = $(prefix)/lib/muine muinelib_LTLIBRARIES = libmuine.la +EXTRA_DIST = recorder-marshal.list + if HAVE_XINE xine_sources = player-xine.c endif + if HAVE_GST -gst_sources = player-gst.c +RMARSHALFILES = recorder-marshal.h recorder-marshal.c +recorder-marshal.h: recorder-marshal.list + ( $(GLIB_GENMARSHAL) --prefix=recorder_marshal ./recorder-marshal.list --header > recorder-marshal.h ) +recorder-marshal.c: recorder-marshal.h + ( $(GLIB_GENMARSHAL) --prefix=recorder_marshal ./recorder-marshal.list --body --header > recorder-marshal.c ) +gst_sources = player-gst.c $(RMARSHALFILES) recorder-gst.c +CLEANFILES = $(RMARSHALFILES) + endif libmuine_la_SOURCES = \ $(xine_sources) \ $(gst_sources) \ player.h \ + recorder.h \ metadata.c \ metadata.h \ ogg-helper.c \ Index: libmuine/metadata.c =================================================================== RCS file: /cvs/gnome/muine/libmuine/metadata.c,v retrieving revision 1.13 diff -u -u -r1.13 metadata.c --- libmuine/metadata.c 27 Feb 2004 21:11:01 -0000 1.13 +++ libmuine/metadata.c 30 Oct 2004 19:36:19 -0000 @@ -669,8 +669,10 @@ gnome_vfs_get_file_info (escaped, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE | GNOME_VFS_FILE_INFO_FOLLOW_LINKS); - if (!strcmp (info->mime_type, "audio/x-mp3") || - !strcmp (info->mime_type, "audio/mpeg")) + if (info->mime_type == NULL) { + *error_message_return = g_strdup ("Unknown format"); + } else if (!strcmp (info->mime_type, "audio/x-mp3") || + !strcmp (info->mime_type, "audio/mpeg")) m = assign_metadata_mp3 (escaped, info, error_message_return); else if (!strcmp (info->mime_type, "application/x-ogg") || !strcmp (info->mime_type, "application/ogg")) Index: libmuine/recorder-gst.c =================================================================== RCS file: libmuine/recorder-gst.c diff -N libmuine/recorder-gst.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libmuine/recorder-gst.c 30 Oct 2004 19:36:24 -0000 @@ -0,0 +1,534 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* + * Copyright (C) 2004 Fernando Herrera + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "recorder.h" +#include "recorder-marshal.h" + +static void recorder_class_init (RecorderClass *klass); +static void recorder_init (Recorder *recorder); +static void recorder_finalize (GObject *object); +static void eos_cb (GstElement *sink, + Recorder *recorder); +static void error_cb (GstElement *gstelement, GstElement *arg1, GError *arg2, gchar *arg3, Recorder *recorder); + +static void recorder_cd_progress_cb (CDRecorder *cdrecorder, + gdouble fraction, + gpointer data); + +static gboolean recorder_insert_cd_request_cb (CDRecorder *cdrecorder, + gboolean is_reload, + gboolean can_rewrite, + gboolean busy_cd, + gpointer data); + + + +enum { + END_OF_STREAM, + CD_BURN_PROGRESS, + CD_BURN_INSERT_CD, + ERROR, + LAST_SIGNAL +}; + +struct _RecorderPriv { + GstElement *pipeline; + GstElement *source; + GstElement *decoder; + GstElement *writer; + GstElement *converter; + GstElement *encoder; + GstElement *sink; + + guint eos_idle_id; + gulong eos_idle_handler; + + gint64 pos; + + GList *tracks; + CDDrive *drive; + CDRecorder *cdrecorder; +}; + +static GObjectClass *parent_class; +static guint signals[LAST_SIGNAL]; + +GType +recorder_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (RecorderClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) recorder_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (Recorder), + 0, + (GInstanceInitFunc) recorder_init, + }; + + type = g_type_register_static (G_TYPE_OBJECT, + "Recorder", + &info, 0); + } + + return type; +} + +static void +recorder_class_init (RecorderClass *klass) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (klass); + object_class = (GObjectClass *) klass; + + object_class->finalize = recorder_finalize; + + signals[END_OF_STREAM] = + g_signal_new ("end_of_stream", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[CD_BURN_PROGRESS] = + g_signal_new ("cd_burn_progress", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__DOUBLE, + G_TYPE_NONE, 1, G_TYPE_DOUBLE); + signals[CD_BURN_INSERT_CD] = + g_signal_new ("cd_burn_insert_cd", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + recorder_marshal_BOOLEAN__BOOLEAN_BOOLEAN_BOOLEAN, + G_TYPE_BOOLEAN, 3, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); + signals[ERROR] = + g_signal_new ("error", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); +} + +static void +recorder_init (Recorder *recorder) +{ +} + +static void +recorder_construct (Recorder *recorder, char **error) +{ + RecorderPriv *priv; + + gst_init (NULL, NULL); + + priv = g_new0 (RecorderPriv, 1); + recorder->priv = priv; + + priv->eos_idle_id = 0; + + priv->pipeline = gst_pipeline_new ("pipeline"); + + priv->source = gst_element_factory_make ("gnomevfssrc", "source"); + if (!priv->source) { + *error = g_strdup (_("Failed to create the required gnomevfssrc GStreamer element")); + + return; + } + + priv->decoder = gst_element_factory_make ("mad", "decoder"); + if (!priv->decoder) { + *error = g_strdup (_("Could not render GStreamer mad decoder")); + + return; + } + + priv->converter = gst_element_factory_make ("audioconvert", "converter"); + + priv->encoder = gst_element_factory_make ("wavenc", "encoder"); + + priv->sink = gst_element_factory_make ("filesink", "sink"); + + gst_bin_add_many (GST_BIN (priv->pipeline), priv->source, priv->decoder, priv->converter, priv->encoder, priv->sink, NULL); + gst_element_link_many (priv->source, priv->decoder, priv->converter, priv->encoder, priv->sink, NULL); + + g_signal_connect (priv->pipeline, "error", G_CALLBACK (error_cb), recorder); + priv->eos_idle_handler = g_signal_connect (priv->pipeline, "eos", G_CALLBACK (eos_cb), recorder); + + priv->tracks = NULL; + priv->drive = NULL; + + priv->cdrecorder = cd_recorder_new (); + + g_signal_connect (G_OBJECT (priv->cdrecorder), "progress-changed", G_CALLBACK (recorder_cd_progress_cb), recorder); + g_signal_connect (G_OBJECT (priv->cdrecorder), "insert-cd-request", G_CALLBACK (recorder_insert_cd_request_cb), recorder); + + +} + +static void +recorder_finalize (GObject *object) +{ + Recorder *recorder = RECORDER (object); + + //recorder_write_file_cancel (recorder); + + g_free (recorder->priv); + + if (G_OBJECT_CLASS (parent_class)->finalize) + (* G_OBJECT_CLASS (parent_class)->finalize) (object); +} + +Recorder * +recorder_new (char **error) +{ + Recorder *recorder; + + recorder = g_object_new (TYPE_RECORDER, NULL); + + *error = NULL; + + recorder_construct (recorder, error); + + return recorder; +} + +static void +eos_cb (GstElement *sink, Recorder *recorder) +{ + recorder->priv->eos_idle_id = 0; + gst_element_set_state (GST_ELEMENT (recorder->priv->pipeline), GST_STATE_NULL); + g_signal_emit (recorder, signals[END_OF_STREAM], 0); +} + +typedef struct { + Recorder *recorder; + char *error; +} RecorderError; + +static gboolean +error_idle_cb (RecorderError *data) +{ + g_signal_emit (data->recorder, signals[ERROR], 0, data->error); + + g_free (data->error); + g_free (data); + + return FALSE; +} + +static void +error_cb (GstElement *gstelement, + GstElement *arg1, + GError *error, + gchar *str, + Recorder *recorder) +{ + RecorderError *data = g_new0 (RecorderError, 1); + + data->recorder = recorder; + data->error = g_strconcat (error->message, ":\n", str, NULL); + + g_signal_handler_disconnect (recorder->priv->pipeline, recorder->priv->eos_idle_handler); + + g_idle_add ((GSourceFunc) error_idle_cb, data); +} + +gboolean +recorder_set_orig (Recorder *recorder, + const char *file, + char **error) +{ + g_return_val_if_fail (IS_RECORDER (recorder), FALSE); + + *error = NULL; + + g_print ("File=%s\n", file); + + if (recorder->priv->eos_idle_id > 0) { + g_source_remove (recorder->priv->eos_idle_id); + recorder->priv->eos_idle_id = 0; + } + + g_object_set (G_OBJECT (recorder->priv->source), "location", file, NULL); + + recorder->priv->pos = 0; + + return TRUE; +} + +gboolean +recorder_set_dest (Recorder *recorder, + const char *file, + char **error) +{ + g_return_val_if_fail (IS_RECORDER (recorder), FALSE); + + *error = NULL; + + if (recorder->priv->eos_idle_id > 0) { + g_source_remove (recorder->priv->eos_idle_id); + recorder->priv->eos_idle_id = 0; + } + + g_object_set (G_OBJECT (recorder->priv->sink), "location", file, NULL); + + recorder->priv->pos = 0; + + return TRUE; +} + + +void +recorder_write_file (Recorder *recorder) +{ + g_return_if_fail (IS_RECORDER (recorder)); + + gst_element_set_state (GST_ELEMENT (recorder->priv->pipeline), GST_STATE_PLAYING); + + recorder->priv->eos_idle_id = g_idle_add ((GSourceFunc) gst_bin_iterate, GST_BIN (recorder->priv->pipeline)); + +} + +void +recorder_write_file_cancel (Recorder *recorder) +{ + g_return_if_fail (IS_RECORDER (recorder)); + + recorder->priv->pos = 0; + + gst_element_set_state (GST_ELEMENT (recorder->priv->pipeline), GST_STATE_READY); +} + +void +recorder_pause (Recorder *recorder) +{ + g_return_if_fail (IS_RECORDER (recorder)); + + gst_element_set_state (GST_ELEMENT (recorder->priv->pipeline), GST_STATE_PAUSED); +} + +int +recorder_tell (Recorder *recorder) +{ + g_return_val_if_fail (IS_RECORDER (recorder), -1); + + return recorder->priv->pos / GST_SECOND; +} + +gboolean +recorder_add_track (Recorder *recorder, + const char *file, + char **error) +{ + Track *track; + g_return_val_if_fail (IS_RECORDER (recorder), FALSE); + + *error = NULL; + + track = g_new0 (Track, 1); + + track->type = TRACK_TYPE_AUDIO; + track->contents.audio.filename = g_strdup (file); + track->contents.audio.cdtext = g_path_get_basename (file); + + + /* FIXME: check for existence */ + + recorder->priv->tracks = g_list_append (recorder->priv->tracks, track); + + return TRUE; +} + +gboolean +recorder_has_many_devices () +{ + GList *drives, *tmp; + int num_drives = 0; + + drives = scan_for_cdroms (FALSE, FALSE); + + for (tmp = drives; tmp != NULL; tmp = tmp->next) { + CDDrive *drive = (CDDrive*) tmp->data; + + if (drive->type & (CDDRIVE_TYPE_CD_RECORDER | CDDRIVE_TYPE_CDRW_RECORDER | + CDDRIVE_TYPE_DVD_RAM_RECORDER | CDDRIVE_TYPE_DVD_RW_RECORDER | + CDDRIVE_TYPE_DVD_PLUS_R_RECORDER | CDDRIVE_TYPE_DVD_PLUS_RW_RECORDER)) + num_drives++; + + cd_drive_free (drive); + } + g_list_free (drives); + + return num_drives > 1; +} + +gchar* +recorder_get_valid_devices (void) +{ + GList *drives, *tmp; + GString *buf; + gchar *str; + + buf = g_string_new (NULL); + + drives = scan_for_cdroms (FALSE, FALSE); + + for (tmp = drives; tmp != NULL; tmp = tmp->next) { + CDDrive *drive = (CDDrive*) tmp->data; + + if (drive->type & (CDDRIVE_TYPE_CD_RECORDER | CDDRIVE_TYPE_CDRW_RECORDER | + CDDRIVE_TYPE_DVD_RAM_RECORDER | CDDRIVE_TYPE_DVD_RW_RECORDER | + CDDRIVE_TYPE_DVD_PLUS_R_RECORDER | CDDRIVE_TYPE_DVD_PLUS_RW_RECORDER)) { + g_string_append (buf, drive->device); + g_string_append (buf, ":"); + g_string_append (buf, drive->display_name); + g_string_append (buf, ";"); + } + cd_drive_free (drive); + } + g_list_free (drives); + + str = g_string_free (buf, FALSE); + + return str; +} + +gboolean +recorder_select_drive (Recorder *recorder, + const char *device, + char **error) +{ + GList *drives, *tmp; + g_return_val_if_fail (IS_RECORDER (recorder), FALSE); + + *error = NULL; + + drives = scan_for_cdroms (FALSE, FALSE); + + for (tmp = drives; tmp != NULL; tmp = tmp->next) { + CDDrive *drive = (CDDrive*) tmp->data; + if (strcmp (drive->device, device) == 0) { + recorder->priv->drive = drive; + break; + } + cd_drive_free (drive); + } + g_list_free (drives); + + if (recorder->priv->drive == NULL) { + *error = g_strdup_printf (_("Cannot found drive %s"), device); + return FALSE; + } + + if (!(recorder->priv->drive->type & (CDDRIVE_TYPE_CD_RECORDER | CDDRIVE_TYPE_CDRW_RECORDER | + CDDRIVE_TYPE_DVD_RAM_RECORDER | CDDRIVE_TYPE_DVD_RW_RECORDER | + CDDRIVE_TYPE_DVD_PLUS_R_RECORDER | CDDRIVE_TYPE_DVD_PLUS_RW_RECORDER))) { + *error = g_strdup_printf (_("Drive %s cannot burn CDs"), device); + return FALSE; + } + + return TRUE; +} + +gint64 +recorder_get_media_size (Recorder *recorder) +{ + g_return_val_if_fail (IS_RECORDER (recorder), CD_MEDIA_SIZE_NA); + return cd_drive_get_media_size (recorder->priv->drive); +} + + +/* FIXME: Exportar una funcion nueva para hacer get_size del CD */ + +int +recorder_burn_cd (Recorder *recorder) +{ + g_return_val_if_fail (IS_RECORDER (recorder), FALSE); + return cd_recorder_write_tracks (recorder->priv->cdrecorder, recorder->priv->drive, recorder->priv->tracks, 0, + CDRECORDER_DUMMY_WRITE | CDRECORDER_DISC_AT_ONCE | CDRECORDER_DEBUG); +} + +static void +recorder_cd_progress_cb (CDRecorder *cdrecorder, gdouble fraction, gpointer data) +{ + Recorder *recorder = (Recorder*) data; + + g_signal_emit (recorder, signals[CD_BURN_PROGRESS], 0, fraction); +} + +static gboolean +recorder_insert_cd_request_cb (CDRecorder *cdrecorder, gboolean is_reload, gboolean can_rewrite, gboolean busy_cd, gpointer data) +{ + + Recorder *recorder = (Recorder*) data; + gboolean res; + + g_signal_emit (recorder, signals[CD_BURN_INSERT_CD], 0, is_reload, can_rewrite, busy_cd, &res); + return res; +} + + + + +unsigned long long +get_dir_free_space (char *path) +{ + GnomeVFSFileSize size; + GnomeVFSURI *uri; + + uri = gnome_vfs_uri_new (path); + if (gnome_vfs_get_volume_free_space (uri, &size) == GNOME_VFS_OK) { + gnome_vfs_uri_unref (uri); + return (unsigned long) size; + } else { + gnome_vfs_uri_unref (uri); + return 0; + } +} + Index: libmuine/recorder-marshal.list =================================================================== RCS file: libmuine/recorder-marshal.list diff -N libmuine/recorder-marshal.list --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libmuine/recorder-marshal.list 30 Oct 2004 19:36:24 -0000 @@ -0,0 +1 @@ +BOOLEAN:BOOLEAN,BOOLEAN,BOOLEAN Index: libmuine/recorder.h =================================================================== RCS file: libmuine/recorder.h diff -N libmuine/recorder.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libmuine/recorder.h 30 Oct 2004 19:36:24 -0000 @@ -0,0 +1,75 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* + * Copyright (C) 2004 Fernando Herrera + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __RECORDER_H__ +#define __RECORDER_H__ + +#include + +#define TYPE_RECORDER (recorder_get_type ()) +#define RECORDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RECORDER, Recorder)) +#define RECORDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RECORDER, RecorderClass)) +#define IS_RECORDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RECORDER)) +#define IS_RECORDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RECORDER)) +#define RECORDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RECORDER, RecorderClass)) + +typedef struct _Recorder Recorder; +typedef struct _RecorderClass RecorderClass; +typedef struct _RecorderPriv RecorderPriv; + +struct _Recorder +{ + GObject parent; + RecorderPriv *priv; +}; + +struct _RecorderClass +{ + GObjectClass parent_class; +}; + + +GType recorder_get_type (void); +Recorder * recorder_new (char **error); +gboolean recorder_set_orig (Recorder *recorder, + const char *filename, + char **error); +gboolean recorder_set_dest (Recorder *recorder, + const char *filename, + char **error); +void recorder_write_file (Recorder *recorder); +void recorder_write_file_cancel (Recorder *recorder); +gboolean recorder_add_track (Recorder *recorder, + const char *filename, + char **error); +gchar * recorder_get_valid_devices (void); +gboolean recorder_has_many_devices (void); +gboolean recorder_select_drive (Recorder *recorder, + const char *device, + char **error); + +gint64 recorder_get_media_size (Recorder *recorder); + +int recorder_burn_cd (Recorder *recorder); +void recorder_pause (Recorder *recorder); +int recorder_tell (Recorder *recorder); +unsigned long long get_dir_free_space (char *path); + +#endif /* __RECORDER_H__ */ Index: src/Album.cs =================================================================== RCS file: /cvs/gnome/muine/src/Album.cs,v retrieving revision 1.25 diff -u -u -r1.25 Album.cs --- src/Album.cs 20 Jun 2004 18:53:26 -0000 1.25 +++ src/Album.cs 30 Oct 2004 19:36:27 -0000 @@ -19,6 +19,11 @@ using System; using System.Collections; +using System.IO; +using System.Net; +using System.Threading; +using System.Runtime.InteropServices; + public class Album { Index: src/BurnPrefs.cs =================================================================== RCS file: src/BurnPrefs.cs diff -N src/BurnPrefs.cs --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/BurnPrefs.cs 30 Oct 2004 19:36:27 -0000 @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2004 Fernando Herrera + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +using System; +using System.Collections; + +using Gtk; +using GLib; + +public class BurnPrefs +{ + [Glade.Widget] + Window window; + [Glade.Widget] + OptionMenu drives_menu; + + private ArrayList devices; + + + public BurnPrefs (ArrayList devices) + { + Glade.XML gxml = new Glade.XML (null, "BurnPrefs.glade", "window", null); + gxml.Autoconnect (this); + + this.devices = (ArrayList) devices.Clone (); + + window.Title = String.Format (Muine.Catalog.GetString ("Burn playlist")); + + window.SetDefaultSize (400, -1); + Menu m = new Menu (); + foreach (CdUnit unit in devices) { + MenuItem item = new MenuItem (unit.Name); + m.Append (item); + } + drives_menu.Menu = m; + drives_menu.ShowAll (); + try { + String path = (String) Muine.GConfClient.Get ("/apps/muine/burn/drive"); + for (int i = 0; i < devices.Count; i++) { + CdUnit unit = (CdUnit) devices[i]; + if (unit.Path == path) + drives_menu.SetHistory ((uint) i); + } + } catch { + drives_menu.SetHistory (0); + } + } + + public bool GetDrivePath (out String drive_path) + { + int res = ((Dialog) window).Run (); + + if (res == (int) ResponseType.Ok) { + CdUnit unit = (CdUnit) devices[(int) drives_menu.History]; + drive_path = unit.Path; + Muine.GConfClient.Set ("/apps/muine/burn/drive", drive_path); + window.Destroy (); + return true; + } else { + drive_path = null; + window.Destroy (); + return false; + } + } + +} Index: src/CdUnit.cs =================================================================== RCS file: src/CdUnit.cs diff -N src/CdUnit.cs --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/CdUnit.cs 30 Oct 2004 19:36:27 -0000 @@ -0,0 +1,29 @@ +public class CdUnit { + + private string name; + public string Name { + get { + return name; + } + set { + name = value; + } + } + + private string path; + public string Path { + get { + return path; + } + set { + path = value; + } + } + + + public CdUnit (string path, string name) + { + Path = path; + Name = name; + } +} Index: src/Makefile.am =================================================================== RCS file: /cvs/gnome/muine/src/Makefile.am,v retrieving revision 1.37 diff -u -u -r1.37 Makefile.am --- src/Makefile.am 28 Sep 2004 17:54:45 -0000 1.37 +++ src/Makefile.am 30 Oct 2004 19:36:31 -0000 @@ -13,6 +13,7 @@ $(srcdir)/About.cs \ $(srcdir)/Metadata.cs \ $(srcdir)/Player.cs \ + $(srcdir)/Recorder.cs \ $(srcdir)/FileSelector.cs \ $(srcdir)/StringUtils.cs \ $(srcdir)/KeyUtils.cs \ @@ -20,6 +21,7 @@ $(srcdir)/NoMusicFoundWindow.cs \ $(srcdir)/ProgressWindow.cs \ $(srcdir)/ErrorDialog.cs \ + $(srcdir)/WarningDialog.cs \ $(srcdir)/YesNoDialog.cs \ $(srcdir)/VolumeButton.cs \ $(srcdir)/HandleView.cs \ @@ -35,7 +37,9 @@ $(srcdir)/CoverImage.cs \ $(srcdir)/MmKeys.cs \ $(srcdir)/GettextCatalog.cs \ - $(srcdir)/FileUtils.cs + $(srcdir)/FileUtils.cs \ + $(srcdir)/CdUnit.cs \ + $(srcdir)/BurnPrefs.cs ASSEMBLIES = \ -r:AmazonSearchService.dll \ @@ -52,6 +56,7 @@ /resource:$(top_srcdir)/data/glade/AddWindow.glade,AddWindow.glade \ /resource:$(top_srcdir)/data/glade/ProgressWindow.glade,ProgressWindow.glade \ /resource:$(top_srcdir)/data/glade/InfoWindow.glade,InfoWindow.glade \ + /resource:$(top_srcdir)/data/glade/BurnPrefs.glade,BurnPrefs.glade \ /resource:$(top_srcdir)/data/images/muine-previous.png,muine-previous.png \ /resource:$(top_srcdir)/data/images/muine-previous-16.png,muine-previous-16.png \ /resource:$(top_srcdir)/data/images/muine-play.png,muine-play.png \ Index: src/NotificationAreaIcon.cs =================================================================== RCS file: /cvs/gnome/muine/src/NotificationAreaIcon.cs,v retrieving revision 1.22 diff -u -u -r1.22 NotificationAreaIcon.cs --- src/NotificationAreaIcon.cs 18 Jun 2004 19:33:16 -0000 1.22 +++ src/NotificationAreaIcon.cs 30 Oct 2004 19:36:33 -0000 @@ -43,6 +43,7 @@ public ImageMenuItem play_song_menu_item; public ImageMenuItem play_album_menu_item; public MenuItem show_window_menu_item; + public ImageMenuItem quit_menu_item; private bool button_down = false; @@ -105,6 +106,13 @@ show_window_menu_item = new MenuItem (Muine.Catalog.GetString ("Show _Window")); menu.Append (show_window_menu_item); + + sep = new SeparatorMenuItem (); + menu.Append (sep); + + quit_menu_item = new ImageMenuItem (Muine.Catalog.GetString ("_Quit")); + quit_menu_item.Image = new Gtk.Image (Stock.Quit, IconSize.Menu); + menu.Append (quit_menu_item); menu.ShowAll (); } Index: src/Player.cs =================================================================== RCS file: /cvs/gnome/muine/src/Player.cs,v retrieving revision 1.18 diff -u -u -r1.18 Player.cs --- src/Player.cs 28 Sep 2004 17:45:09 -0000 1.18 +++ src/Player.cs 30 Oct 2004 19:36:33 -0000 @@ -27,6 +27,11 @@ string filename, out IntPtr error_ptr); [DllImport ("libmuine")] + private static extern bool player_set_output_file (IntPtr player, + string filename, + out IntPtr error_ptr); + + [DllImport ("libmuine")] private static extern void player_set_replaygain (IntPtr player, double gain, double peak); Index: src/PlaylistWindow.cs =================================================================== RCS file: /cvs/gnome/muine/src/PlaylistWindow.cs,v retrieving revision 1.127 diff -u -u -r1.127 PlaylistWindow.cs --- src/PlaylistWindow.cs 28 Sep 2004 17:24:39 -0000 1.127 +++ src/PlaylistWindow.cs 30 Oct 2004 19:36:47 -0000 @@ -21,6 +21,7 @@ using System.Collections; using System.IO; using System.Text.RegularExpressions; +using System.Runtime.InteropServices; using Gtk; using GLib; @@ -84,6 +85,9 @@ /* the player object */ private Player player; + /* the recorder object */ + private Recorder recorder; + /* the playlist filename */ private string playlist_filename; @@ -207,7 +211,7 @@ return; } - ProgressWindow pw = new ProgressWindow (this, dinfo.Name); + ProgressWindow pw = new ProgressWindow (this, Muine.Catalog.GetString ("Loading:"), dinfo.Name); Muine.DB.AddWatchedFolder (dinfo.FullName); HandleDirectory (dinfo, pw); @@ -245,7 +249,7 @@ if (!playlistsdir.Exists) playlistsdir.Create (); - ProgressWindow pw = new ProgressWindow (this, musicdir.Name); + ProgressWindow pw = new ProgressWindow (this, Muine.Catalog.GetString ("Loading:"), musicdir.Name); /* seems to be that $HOME/Music does exists, but user hasn't started Muine before! */ Muine.DB.AddWatchedFolder (musicdir.FullName); @@ -403,6 +407,7 @@ icon.play_song_menu_item.Activated += new EventHandler (HandleAddSongCommand); icon.play_album_menu_item.Activated += new EventHandler (HandleAddAlbumCommand); icon.show_window_menu_item.Activated += new EventHandler (HandleToggleWindowVisibilityCommand); + icon.quit_menu_item.Activated += new EventHandler (HandleQuitCommand); } private Gdk.Pixbuf empty_pixbuf; @@ -1372,7 +1377,7 @@ DirectoryInfo dinfo = new DirectoryInfo (fs.Filename); if (dinfo.Exists) { - ProgressWindow pw = new ProgressWindow (this, dinfo.Name); + ProgressWindow pw = new ProgressWindow (this, Muine.Catalog.GetString ("Loading:"), Muine.Catalog.GetString ("Importing ") + dinfo.Name + "..."); Muine.DB.AddWatchedFolder (dinfo.FullName); HandleDirectory (dinfo, pw); @@ -1399,6 +1404,163 @@ OpenPlaylist (fn); } + private bool HandleInsertCdEvent (bool is_reload, bool can_rewrite, bool busy_cd) + { + String msg; + String title; + if (busy_cd) { + msg = Muine.Catalog.GetString ("Please make sure another application is not using the disc."); + title = Muine.Catalog.GetString ("Disc is busy"); + } else if (is_reload && can_rewrite) { + msg = Muine.Catalog.GetString ("Please insert a rewritable or blank media in the drive tray."); + title = Muine.Catalog.GetString ("Insert rewritable or blank media"); + } else if (is_reload && !can_rewrite) { + msg = Muine.Catalog.GetString ("Please insert a blank media in the drive tray."); + title = Muine.Catalog.GetString ("Insert blank media"); + } else if (can_rewrite) { + msg = Muine.Catalog.GetString ("Please replace the in-drive media by a rewritable or blank media."); + title = Muine.Catalog.GetString ("Reload rewritable or blank media"); + } else { + msg = Muine.Catalog.GetString ("Please replace the in-drive media by a blank media."); + title = Muine.Catalog.GetString ("Reload blank media"); + } + + Dialog dialog = new Dialog (title, this, DialogFlags.Modal); + dialog.AddButton (Stock.Ok, ResponseType.Ok); + dialog.AddButton (Stock.Cancel, ResponseType.Cancel); + Label label = new Label (msg); + label.Visible = true; + dialog.VBox.PackStart (label); + if (dialog.Run () == (int) ResponseType.Cancel) { + dialog.Destroy (); + return false; + } + + dialog.Destroy (); + return true; + } + + + + [DllImport ("libmuine")] + private static extern ulong get_dir_free_space (string path); + + private String GetBurnTempDir () + { + String temp_dir; + + try { + temp_dir = (String) Muine.GConfClient.Get ("/apps/muine/burn/temp"); + } catch { + temp_dir = null; + } + + + ulong estimated_size = recorder.GetDuration () * (44100 * 2 * 2 + 271); + Console.WriteLine ("Estimated: " + estimated_size); + Console.WriteLine ("Free: " + (get_dir_free_space (temp_dir) )); + + while (temp_dir == null || temp_dir == "" || estimated_size > get_dir_free_space (temp_dir)) { + Label label; + FileSelection sel = new FileSelection (Muine.Catalog.GetString ("Select a temporal directory")); + + if (temp_dir == null || temp_dir == "") + new ErrorDialog (String.Format (Muine.Catalog.GetString ("You need to select a directory for temporal files")), this); + else { + new ErrorDialog (String.Format (Muine.Catalog.GetString ("{0} has only {1} MiBs free. Please select " + + "another one with at least {2} MiBs free"), + temp_dir, + get_dir_free_space (temp_dir) / 1048576, + estimated_size / 1048576), this); + sel.Filename = temp_dir; + } + + sel.HideFileopButtons (); + sel.HistoryPulldown.Visible = false; + sel.FileList.Parent.Visible = false; + sel.SetDefaultSize (350, 250); + + if (sel.Run () != (int) ResponseType.Ok) { + sel.Destroy (); + return null; + } + temp_dir = sel.Filename; + if (temp_dir.EndsWith ("/") == false) + temp_dir += "/"; + Muine.GConfClient.Set ("/apps/muine/burn/temp", temp_dir); + sel.Destroy (); + Console.WriteLine (temp_dir); + } + return temp_dir; + } + + private String GetBurnDrivePath () + { + String drive_path; + + try { + drive_path = (String) Muine.GConfClient.Get ("/apps/muine/burn/drive"); + } catch { + drive_path = null; + } + if (drive_path != null) { + if (recorder.SetDrive (drive_path) == false) + drive_path = null; + } + + ArrayList devices = recorder.GetValidDevices (); + if (devices.Count == 0) { + new ErrorDialog (String.Format (Muine.Catalog.GetString ("You don't have any recognized CD Recorder"))); + return null; + } + + if (drive_path == null && devices.Count == 1) { + CdUnit unit = (CdUnit) devices[0]; + recorder.SetDrive (unit.Path); + } + + if (drive_path == null || devices.Count > 1) { + BurnPrefs bp = new BurnPrefs (devices); + if (bp.GetDrivePath (out drive_path) == false) + return null; + if (recorder.SetDrive (drive_path) == false) + return null; + } + return drive_path; + } + + private void HandleBurnPlaylistCommand (object o, EventArgs args) + { + String temp_dir; + String drive_path; + long estimated_size, free_space; + + try { + recorder = new Recorder (); + } catch (Exception e) { + new ErrorDialog (String.Format (Muine.Catalog.GetString ("Failed to initialize the recorder backend:\n{0}\n\nExiting..."), e.Message)); + Muine.Exit (); + } + + foreach (int i in playlist.Contents) { + IntPtr handle = new IntPtr (i); + Song song = Song.FromHandle (handle); + recorder.AddSong (song); + } + + temp_dir = GetBurnTempDir (); + if (temp_dir == null) + return; + + drive_path = GetBurnDrivePath (); + if (drive_path == null) + return; + + recorder.InsertCdEvent += new Recorder.InsertCdHandler (HandleInsertCdEvent); + + recorder.WriteFiles (temp_dir); + + } private void HandleSavePlaylistAsCommand (object o, EventArgs args) { FileSelector sel = new FileSelector (Muine.Catalog.GetString ("Save Playlist"), Index: src/ProgressWindow.cs =================================================================== RCS file: /cvs/gnome/muine/src/ProgressWindow.cs,v retrieving revision 1.8 diff -u -u -r1.8 ProgressWindow.cs --- src/ProgressWindow.cs 9 May 2004 20:16:49 -0000 1.8 +++ src/ProgressWindow.cs 30 Oct 2004 19:36:47 -0000 @@ -25,30 +25,35 @@ public class ProgressWindow { [Glade.Widget] - Window window; + public Window window; [Glade.Widget] Label loading_label; [Glade.Widget] Container file_label_container; + [Glade.Widget] + ProgressBar progressbar; private EllipsizingLabel file_label; + private int steps = 0; + private int current_step = 0; bool canceled; - public ProgressWindow (Window parent, string folder) + public ProgressWindow (Window parent, string label, string title) { Glade.XML gxml = new Glade.XML (null, "ProgressWindow.glade", "window", null); gxml.Autoconnect (this); window.TransientFor = parent; - window.Title = String.Format (Muine.Catalog.GetString ("Importing {0}..."), folder); + window.Title = String.Format (title); - window.SetDefaultSize (300, -1); + window.SetDefaultSize (400, -1); file_label = new EllipsizingLabel (""); file_label.Xalign = 0.0f; file_label.Visible = true; file_label_container.Add (file_label); + loading_label.Text = label; MarkupUtils.LabelSetMarkup (loading_label, 0, StringUtils.GetByteLength (loading_label.Text), false, true, false); @@ -73,6 +78,39 @@ Main.Iteration (); return true; + } + + public int TotalSteps { + set { + steps = value; + } + get { + return steps; + } + } + + public double Fraction { + set { + progressbar.Fraction = value; + } + get { + return progressbar.Fraction; + } + } + + public String Label { + set { + loading_label.Text = String.Format (value); + } + get { + return loading_label.Text; + } + } + + public void Step () + { + current_step += 1; + progressbar.Fraction = (double) current_step / steps; } public void Done () Index: src/Recorder.cs =================================================================== RCS file: src/Recorder.cs diff -N src/Recorder.cs --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/Recorder.cs 30 Oct 2004 19:36:49 -0000 @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2004 Jorn Baayen + * Copyright (C) 2004 Fernando Herrera + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +using Gtk; +using System; +using System.Runtime.InteropServices; +using System.Collections; +using System.IO; + + +public class Recorder : GLib.Object +{ + [DllImport ("libmuine")] + private static extern bool recorder_set_orig (IntPtr recorder, + string filename, + out IntPtr error_ptr); + + [DllImport ("libmuine")] + private static extern bool recorder_set_dest (IntPtr recorder, + string filename, + out IntPtr error_ptr); + + [DllImport ("libmuine")] + private static extern bool recorder_add_track (IntPtr recorder, + string filename, + out IntPtr error_ptr); + [DllImport ("libmuine")] + private static extern bool recorder_has_many_devices (); + + [DllImport ("libmuine")] + private static extern string recorder_get_valid_devices (); + + [DllImport ("libmuine")] + private static extern bool recorder_select_drive (IntPtr recorder, + string device, + out IntPtr error_ptr); + [DllImport ("libmuine")] + private static extern long recorder_get_media_size (IntPtr recorder); + + [DllImport ("libmuine")] + private static extern int recorder_burn_cd (IntPtr recorder); + + private bool writing = false; + private int num_songs = 0; + private ulong duration = 0; + private string temp_dir = null; + ProgressWindow pw; + + private Queue songs; + private Queue files; + + public void AddSong (Song song) { + songs.Enqueue (song); + duration += (ulong) song.Duration; + } + + public ulong GetDuration () { + return duration; + } + + [DllImport ("libmuine")] + private static extern void recorder_write_file (IntPtr recorder); + + + [DllImport ("libmuine")] + private static extern void recorder_write_file_cancel (IntPtr recorder); + + private void WriteFileCancel () + { + recorder_write_file_cancel (Raw); + } + + private void WriteFile () + { + IntPtr error_ptr; + Song song; + + if (songs.Count == 0) + return; + + song = (Song) songs.Dequeue (); + + if (pw.ReportFile (song.Title) == false) { + WriteFileCancel (); + return; + } + + recorder_set_orig (Raw, song.Filename, out error_ptr); + if (error_ptr != IntPtr.Zero) { + string error = GLib.Marshaller.PtrToStringGFree (error_ptr); + + new ErrorDialog (String.Format (Muine.Catalog.GetString ("Error opening {0}:\n{1}"), + song, error)); + } + + recorder_set_dest (Raw, temp_dir + System.IO.Path.GetFileNameWithoutExtension (song.Filename) + ".wav", + out error_ptr); + if (error_ptr != IntPtr.Zero) { + string error = GLib.Marshaller.PtrToStringGFree (error_ptr); + + new ErrorDialog (String.Format (Muine.Catalog.GetString ("Error opening {0}{1}.wav:\n{2}"), + temp_dir, + System.IO.Path.GetFileNameWithoutExtension (song.Filename), + error)); + } + + recorder_write_file (Raw); + recorder_add_track (Raw, temp_dir + System.IO.Path.GetFileNameWithoutExtension (song.Filename) + ".wav", + out error_ptr); + + files.Enqueue (temp_dir + System.IO.Path.GetFileNameWithoutExtension (song.Filename) + ".wav"); + + if (error_ptr != IntPtr.Zero) { + string error = GLib.Marshaller.PtrToStringGFree (error_ptr); + + new ErrorDialog (String.Format (Muine.Catalog.GetString ("Error opening {0}:\n{1}"), + System.IO.Path.GetFileNameWithoutExtension (song.Filename), + error)); + } + } + + public void WriteFiles (String path) + { + temp_dir = path; + num_songs = songs.Count; + if (num_songs >= 1) { + pw = new ProgressWindow (null, Muine.Catalog.GetString ("Writing temp files:"), + Muine.Catalog.GetString ("Burning CD")); + pw.TotalSteps = num_songs; + WriteFile (); + } + } + + public ArrayList GetValidDevices () + { + ArrayList res = new ArrayList(); + string str = recorder_get_valid_devices (); + + int pos = 0; + int end = str.IndexOf (';', pos); + Console.WriteLine (str); + while (end > 0) { + int p = str.IndexOf (':', pos); + CdUnit unit = new CdUnit (str.Substring (pos, p - pos), + str.Substring (p + 1, end - p - 1 )); + pos = end + 1; + res.Add (unit); + if (pos >= str.Length) + break; + end = str.IndexOf (';', pos); + } + return res; + + } + + + public bool HasManyDevices () + { + return recorder_has_many_devices (); + } + + public bool SetDrive (String path) + { + IntPtr error_ptr; + recorder_select_drive (Raw, path, out error_ptr); + if (error_ptr != IntPtr.Zero) { + string error = GLib.Marshaller.PtrToStringGFree (error_ptr); + + new ErrorDialog (String.Format (Muine.Catalog.GetString ("Error selection drive:\n{0}"), + error)); + return false; + } + + return true; + } + + public void BurnCd () + { + int res; + + res = recorder_burn_cd (Raw); + /* FIXME Show error or ok */ + + string file; + do { + file = (string) files.Dequeue (); + File.Delete (file); + } while (files.Count >= 1); + + pw.Done (); + } + + + + public delegate bool InsertCdHandler (bool is_reload, bool can_rewrite, bool busy_cd); + public event InsertCdHandler InsertCdEvent; + + + [DllImport ("libmuine")] + private static extern IntPtr recorder_new (out IntPtr error_ptr); + + private class Connect + { + [DllImport ("libgobject-2.0-0.dll")] + public static extern uint g_signal_connect_data (IntPtr obj, string name, + SignalDelegate cb, IntPtr data, + IntPtr p, int flags); + } + + private class ConnectInt + { + [DllImport ("libgobject-2.0-0.dll")] + public static extern uint g_signal_connect_data (IntPtr obj, string name, + IntSignalDelegate cb, IntPtr data, + IntPtr p, int flags); + } + + private class ConnectString + { + [DllImport ("libgobject-2.0-0.dll")] + public static extern uint g_signal_connect_data (IntPtr obj, string name, + StringSignalDelegate cb, IntPtr data, + IntPtr p, int flags); + } + + private class ConnectDouble + { + [DllImport ("libgobject-2.0-0.dll")] + public static extern uint g_signal_connect_data (IntPtr obj, string name, + DoubleSignalDelegate cb, IntPtr data, + IntPtr p, int flags); + } + + private class ConnectBoolBoolBool + { + [DllImport ("libgobject-2.0-0.dll")] + public static extern uint g_signal_connect_data (IntPtr obj, string name, + BoolBoolBoolSignalDelegate cb, IntPtr data, + IntPtr p, int flags); + } + + + public Recorder () : base (IntPtr.Zero) + { + IntPtr error_ptr; + + songs = new Queue (); + files = new Queue (); + Raw = recorder_new (out error_ptr); + if (error_ptr != IntPtr.Zero) { + string error = GLib.Marshaller.PtrToStringGFree (error_ptr); + throw new Exception (error); + } + + Connect.g_signal_connect_data (Raw, "end_of_stream", new SignalDelegate (EosCallback), + IntPtr.Zero, IntPtr.Zero, 0); + ConnectString.g_signal_connect_data (Raw, "error", new StringSignalDelegate (ErrorCallback), + IntPtr.Zero, IntPtr.Zero, 0); + ConnectDouble.g_signal_connect_data (Raw, "cd_burn_progress", new DoubleSignalDelegate (CdProgressCallback), + IntPtr.Zero, IntPtr.Zero, 0); + + ConnectBoolBoolBool.g_signal_connect_data (Raw, "cd_burn_insert_cd", new BoolBoolBoolSignalDelegate (CdInsertionCallback), + IntPtr.Zero, IntPtr.Zero, 0); + + + + } + + ~Recorder () + { + Dispose (); + } + + private delegate void SignalDelegate (IntPtr obj); + private delegate void IntSignalDelegate (IntPtr obj, int i); + private delegate void StringSignalDelegate (IntPtr obj, string s); + private delegate void DoubleSignalDelegate (IntPtr obj, double d); + private delegate bool BoolBoolBoolSignalDelegate (IntPtr obj, bool b1, bool b2, bool b3); + + public delegate void EndOfStreamEventHandler (); + public event EndOfStreamEventHandler EndOfStreamEvent; + + private void EosCallback (IntPtr obj) + { + long media_size = 0; + if (EndOfStreamEvent != null) + EndOfStreamEvent (); + if (songs.Count > 0) { + pw.Step (); + WriteFile (); + } else { + do { + string title, msg; + Dialog dialog; + int res; + + media_size = recorder_get_media_size (Raw); + if (media_size >= (long) duration) + break; + if (media_size == -1 /* CD_MEDIA_SIZE_UNKNOWN */) + break; + if (media_size == -3 /* CD_MEDIA_SIZE_BUSY */) + continue; + if (media_size == -2 /* CD_MEDIA_SIZE_NA */) { + msg = String.Format (Muine.Catalog.GetString ("Please insert a blank disc with at least {0} mins free"), (duration / 60)); + title = Muine.Catalog.GetString ("Insert Disc"); + dialog = new Dialog (title, pw.window, DialogFlags.Modal); + dialog.AddButton (Stock.Ok, ResponseType.Ok); + dialog.AddButton (Stock.Cancel, ResponseType.Cancel); + } else { + + dialog = new Dialog (); + msg = String.Format (Muine.Catalog.GetString ("Please replace the in-drive media with a blank disc with at least {0} mins free"), (duration / 60)); + title = Muine.Catalog.GetString ("Replace Disc"); + dialog = new Dialog (title, pw.window, DialogFlags.Modal); + dialog.AddButton (Muine.Catalog.GetString ("_Write it anyway"), ResponseType.Yes); + dialog.AddButton (Stock.Ok, ResponseType.Ok); + dialog.AddButton (Stock.Cancel, ResponseType.Cancel); + } + + Label label = new Label (msg); + label.Visible = true; + dialog.VBox.PackStart (label); + + res = dialog.Run (); + dialog.Destroy (); + if (res == (int) ResponseType.Cancel) { + pw.Done (); + return ; + } + if (res == (int) ResponseType.Yes) { + //overburn = true; + break; + } + } while (media_size < 0 || (long) duration > ((media_size / 1024 / 1024) - 1) * 48 / 7 / 60); + + + pw.Label = Muine.Catalog.GetString ("Burning CD:"); + pw.ReportFile (Muine.Catalog.GetString ("Initializing unit")); + BurnCd (); + } + } + + private void ErrorCallback (IntPtr obj, string error) + { + pw.Done (); + Muine.GConfClient.Set ("/apps/muine/burn/temp", ""); + new ErrorDialog (String.Format (Muine.Catalog.GetString ("Recorder backend error:\n{0}"), error)); + Dispose (); + } + private void CdProgressCallback (IntPtr obj, double fraction) + { + pw.Fraction = fraction; + pw.ReportFile (Muine.Catalog.GetString ("Progress: " + (int) (fraction * 100) + "%")); + } + private bool CdInsertionCallback (IntPtr obj, bool is_reload, bool can_rewrite, bool busy_cd) + { + return InsertCdEvent (is_reload, can_rewrite, busy_cd); + } + + +} Index: src/WarningDialog.cs =================================================================== RCS file: src/WarningDialog.cs diff -N src/WarningDialog.cs --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/WarningDialog.cs 30 Oct 2004 19:36:49 -0000 @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2004 Jorn Baayen + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +using System; + +using Gtk; +using GLib; + +public class WarningDialog +{ + [Glade.Widget] + Dialog window; + [Glade.Widget] + Label label; + + public void Setup (string text) + { + Glade.XML gxml = new Glade.XML (null, "WarningDialog.glade", "window", null); + gxml.Autoconnect (this); + + string heading = Muine.Catalog.GetString ("Warning:"); + string full_text = heading + "\n\n" + text; + + MarkupUtils.LabelSetMarkup (label, 0, StringUtils.GetByteLength (heading), + true, true, false); + + label.Text = full_text; + + window.Run (); + + window.Destroy (); + } + + public WarningDialog (string text) + { + Setup (text); + } + + public WarningDialog (string text, Window parent) + { + Setup (text); + + window.TransientFor = parent; + } +}