summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
Diffstat (limited to 'gtk2_ardour')
-rw-r--r--gtk2_ardour/ardour_ui.cc2
-rw-r--r--gtk2_ardour/export_channel_selector.cc8
-rw-r--r--gtk2_ardour/export_channel_selector.h2
-rw-r--r--gtk2_ardour/export_dialog.cc97
-rw-r--r--gtk2_ardour/export_dialog.h22
-rw-r--r--gtk2_ardour/export_format_dialog.cc23
-rw-r--r--gtk2_ardour/export_format_dialog.h8
-rw-r--r--gtk2_ardour/export_range_markers_dialog.cc209
-rw-r--r--gtk2_ardour/export_range_markers_dialog.h66
-rw-r--r--gtk2_ardour/export_timespan_selector.cc19
-rw-r--r--gtk2_ardour/export_timespan_selector.h3
-rw-r--r--gtk2_ardour/icons/soundcloud.pngbin0 -> 1140 bytes
-rw-r--r--gtk2_ardour/soundcloud_export_selector.cc110
-rw-r--r--gtk2_ardour/soundcloud_export_selector.h41
-rw-r--r--gtk2_ardour/system_exec.cc808
-rw-r--r--gtk2_ardour/system_exec.h201
-rw-r--r--gtk2_ardour/transcode_ffmpeg.h2
-rw-r--r--gtk2_ardour/video_monitor.h2
-rw-r--r--gtk2_ardour/wscript2
19 files changed, 261 insertions, 1364 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 8487d1d547..90809c907f 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -123,7 +123,7 @@ typedef uint64_t microseconds_t;
#include "video_server_dialog.h"
#include "add_video_dialog.h"
#include "transcode_video_dialog.h"
-#include "system_exec.h"
+#include "pbd/system_exec.h"
#include "i18n.h"
diff --git a/gtk2_ardour/export_channel_selector.cc b/gtk2_ardour/export_channel_selector.cc
index 10e3135b53..20155471af 100644
--- a/gtk2_ardour/export_channel_selector.cc
+++ b/gtk2_ardour/export_channel_selector.cc
@@ -458,15 +458,15 @@ RegionExportChannelSelector::RegionExportChannelSelector (ARDOUR::Session * _ses
raw_button.set_label (string_compose (_("Region contents without fades nor region gain (channels: %1)"), region_chans));
raw_button.signal_toggled ().connect (sigc::mem_fun (*this, &RegionExportChannelSelector::handle_selection));
- vbox.pack_start (raw_button);
+ vbox.pack_start (raw_button, false, false);
fades_button.set_label (string_compose (_("Region contents with fades and region gain (channels: %1)"), region_chans));
fades_button.signal_toggled ().connect (sigc::mem_fun (*this, &RegionExportChannelSelector::handle_selection));
- vbox.pack_start (fades_button);
+ vbox.pack_start (fades_button, false, false);
processed_button.set_label (string_compose (_("Track output (channels: %1)"), track_chans));
processed_button.signal_toggled ().connect (sigc::mem_fun (*this, &RegionExportChannelSelector::handle_selection));
- vbox.pack_start (processed_button);
+ vbox.pack_start (processed_button, false, false);
sync_with_manager();
vbox.show_all_children ();
@@ -541,7 +541,7 @@ TrackExportChannelSelector::TrackExportChannelSelector (ARDOUR::Session * sessio
// Options
options_box.pack_start(region_contents_button);
options_box.pack_start(track_output_button);
- main_layout.pack_start(options_box);
+ main_layout.pack_start(options_box, false, false);
// Track scroller
track_scroller.add (track_view);
diff --git a/gtk2_ardour/export_channel_selector.h b/gtk2_ardour/export_channel_selector.h
index 984026a748..734aa8e57b 100644
--- a/gtk2_ardour/export_channel_selector.h
+++ b/gtk2_ardour/export_channel_selector.h
@@ -122,7 +122,7 @@ class PortExportChannelSelector : public ExportChannelSelector
typedef Gtk::TreeModelColumn<Glib::RefPtr<Gtk::ListStore> > ComboCol;
ComboCol port_list_col;
- /* Channel struct, that represents the selected port and it's name */
+ /* Channel struct, that represents the selected port and its name */
struct Channel {
public:
diff --git a/gtk2_ardour/export_dialog.cc b/gtk2_ardour/export_dialog.cc
index 1458747786..dfba7550ac 100644
--- a/gtk2_ardour/export_dialog.cc
+++ b/gtk2_ardour/export_dialog.cc
@@ -141,68 +141,26 @@ ExportDialog::init ()
}
void
-ExportDialog::expanded_changed ()
-{
- set_resizable(advanced->get_expanded());
-}
-
-void
ExportDialog::init_gui ()
{
Gtk::Alignment * preset_align = Gtk::manage (new Gtk::Alignment());
preset_align->add (*preset_selector);
preset_align->set_padding (0, 12, 0, 0);
- get_vbox()->pack_start (*preset_align, false, false, 0);
-
- Gtk::VPaned * advanced_paned = Gtk::manage (new Gtk::VPaned());
-
- Gtk::VBox* timespan_vbox = Gtk::manage (new Gtk::VBox());
- timespan_vbox->set_spacing (12);
- timespan_vbox->set_border_width (12);
-
- Gtk::Alignment * timespan_align = Gtk::manage (new Gtk::Alignment());
- timespan_label = Gtk::manage (new Gtk::Label (_("Time Span"), Gtk::ALIGN_LEFT));
- timespan_align->add (*timespan_selector);
- timespan_align->set_padding (0, 0, 18, 0);
- timespan_vbox->pack_start (*timespan_label, false, false, 0);
- timespan_vbox->pack_start (*timespan_align, true, true, 0);
- advanced_paned->pack1(*timespan_vbox, true, false);
-
- Gtk::VBox* channels_vbox = Gtk::manage (new Gtk::VBox());
- channels_vbox->set_spacing (12);
- channels_vbox->set_border_width (12);
-
- Gtk::Alignment * channels_align = Gtk::manage (new Gtk::Alignment());
- channels_label = Gtk::manage (new Gtk::Label (_("Channels"), Gtk::ALIGN_LEFT));
- channels_align->add (*channel_selector);
- channels_align->set_padding (0, 12, 18, 0);
- channels_vbox->pack_start (*channels_label, false, false, 0);
- channels_vbox->pack_start (*channels_align, true, true, 0);
- advanced_paned->pack2(*channels_vbox, channel_selector_is_expandable(), false);
-
- get_vbox()->pack_start (*file_notebook, false, false, 0);
- get_vbox()->pack_start (warning_widget, false, false, 0);
- get_vbox()->pack_start (progress_widget, false, false, 0);
-
- advanced = Gtk::manage (new Gtk::Expander (_("Time span and channel options")));
- advanced->property_expanded().signal_changed().connect(
- sigc::mem_fun(*this, &ExportDialog::expanded_changed));
- advanced->add (*advanced_paned);
-
- if (channel_selector_is_expandable()) {
- advanced_sizegroup = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_VERTICAL);
- advanced_sizegroup->add_widget(*timespan_selector);
- advanced_sizegroup->add_widget(*channel_selector);
- }
- get_vbox()->pack_start (*advanced, true, true);
+ Gtk::VBox * file_format_selector = Gtk::manage (new Gtk::VBox());
+ file_format_selector->set_homogeneous (false);
+ file_format_selector->pack_start (*preset_align, false, false, 0);
+ file_format_selector->pack_start (*file_notebook, false, false, 0);
+ file_format_selector->pack_start (*soundcloud_selector, false, false, 0);
- Pango::AttrList bold;
- Pango::Attribute b = Pango::Attribute::create_attr_weight (Pango::WEIGHT_BOLD);
- bold.insert (b);
+ export_notebook.append_page (*file_format_selector, _("File format"));
+ export_notebook.append_page (*timespan_selector, _("Time Span"));
+ export_notebook.append_page (*channel_selector, _("Channels"));
+
+ get_vbox()->pack_start (export_notebook, true, true, 0);
+ get_vbox()->pack_end (warning_widget, false, false, 0);
+ get_vbox()->pack_end (progress_widget, false, false, 0);
- timespan_label->set_attributes (bold);
- channels_label->set_attributes (bold);
}
void
@@ -211,6 +169,7 @@ ExportDialog::init_components ()
preset_selector.reset (new ExportPresetSelector ());
timespan_selector.reset (new ExportTimespanSelectorMultiple (_session, profile_manager));
channel_selector.reset (new PortExportChannelSelector (_session, profile_manager));
+ soundcloud_selector.reset (new SoundcloudExportSelector ());
file_notebook.reset (new ExportFileNotebook ());
}
@@ -301,10 +260,33 @@ ExportDialog::show_conflicting_files ()
}
void
+ExportDialog::soundcloud_upload_progress(double total, double now, std::string title)
+{
+ soundcloud_selector->do_progress_callback(total, now, title);
+
+}
+
+void
ExportDialog::do_export ()
{
try {
profile_manager->prepare_for_export ();
+ handler->upload_username = soundcloud_selector->username();
+ handler->upload_password = soundcloud_selector->password();
+ handler->upload_public = soundcloud_selector->upload_public();
+ handler->upload_open = soundcloud_selector->upload_open();
+
+ handler->SoundcloudProgress.connect_same_thread(
+ *this,
+ boost::bind(&ExportDialog::soundcloud_upload_progress, this, _1, _2, _3)
+ );
+#if 0
+ handler->SoundcloudProgress.connect(
+ *this, invalidator (*this),
+ boost::bind(&ExportDialog::soundcloud_upload_progress, this, _1, _2, _3),
+ gui_context()
+ );
+#endif
handler->do_export ();
show_progress ();
} catch(std::exception & e) {
@@ -418,6 +400,7 @@ ExportRangeDialog::init_components ()
preset_selector.reset (new ExportPresetSelector ());
timespan_selector.reset (new ExportTimespanSelectorSingle (_session, profile_manager, range_id));
channel_selector.reset (new PortExportChannelSelector (_session, profile_manager));
+ soundcloud_selector.reset (new SoundcloudExportSelector ());
file_notebook.reset (new ExportFileNotebook ());
}
@@ -431,6 +414,7 @@ ExportSelectionDialog::init_components ()
preset_selector.reset (new ExportPresetSelector ());
timespan_selector.reset (new ExportTimespanSelectorSingle (_session, profile_manager, X_("selection")));
channel_selector.reset (new PortExportChannelSelector (_session, profile_manager));
+ soundcloud_selector.reset (new SoundcloudExportSelector ());
file_notebook.reset (new ExportFileNotebook ());
}
@@ -444,8 +428,7 @@ void
ExportRegionDialog::init_gui ()
{
ExportDialog::init_gui ();
-
- channels_label->set_text (_("Source"));
+ export_notebook.set_tab_label_text(*export_notebook.get_nth_page(2), _("Source"));
}
void
@@ -456,6 +439,7 @@ ExportRegionDialog::init_components ()
preset_selector.reset (new ExportPresetSelector ());
timespan_selector.reset (new ExportTimespanSelectorSingle (_session, profile_manager, loc_id));
channel_selector.reset (new RegionExportChannelSelector (_session, profile_manager, region, track));
+ soundcloud_selector.reset (new SoundcloudExportSelector ());
file_notebook.reset (new ExportFileNotebook ());
}
@@ -471,5 +455,6 @@ StemExportDialog::init_components ()
preset_selector.reset (new ExportPresetSelector ());
timespan_selector.reset (new ExportTimespanSelectorMultiple (_session, profile_manager));
channel_selector.reset (new TrackExportChannelSelector (_session, profile_manager));
+ soundcloud_selector.reset (new SoundcloudExportSelector ());
file_notebook.reset (new ExportFileNotebook ());
}
diff --git a/gtk2_ardour/export_dialog.h b/gtk2_ardour/export_dialog.h
index 756a3e7b53..315780750e 100644
--- a/gtk2_ardour/export_dialog.h
+++ b/gtk2_ardour/export_dialog.h
@@ -32,6 +32,7 @@
#include "export_file_notebook.h"
#include "export_preset_selector.h"
#include "ardour_dialog.h"
+#include "soundcloud_export_selector.h"
#include <gtkmm.h>
@@ -43,7 +44,8 @@ namespace ARDOUR {
class ExportTimespanSelector;
class ExportChannelSelector;
-class ExportDialog : public ArdourDialog {
+class ExportDialog : public ArdourDialog, public PBD::ScopedConnectionList
+{
public:
@@ -75,26 +77,22 @@ class ExportDialog : public ArdourDialog {
// Must initialize all the shared_ptrs below
virtual void init_components ();
- // Override if the channel selector should not be grown
- virtual bool channel_selector_is_expandable() { return true; }
-
boost::scoped_ptr<ExportPresetSelector> preset_selector;
boost::scoped_ptr<ExportTimespanSelector> timespan_selector;
boost::scoped_ptr<ExportChannelSelector> channel_selector;
boost::scoped_ptr<ExportFileNotebook> file_notebook;
+ boost::scoped_ptr<SoundcloudExportSelector> soundcloud_selector;
Gtk::VBox warning_widget;
Gtk::VBox progress_widget;
- Gtk::Label * timespan_label;
- Gtk::Label * channels_label;
+ /*** GUI components ***/
+ Gtk::Notebook export_notebook;
private:
void init ();
- void expanded_changed();
-
void notify_errors (bool force = false);
void close_dialog ();
@@ -112,10 +110,7 @@ class ExportDialog : public ArdourDialog {
PublicEditor & editor;
StatusPtr status;
- /*** GUI components ***/
- Glib::RefPtr<Gtk::SizeGroup> advanced_sizegroup;
- Gtk::Expander * advanced;
/* Warning area */
@@ -138,6 +133,8 @@ class ExportDialog : public ArdourDialog {
float previous_progress; // Needed for gtk bug workaround
+ void soundcloud_upload_progress(double total, double now, std::string title);
+
/* Buttons */
Gtk::Button * cancel_button;
@@ -170,9 +167,6 @@ class ExportRegionDialog : public ExportDialog
public:
ExportRegionDialog (PublicEditor & editor, ARDOUR::AudioRegion const & region, ARDOUR::AudioTrack & track);
- protected:
- virtual bool channel_selector_is_expandable() { return false; }
-
private:
void init_gui ();
void init_components ();
diff --git a/gtk2_ardour/export_format_dialog.cc b/gtk2_ardour/export_format_dialog.cc
index c5d1573d54..69c494e090 100644
--- a/gtk2_ardour/export_format_dialog.cc
+++ b/gtk2_ardour/export_format_dialog.cc
@@ -51,6 +51,9 @@ ExportFormatDialog::ExportFormatDialog (FormatPtr format, bool new_dialog) :
silence_end_checkbox (_("Add silence at end:")),
silence_end_clock ("silence_end", true, "", true, false, true),
+ upload_checkbox(_("Upload to Soundcloud")),
+ command_label(_("Command to run post-export\n(%f=full path & filename, %d=directory, %b=basename, %u=username, %p=password):")),
+
format_table (3, 4),
compatibility_label (_("Compatibility"), Gtk::ALIGN_LEFT),
quality_label (_("Quality"), Gtk::ALIGN_LEFT),
@@ -113,6 +116,10 @@ ExportFormatDialog::ExportFormatDialog (FormatPtr format, bool new_dialog) :
silence_table.attach (silence_end_checkbox, 1, 2, 2, 3);
silence_table.attach (silence_end_clock, 2, 3, 2, 3);
+ get_vbox()->pack_start (upload_checkbox, false, false);
+ get_vbox()->pack_start (command_label, false, false);
+ get_vbox()->pack_start (command_entry, false, false);
+
/* Format table */
init_format_table();
@@ -142,6 +149,8 @@ ExportFormatDialog::ExportFormatDialog (FormatPtr format, bool new_dialog) :
with_cue.signal_toggled().connect (sigc::mem_fun (*this, &ExportFormatDialog::update_with_cue));
with_toc.signal_toggled().connect (sigc::mem_fun (*this, &ExportFormatDialog::update_with_toc));
+ upload_checkbox.signal_toggled().connect (sigc::mem_fun (*this, &ExportFormatDialog::update_upload));
+ command_entry.signal_changed().connect (sigc::mem_fun (*this, &ExportFormatDialog::update_command));
cue_toc_vbox.pack_start (with_cue, false, false);
cue_toc_vbox.pack_start (with_toc, false, false);
@@ -296,6 +305,8 @@ ExportFormatDialog::load_state (FormatPtr spec)
}
tag_checkbox.set_active (spec->tag());
+ upload_checkbox.set_active (spec->upload());
+ command_entry.set_text (spec->command());
}
void
@@ -718,6 +729,18 @@ ExportFormatDialog::update_with_toc ()
}
void
+ExportFormatDialog::update_upload ()
+{
+ manager.select_upload (upload_checkbox.get_active());
+}
+
+void
+ExportFormatDialog::update_command ()
+{
+ manager.set_command (command_entry.get_text());
+}
+
+void
ExportFormatDialog::update_description()
{
std::string text = ": " + format->description(false);
diff --git a/gtk2_ardour/export_format_dialog.h b/gtk2_ardour/export_format_dialog.h
index 8d37ded2cd..42ed1a9886 100644
--- a/gtk2_ardour/export_format_dialog.h
+++ b/gtk2_ardour/export_format_dialog.h
@@ -175,6 +175,12 @@ class ExportFormatDialog : public ArdourDialog, public PBD::ScopedConnectionList
Gtk::CheckButton silence_end_checkbox;
AudioClock silence_end_clock;
+ /* Upload */
+
+ Gtk::CheckButton upload_checkbox;
+ Gtk::Label command_label;
+ Gtk::Entry command_entry;
+
/* Format table */
struct CompatibilityCols : public Gtk::TreeModelColumnRecord
@@ -307,6 +313,8 @@ class ExportFormatDialog : public ArdourDialog, public PBD::ScopedConnectionList
void update_with_toc ();
void update_with_cue ();
+ void update_upload ();
+ void update_command ();
Gtk::TreeView sample_format_view;
Gtk::TreeView dither_type_view;
diff --git a/gtk2_ardour/export_range_markers_dialog.cc b/gtk2_ardour/export_range_markers_dialog.cc
index 4b99162974..e69de29bb2 100644
--- a/gtk2_ardour/export_range_markers_dialog.cc
+++ b/gtk2_ardour/export_range_markers_dialog.cc
@@ -1,209 +0,0 @@
-/*
- Copyright (C) 2006 Paul Davis
- Author: Andre Raue
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <sys/stat.h>
-
-#include <sstream>
-
-#include "ardour/audioengine.h"
-#include "ardour/sndfile_helpers.h"
-
-#include "ardour_ui.h"
-#include "export_range_markers_dialog.h"
-
-#include "i18n.h"
-
-using namespace Gtk;
-using namespace ARDOUR;
-using namespace PBD;
-using namespace std;
-
-ExportRangeMarkersDialog::ExportRangeMarkersDialog (PublicEditor& editor)
- : ExportDialog(editor)
-{
- set_title (_("Export Ranges"));
- file_frame.set_label (_("Export to Directory"));
-
- do_not_allow_export_cd_markers();
-
- total_duration = 0;
- current_range_marker_index = 0;
-}
-
-Gtk::FileChooserAction
-ExportRangeMarkersDialog::browse_action () const
-{
- return Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER;
-}
-
-void
-ExportRangeMarkersDialog::export_data ()
-{
- getSession().locations()->apply(*this, &ExportRangeMarkersDialog::process_range_markers_export);
-}
-
-void
-ExportRangeMarkersDialog::process_range_markers_export(Locations::LocationList& locations)
-{
- Locations::LocationList::iterator locationIter;
- current_range_marker_index = 0;
- init_progress_computing(locations);
-
- for (locationIter = locations.begin(); locationIter != locations.end(); ++locationIter) {
- Location *currentLocation = (*locationIter);
-
- if(currentLocation->is_range_marker()){
- // init filename
- string filepath = get_target_filepath(
- get_selected_file_name(),
- currentLocation->name(),
- get_selected_header_format());
-
- initSpec(filepath);
-
- spec.start_frame = currentLocation->start();
- spec.end_frame = currentLocation->end();
-
- if (getSession().start_export(spec)){
- // if export fails
- return;
- }
-
- // wait until export of this range finished
- gtk_main_iteration();
-
- while (spec.running){
- if(gtk_events_pending()){
- gtk_main_iteration();
- }else {
- usleep(10000);
- }
- }
-
- current_range_marker_index++;
-
- getSession().stop_export (spec);
- }
- }
-
- spec.running = false;
-}
-
-
-string
-ExportRangeMarkersDialog::get_target_filepath(string path, string filename, string postfix)
-{
- string target_path = path;
- if ((target_path.find_last_of ('/')) != string::npos) {
- target_path += '/';
- }
-
- string target_filepath = target_path + filename + postfix;
- struct stat statbuf;
-
- for(int counter=1; (stat (target_filepath.c_str(), &statbuf) == 0); counter++){
- // while file exists
- ostringstream scounter;
- scounter.flush();
- scounter << counter;
-
- target_filepath =
- target_path + filename + "_" + scounter.str() + postfix;
- }
-
- return target_filepath;
-}
-
-bool
-ExportRangeMarkersDialog::is_filepath_valid(string &filepath)
-{
- // sanity check file name first
- struct stat statbuf;
-
- if (filepath.empty()) {
- // warning dialog
- string txt = _("Please enter a valid target directory.");
- MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
- msg.run();
- return false;
- }
-
- if ( (stat (filepath.c_str(), &statbuf) != 0) ||
- (!S_ISDIR (statbuf.st_mode)) ) {
- string txt = _("Please select an existing target directory. Files are not allowed!");
- MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
- msg.run();
- return false;
- }
-
- // directory needs to exist and be writable
- string dirpath = Glib::path_get_dirname (filepath);
- if (!exists_and_writable (dirpath)) {
- string txt = _("Cannot write file in: ") + dirpath;
- MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
- msg.run();
- return false;
- }
-
- return true;
-}
-
-void
-ExportRangeMarkersDialog::init_progress_computing(Locations::LocationList& locations)
-{
- // flush vector
- range_markers_durations_aggregated.resize(0);
-
- framecnt_t duration_before_current_location = 0;
- Locations::LocationList::iterator locationIter;
-
- for (locationIter = locations.begin(); locationIter != locations.end(); ++locationIter) {
- Location *currentLocation = (*locationIter);
-
- if(currentLocation->is_range_marker()){
- range_markers_durations_aggregated.push_back (duration_before_current_location);
-
- framecnt_t duration = currentLocation->end() - currentLocation->start();
-
- range_markers_durations.push_back (duration);
- duration_before_current_location += duration;
- }
- }
-
- total_duration = duration_before_current_location;
-}
-
-
-gint
-ExportRangeMarkersDialog::progress_timeout ()
-{
- double progress = 0.0;
-
- if (current_range_marker_index >= range_markers_durations.size()){
- progress = 1.0;
- } else{
- progress = ((double) range_markers_durations_aggregated[current_range_marker_index] +
- (spec.progress * (double) range_markers_durations[current_range_marker_index])) /
- (double) total_duration;
- }
-
- set_progress_fraction( progress );
- return TRUE;
-}
diff --git a/gtk2_ardour/export_range_markers_dialog.h b/gtk2_ardour/export_range_markers_dialog.h
index b0a29b5dc2..e69de29bb2 100644
--- a/gtk2_ardour/export_range_markers_dialog.h
+++ b/gtk2_ardour/export_range_markers_dialog.h
@@ -1,66 +0,0 @@
-/*
- Copyright (C) 2006 Andre Raue
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef __export_range_markers_dialog_h__
-#define __export_range_markers_dialog_h__
-
-#include "ardour/location.h"
-
-#include "export_dialog.h"
-
-
-class ExportRangeMarkersDialog : public ExportDialog
-{
- public:
- ExportRangeMarkersDialog (PublicEditor&);
-
- Gtk::FileChooserAction browse_action() const;
-
- protected:
- virtual bool is_filepath_valid(string &filepath);
-
- void export_data();
-
- bool wants_dir() { return true; }
-
- private:
- // keeps the duration of all range_markers before the current
- vector<nframes_t> range_markers_durations_aggregated;
- vector<nframes_t> range_markers_durations;
- // duration of all range markers
- nframes_t total_duration;
- // index of range marker, that get's exported right now
- unsigned int current_range_marker_index;
-
- // sets value of progress bar
- virtual gint progress_timeout ();
-
- // initializes range_markers_durations_aggregated, range_markers_durations
- // and total_duration
- void init_progress_computing(ARDOUR::Locations::LocationList& locations);
-
- // searches for a filename like "<filename><nr>.<postfix>" in path, that
- // does not exist
- string get_target_filepath(string path, string filename, string postfix);
-
- void process_range_markers_export(ARDOUR::Locations::LocationList&);
-};
-
-
-#endif // __export_range_markers_dialog_h__
diff --git a/gtk2_ardour/export_timespan_selector.cc b/gtk2_ardour/export_timespan_selector.cc
index f239ab194b..53b7dc9fe0 100644
--- a/gtk2_ardour/export_timespan_selector.cc
+++ b/gtk2_ardour/export_timespan_selector.cc
@@ -105,6 +105,9 @@ ExportTimespanSelector::ExportTimespanSelector (ARDOUR::Session * session, Profi
/* Range view */
range_list = Gtk::ListStore::create (range_cols);
+ // order by location start times
+ range_list->set_sort_column(range_cols.location, Gtk::SORT_ASCENDING);
+ range_list->set_sort_func(range_cols.location, sigc::mem_fun(*this, &ExportTimespanSelector::location_sorter));
range_view.set_model (range_list);
range_view.set_headers_visible (true);
}
@@ -114,6 +117,22 @@ ExportTimespanSelector::~ExportTimespanSelector ()
}
+int
+ExportTimespanSelector::location_sorter(Gtk::TreeModel::iterator a, Gtk::TreeModel::iterator b)
+{
+ Location *l1 = (*a)[range_cols.location];
+ Location *l2 = (*b)[range_cols.location];
+ const Location *ls = _session->locations()->session_range_location();
+
+ // always sort session range first
+ if (l1 == ls)
+ return -1;
+ if (l2 == ls)
+ return +1;
+
+ return l1->start() - l2->start();
+}
+
void
ExportTimespanSelector::add_range_to_selection (ARDOUR::Location const * loc)
{
diff --git a/gtk2_ardour/export_timespan_selector.h b/gtk2_ardour/export_timespan_selector.h
index 2118a57b83..1c4a952913 100644
--- a/gtk2_ardour/export_timespan_selector.h
+++ b/gtk2_ardour/export_timespan_selector.h
@@ -84,6 +84,7 @@ class ExportTimespanSelector : public Gtk::VBox, public ARDOUR::SessionHandlePtr
void update_range_name (std::string const & path, std::string const & new_text);
void set_selection_state_of_all_timespans (bool);
+ int location_sorter(Gtk::TreeModel::iterator a, Gtk::TreeModel::iterator b);
/*** GUI components ***/
@@ -127,7 +128,7 @@ class ExportTimespanSelector : public Gtk::VBox, public ARDOUR::SessionHandlePtr
Gtk::ScrolledWindow range_scroller;
};
-/// Allows seleting multiple timespans
+/// Allows selecting multiple timespans
class ExportTimespanSelectorMultiple : public ExportTimespanSelector
{
public:
diff --git a/gtk2_ardour/icons/soundcloud.png b/gtk2_ardour/icons/soundcloud.png
new file mode 100644
index 0000000000..39c50fe7b3
--- /dev/null
+++ b/gtk2_ardour/icons/soundcloud.png
Binary files differ
diff --git a/gtk2_ardour/soundcloud_export_selector.cc b/gtk2_ardour/soundcloud_export_selector.cc
new file mode 100644
index 0000000000..1ecab514ab
--- /dev/null
+++ b/gtk2_ardour/soundcloud_export_selector.cc
@@ -0,0 +1,110 @@
+/* soundcloud_export_selector.cpp ***************************************************
+
+ Adapted for Ardour by Ben Loftis, March 2012
+
+ Licence GPL:
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+*************************************************************************************/
+#include "ardour/soundcloud_upload.h"
+#include "soundcloud_export_selector.h"
+
+#include <pbd/error.h>
+#include "pbd/openuri.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <iostream>
+#include <glib/gstdio.h>
+
+#include "i18n.h"
+
+using namespace PBD;
+
+#include "ardour/session_metadata.h"
+#include "utils.h"
+
+SoundcloudExportSelector::SoundcloudExportSelector() :
+ sc_table (4, 3),
+ soundcloud_public_checkbox (_("Make file(s) public")),
+ soundcloud_username_label (_("User Email"), 1.0, 0.5),
+ soundcloud_password_label (_("Password"), 1.0, 0.5),
+ soundcloud_open_checkbox (_("Open uploaded files in browser")),
+ progress_bar()
+{
+
+
+ soundcloud_public_checkbox.set_name ("ExportCheckbox");
+ soundcloud_username_label.set_name ("ExportFormatLabel");
+ soundcloud_username_entry.set_name ("ExportFormatDisplay");
+ soundcloud_password_label.set_name ("ExportFormatLabel");
+ soundcloud_password_entry.set_name ("ExportFormatDisplay");
+
+ soundcloud_username_entry.set_text (ARDOUR::SessionMetadata::Metadata()->user_email());
+ soundcloud_password_entry.set_visibility(false);
+
+ Gtk::Frame *sc_frame = manage(new Gtk::Frame);
+ sc_frame->set_border_width(4);
+ sc_frame->set_shadow_type(Gtk::SHADOW_ETCHED_OUT);
+ sc_frame->set_name("soundcloud_export_box");
+ pack_start(*sc_frame, false, false);
+
+ sc_table.set_border_width(4);
+ sc_table.set_col_spacings (5);
+ sc_table.set_row_spacings (5);
+ sc_frame->add (sc_table);
+
+ // sc_table.attach ( *( manage (new EventBox (::get_icon (X_("soundcloud"))))) , 0, 1, 0, 1);
+ sc_table.attach ( *(Gtk::manage (new Gtk::Image (get_icon (X_("soundcloud"))))) , 0, 1, 0, 2);
+
+ sc_table.attach (soundcloud_public_checkbox, 2, 3, 1, 2);
+ sc_table.attach (soundcloud_username_label, 0, 1, 3, 4);
+ sc_table.attach (soundcloud_username_entry, 1, 3, 3, 4);
+ sc_table.attach (soundcloud_password_label, 0, 1, 5, 6);
+ sc_table.attach (soundcloud_password_entry, 1, 3, 5, 6);
+ sc_table.attach (soundcloud_open_checkbox, 2, 3, 7, 8);
+
+ pack_end(progress_bar, false, false);
+ sc_frame->show_all();
+}
+
+
+int
+SoundcloudExportSelector::do_progress_callback(double ultotal, double ulnow, const std::string &filename)
+{
+ std::cerr << "SoundcloudExportSelector::do_progress_callback(" << ultotal << ", " << ulnow << ", " << filename << ")..." << std::endl;
+ if (soundcloud_cancel) {
+ progress_bar.set_fraction (0);
+ // cancel_button.set_label ("");
+ return -1;
+ }
+
+ double fraction = 0.0;
+ if (ultotal != 0) {
+ fraction = ulnow / ultotal;
+ }
+
+ progress_bar.set_fraction ( fraction );
+
+ std::string prog;
+ prog = string_compose (_("%1: %2 of %3 bytes uploaded"), filename, ulnow, ultotal);
+ progress_bar.set_text( prog );
+
+
+ return 0;
+}
+
diff --git a/gtk2_ardour/soundcloud_export_selector.h b/gtk2_ardour/soundcloud_export_selector.h
new file mode 100644
index 0000000000..7962ba8b06
--- /dev/null
+++ b/gtk2_ardour/soundcloud_export_selector.h
@@ -0,0 +1,41 @@
+/*soundcloud_export_selector.h***********************************************
+
+ Adapted for Ardour by Ben Loftis, March 2012
+
+*****************************************************************************/
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <stdio.h>
+#include <cstring>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <gtkmm.h>
+#include <gtkmm/progressbar.h>
+
+class SoundcloudExportSelector : public Gtk::VBox, public ARDOUR::SessionHandlePtr
+{
+ public:
+ SoundcloudExportSelector ();
+ int do_progress_callback (double ultotal, double ulnow, const std::string &filename);
+ std::string username () { return soundcloud_username_entry.get_text (); }
+ std::string password () { return soundcloud_password_entry.get_text (); }
+ bool upload_public () { return soundcloud_public_checkbox.get_active (); }
+ bool upload_open () { return soundcloud_open_checkbox.get_active (); }
+ void cancel () { soundcloud_cancel = true; }
+
+ private:
+ Gtk::Table sc_table;
+ Gtk::CheckButton soundcloud_public_checkbox;
+ Gtk::Label soundcloud_username_label;
+ Gtk::Entry soundcloud_username_entry;
+ Gtk::Label soundcloud_password_label;
+ Gtk::Entry soundcloud_password_entry;
+ Gtk::CheckButton soundcloud_open_checkbox;
+ bool soundcloud_cancel;
+ Gtk::ProgressBar progress_bar;
+
+};
+
diff --git a/gtk2_ardour/system_exec.cc b/gtk2_ardour/system_exec.cc
deleted file mode 100644
index 59f3647e51..0000000000
--- a/gtk2_ardour/system_exec.cc
+++ /dev/null
@@ -1,808 +0,0 @@
-/*
- Copyright (C) 2010 Paul Davis
- Copyright 2005-2008 Lennart Poettering
- Author: Robin Gareus <robin@gareus.org>
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <assert.h>
-#include <dirent.h>
-
-#ifdef __WIN32__
-#include <windows.h>
-#else
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#endif
-
-
-#include "system_exec.h"
-
-using namespace std;
-void * interposer_thread (void *arg);
-
-static void close_fd (int& fd) { if (fd >= 0) ::close (fd); fd = -1; }
-
-#ifndef __WIN32__
-/*
- * This function was part of libasyncns.
- * LGPL v2.1
- * Copyright 2005-2008 Lennart Poettering
- */
-static int close_allv(const int except_fds[]) {
- struct rlimit rl;
- int fd;
-
-#ifdef __linux__
-
- DIR *d;
-
- assert(except_fds);
-
- if ((d = opendir("/proc/self/fd"))) {
- struct dirent *de;
-
- while ((de = readdir(d))) {
- int found;
- long l;
- char *e = NULL;
- int i;
-
- if (de->d_name[0] == '.')
- continue;
-
- errno = 0;
- l = strtol(de->d_name, &e, 10);
- if (errno != 0 || !e || *e) {
- closedir(d);
- errno = EINVAL;
- return -1;
- }
-
- fd = (int) l;
-
- if ((long) fd != l) {
- closedir(d);
- errno = EINVAL;
- return -1;
- }
-
- if (fd < 3)
- continue;
-
- if (fd == dirfd(d))
- continue;
-
- found = 0;
- for (i = 0; except_fds[i] >= 0; i++)
- if (except_fds[i] == fd) {
- found = 1;
- break;
- }
-
- if (found) continue;
-
- if (close(fd) < 0) {
- int saved_errno;
-
- saved_errno = errno;
- closedir(d);
- errno = saved_errno;
-
- return -1;
- }
- }
-
- closedir(d);
- return 0;
- }
-
-#endif
-
- if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
- return -1;
-
- for (fd = 0; fd < (int) rl.rlim_max; fd++) {
- int i;
-
- if (fd <= 3)
- continue;
-
- for (i = 0; except_fds[i] >= 0; i++)
- if (except_fds[i] == fd)
- continue;
-
- if (close(fd) < 0 && errno != EBADF)
- return -1;
- }
-
- return 0;
-}
-#endif /* not on windows */
-
-
-SystemExec::SystemExec (std::string c, std::string a)
- : cmd(c)
-{
- pthread_mutex_init(&write_lock, NULL);
- thread_active=false;
- pid = 0;
- pin[1] = -1;
- nicelevel = 0;
- envp = NULL;
- argp = NULL;
-#ifdef __WIN32__
- stdinP[0] = stdinP[1] = INVALID_HANDLE_VALUE;
- stdoutP[0] = stdoutP[1] = INVALID_HANDLE_VALUE;
- stderrP[0] = stderrP[1] = INVALID_HANDLE_VALUE;
-#endif
- make_envp();
- make_argp(a);
-}
-
-SystemExec::SystemExec (std::string c, char **a)
- : cmd(c) , argp(a)
-{
- pthread_mutex_init(&write_lock, NULL);
- thread_active=false;
- pid = 0;
- pin[1] = -1;
- nicelevel = 0;
- envp = NULL;
-#ifdef __WIN32__
- stdinP[0] = stdinP[1] = INVALID_HANDLE_VALUE;
- stdoutP[0] = stdoutP[1] = INVALID_HANDLE_VALUE;
- stderrP[0] = stderrP[1] = INVALID_HANDLE_VALUE;
- make_wargs(a);
-#endif
- make_envp();
-}
-
-SystemExec::~SystemExec ()
-{
- terminate ();
- if (envp) {
- for (int i=0;envp[i];++i) {
- free(envp[i]);
- }
- free (envp);
- }
- if (argp) {
- for (int i=0;argp[i];++i) {
- free(argp[i]);
- }
- free (argp);
- }
-#ifdef __WIN32__
- if (w_args) free(w_args);
-#endif
- pthread_mutex_destroy(&write_lock);
-}
-
-void *
-interposer_thread (void *arg) {
- SystemExec *sex = static_cast<SystemExec *>(arg);
- sex->output_interposer();
- pthread_exit(0);
- return 0;
-}
-
-#ifdef __WIN32__ /* Windows Process */
-
-/* HELPER FUNCTIONS */
-
-static void create_pipe (HANDLE *pipe, bool in) {
- SECURITY_ATTRIBUTES secAtt = { sizeof( SECURITY_ATTRIBUTES ), NULL, TRUE };
- HANDLE tmpHandle;
- if (in) {
- if (!CreatePipe(&pipe[0], &tmpHandle, &secAtt, 1024 * 1024)) return;
- if (!DuplicateHandle(GetCurrentProcess(), tmpHandle, GetCurrentProcess(), &pipe[1], 0, FALSE, DUPLICATE_SAME_ACCESS)) return;
- } else {
- if (!CreatePipe(&tmpHandle, &pipe[1], &secAtt, 1024 * 1024)) return;
- if (!DuplicateHandle(GetCurrentProcess(), tmpHandle, GetCurrentProcess(), &pipe[0], 0, FALSE, DUPLICATE_SAME_ACCESS)) return;
- }
- CloseHandle(tmpHandle);
-}
-
-static void destroy_pipe (HANDLE pipe[2]) {
- if (pipe[0] != INVALID_HANDLE_VALUE) {
- CloseHandle(pipe[0]);
- pipe[0] = INVALID_HANDLE_VALUE;
- }
- if (pipe[1] != INVALID_HANDLE_VALUE) {
- CloseHandle(pipe[1]);
- pipe[1] = INVALID_HANDLE_VALUE;
- }
-}
-
-static BOOL CALLBACK my_terminateApp(HWND hwnd, LPARAM procId)
-{
- DWORD currentProcId = 0;
- GetWindowThreadProcessId(hwnd, &currentProcId);
- if (currentProcId == (DWORD)procId)
- PostMessage(hwnd, WM_CLOSE, 0, 0);
- return TRUE;
-}
-
-/* PROCESS API */
-
-void
-SystemExec::make_envp() {
- ;/* environemt is copied over with CreateProcess(...,env=0 ,..) */
-}
-
-void
-SystemExec::make_wargs(char **a) {
- std::string wa = cmd;
- if (cmd[0] != '"' && cmd[cmd.size()] != '"' && strchr(cmd.c_str(), ' ')) { wa = "\"" + cmd + "\""; }
- std::replace(cmd.begin(), cmd.end(), '/', '\\' );
- char **tmp = a;
- while (tmp && *tmp) {
- wa.append(" \"");
- wa.append(*tmp);
- wa.append("\"");
- tmp++;
- }
- w_args = strdup(wa.c_str());
-}
-
-void
-SystemExec::make_argp(std::string args) {
- std::string wa = cmd;
- if (cmd[0] != '"' && cmd[cmd.size()] != '"' && strchr(cmd.c_str(), ' ')) { wa = "\"" + cmd + "\""; }
- std::replace(cmd.begin(), cmd.end(), '/', '\\' );
- wa.append(" ");
- wa.append(args);
- w_args = strdup(wa.c_str());
-}
-
-void
-SystemExec::terminate ()
-{
- ::pthread_mutex_lock(&write_lock);
- if (pid) {
- /* terminate */
- EnumWindows(my_terminateApp, (LPARAM)pid->dwProcessId);
- PostThreadMessage(pid->dwThreadId, WM_CLOSE, 0, 0);
-
- /* kill ! */
- TerminateProcess(pid->hProcess, 0xf291);
-
- CloseHandle(pid->hThread);
- CloseHandle(pid->hProcess);
- destroy_pipe(stdinP);
- destroy_pipe(stdoutP);
- destroy_pipe(stderrP);
- delete pid;
- pid=0;
- }
- ::pthread_mutex_unlock(&write_lock);
-}
-
-int
-SystemExec::wait (int options)
-{
- while (is_running()) {
- WaitForSingleObject(pid->hProcess, INFINITE);
- Sleep(20);
- }
- return 0;
-}
-
-bool
-SystemExec::is_running ()
-{
- return pid?true:false;
-}
-
-int
-SystemExec::start (int stderr_mode)
-{
- char* working_dir = 0;
-
- if (pid) { return 0; }
-
- pid = new PROCESS_INFORMATION;
- memset(pid, 0, sizeof(PROCESS_INFORMATION));
-
- create_pipe(stdinP, true);
- create_pipe(stdoutP, false);
-
- if (stderr_mode == 2) {
- /* merge stout & stderr */
- DuplicateHandle(GetCurrentProcess(), stdoutP[1], GetCurrentProcess(), &stderrP[1], 0, TRUE, DUPLICATE_SAME_ACCESS);
- } else if (stderr_mode == 1) {
- //TODO read/flush this pipe or close it...
- create_pipe(stderrP, false);
- } else {
- //TODO: keep stderr of this process mode.
- }
-
- bool success = false;
- STARTUPINFOA startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
- (unsigned long)CW_USEDEFAULT, (unsigned long)CW_USEDEFAULT,
- (unsigned long)CW_USEDEFAULT, (unsigned long)CW_USEDEFAULT,
- 0, 0, 0,
- STARTF_USESTDHANDLES,
- 0, 0, 0,
- stdinP[0], stdoutP[1], stderrP[1]
- };
-
- success = CreateProcess(0, w_args,
- 0, 0, /* bInheritHandles = */ TRUE,
- (CREATE_NO_WINDOW&0) | CREATE_UNICODE_ENVIRONMENT | (0&CREATE_NEW_CONSOLE),
- /*env = */ 0,
- working_dir,
- &startupInfo, pid);
-
- if (stdinP[0] != INVALID_HANDLE_VALUE) {
- CloseHandle(stdinP[0]);
- stdinP[0] = INVALID_HANDLE_VALUE;
- }
- if (stdoutP[1] != INVALID_HANDLE_VALUE) {
- CloseHandle(stdoutP[1]);
- stdoutP[1] = INVALID_HANDLE_VALUE;
- }
- if (stderrP[1] != INVALID_HANDLE_VALUE) {
- CloseHandle(stderrP[1]);
- stderrP[1] = INVALID_HANDLE_VALUE;
- }
-
- if (!success) {
- CloseHandle(pid->hThread);
- CloseHandle(pid->hProcess);
- destroy_pipe(stdinP);
- destroy_pipe(stdoutP);
- destroy_pipe(stderrP);
- delete pid;
- pid=0;
- return -1;
- }
-
- int rv = pthread_create(&thread_id_tt, NULL, interposer_thread, this);
- thread_active=true;
- if (rv) {
- thread_active=false;
- terminate();
- return -2;
- }
- Sleep(20);
- return 0;
-}
-
-void
-SystemExec::output_interposer()
-{
- DWORD bytesRead = 0;
- char data[BUFSIZ];
-#if 0 // untested code to set up nonblocking
- unsigned long l = 1;
- ioctlsocket(stdoutP[0], FIONBIO, &l);
-#endif
- while(1) {
-#if 0 // for non-blocking pipes..
- DWORD bytesAvail = 0;
- PeekNamedPipe(stdoutP[0], 0, 0, 0, &bytesAvail, 0);
- if (bytesAvail < 1) {Sleep(500); printf("N/A\n"); continue;}
-#endif
- if (stdoutP[0] == INVALID_HANDLE_VALUE) break;
- if (!ReadFile(stdoutP[0], data, BUFSIZ, &bytesRead, 0)) break;
- if (bytesRead < 1) continue; /* actually not needed; but this is safe. */
- data[bytesRead] = 0;
- ReadStdout(data, bytesRead);/* EMIT SIGNAL */
- }
- Terminated();/* EMIT SIGNAL */
-}
-
-void
-SystemExec::close_stdin()
-{
- if (stdinP[0]!= INVALID_HANDLE_VALUE) FlushFileBuffers(stdinP[0]);
- if (stdinP[1]!= INVALID_HANDLE_VALUE) FlushFileBuffers(stdinP[1]);
- Sleep(200);
- destroy_pipe(stdinP);
-}
-
-int
-SystemExec::write_to_stdin(std::string d, size_t len)
-{
- const char *data;
- DWORD r,c;
-
- ::pthread_mutex_lock(&write_lock);
-
- data=d.c_str();
- if (len == 0) {
- len=(d.length());
- }
- c=0;
- while (c < len) {
- if (!WriteFile(stdinP[1], data+c, len-c, &r, NULL)) {
- if (GetLastError() == 0xE8 /*NT_STATUS_INVALID_USER_BUFFER*/) {
- Sleep(100);
- continue;
- } else {
- fprintf(stderr, "SYSTEM-EXEC: stdin write error.\n");
- break;
- }
- }
- c += r;
- }
- ::pthread_mutex_unlock(&write_lock);
- return c;
-}
-
-
-/* end windows process */
-#else
-/* UNIX/POSIX process */
-
-extern char **environ;
-void
-SystemExec::make_envp() {
- int i=0;
- envp = (char **) calloc(1, sizeof(char*));
- /* copy current environment */
- for (i=0;environ[i];++i) {
- envp[i] = strdup(environ[i]);
- envp = (char **) realloc(envp, (i+2) * sizeof(char*));
- }
- envp[i] = 0;
-}
-
-void
-SystemExec::make_argp(std::string args) {
- int argn = 1;
- char *cp1;
- char *cp2;
-
- char *carg = strdup(args.c_str());
-
- argp = (char **) malloc((argn + 1) * sizeof(char *));
- if (argp == (char **) 0) {
- free(carg);
- return; // FATAL
- }
-
- argp[0] = strdup(cmd.c_str());
-
- /* TODO: quotations and escapes
- * http://stackoverflow.com/questions/1511797/convert-string-to-argv-in-c
- *
- * It's actually not needed. All relevant invocations specify 'argp' directly.
- * Only 'xjadeo -L -R' uses this function and that uses neither quotations
- * nor arguments with white-space.
- */
- for (cp1 = cp2 = carg; *cp2 != '\0'; ++cp2) {
- if (*cp2 == ' ') {
- *cp2 = '\0';
- argp[argn++] = strdup(cp1);
- cp1 = cp2 + 1;
- argp = (char **) realloc(argp, (argn + 1) * sizeof(char *));
- }
- }
- if (cp2 != cp1) {
- argp[argn++] = strdup(cp1);
- argp = (char **) realloc(argp, (argn + 1) * sizeof(char *));
- }
- argp[argn] = (char *) 0;
- free(carg);
-}
-
-
-
-void
-SystemExec::terminate ()
-{
- ::pthread_mutex_lock(&write_lock);
-
- /* close stdin in an attempt to get the child to exit cleanly.
- */
-
- close_stdin();
-
- if (pid) {
- ::usleep(50000);
- sched_yield();
- wait(WNOHANG);
- }
-
- /* if pid is non-zero, the child task is still executing (i.e. it did
- * not exit in response to stdin being closed). try to kill it.
- */
-
- if (pid) {
- ::kill(pid, SIGTERM);
- ::usleep(50000);
- sched_yield();
- wait(WNOHANG);
- }
-
- /* if pid is non-zero, the child task is STILL executing after being
- * sent SIGTERM. Act tough ... send SIGKILL
- */
-
- if (pid) {
- ::fprintf(stderr, "Process is still running! trying SIGKILL\n");
- ::kill(pid, SIGKILL);
- }
-
- wait();
- if (thread_active) pthread_join(thread_id_tt, NULL);
- thread_active = false;
- ::pthread_mutex_unlock(&write_lock);
-}
-
-int
-SystemExec::wait (int options)
-{
- int status=0;
- int ret;
-
- if (pid==0) return -1;
-
- ret = waitpid (pid, &status, options);
-
- if (ret == pid) {
- if (WEXITSTATUS(status) || WIFSIGNALED(status)) {
- pid=0;
- }
- } else {
- if (ret != 0) {
- if (errno == ECHILD) {
- /* no currently running children, reset pid */
- pid=0;
- }
- } /* else the process is still running */
- }
- return status;
-}
-
-bool
-SystemExec::is_running ()
-{
- int status=0;
- if (pid==0) return false;
- if (::waitpid(pid, &status, WNOHANG)==0) return true;
- return false;
-}
-
-int
-SystemExec::start (int stderr_mode)
-{
- if (is_running()) {
- return 0; // mmh what to return here?
- }
- int r;
-
- if (::pipe(pin) < 0 || ::pipe(pout) < 0 || ::pipe(pok) < 0) {
- /* Something unexpected went wrong creating a pipe. */
- return -1;
- }
-
- r = ::fork();
- if (r < 0) {
- /* failed to fork */
- return -2;
- }
-
- if (r > 0) {
- /* main */
- pid=r;
-
- /* check if execve was successful. */
- close_fd(pok[1]);
- char buf;
- for ( ;; ) {
- ssize_t n = ::read(pok[0], &buf, 1 );
- if ( n==1 ) {
- /* child process returned from execve */
- pid=0;
- close_fd(pok[0]);
- close_fd(pin[1]);
- close_fd(pin[0]);
- close_fd(pout[1]);
- close_fd(pout[0]);
- pin[1] = -1;
- return -3;
- } else if ( n==-1 ) {
- if ( errno==EAGAIN || errno==EINTR )
- continue;
- }
- break;
- }
- close_fd(pok[0]);
- /* child started successfully */
-
-#if 0
-/* use fork for output-interposer
- * it will run in a separated process
- */
- /* catch stdout thread */
- r = ::fork();
- if (r < 0) {
- // failed to fork
- terminate();
- return -2;
- }
- if (r == 0) {
- /* 2nd child process - catch stdout */
- close_fd(pin[1]);
- close_fd(pout[1]);
- output_interposer();
- exit(0);
- }
- close_fd(pout[1]);
- close_fd(pin[0]);
- close_fd(pout[0]);
-#else /* use pthread */
- close_fd(pout[1]);
- close_fd(pin[0]);
- int rv = pthread_create(&thread_id_tt, NULL, interposer_thread, this);
-
- thread_active=true;
- if (rv) {
- thread_active=false;
- terminate();
- return -2;
- }
-#endif
- return 0; /* all systems go - return to main */
- }
-
- /* child process - exec external process */
- close_fd(pok[0]);
- ::fcntl(pok[1], F_SETFD, FD_CLOEXEC);
-
- close_fd(pin[1]);
- if (pin[0] != STDIN_FILENO) {
- ::dup2(pin[0], STDIN_FILENO);
- }
- close_fd(pin[0]);
- close_fd(pout[0]);
- if (pout[1] != STDOUT_FILENO) {
- ::dup2(pout[1], STDOUT_FILENO);
- }
-
- if (stderr_mode == 2) {
- /* merge STDERR into output */
- if (pout[1] != STDERR_FILENO) {
- ::dup2(pout[1], STDERR_FILENO);
- }
- } else if (stderr_mode == 1) {
- /* ignore STDERR */
- ::close(STDERR_FILENO);
- } else {
- /* keep STDERR */
- }
-
- if (pout[1] != STDOUT_FILENO && pout[1] != STDERR_FILENO) {
- close_fd(pout[1]);
- }
-
- if (nicelevel !=0) {
- ::nice(nicelevel);
- }
-
-#if 0
- /* chdir to executable dir */
- char *directory;
- directory = strdup(cmd.c_str());
- if (strrchr(directory, '/') != (char *) 0) {
- ::chdir(directory);
- }
- free(directory);
-#endif
-
-#ifdef HAVE_SIGSET
- sigset(SIGPIPE, SIG_DFL);
-#else
- signal(SIGPIPE, SIG_DFL);
-#endif
-
- int good_fds[1] = { -1 };
- close_allv(good_fds);
-
- ::execve(argp[0], argp, envp);
- /* if we reach here something went wrong.. */
- char buf = 0;
- (void) ::write(pok[1], &buf, 1 );
- close_fd(pok[1]);
- exit(-1);
- return -1;
-}
-
-void
-SystemExec::output_interposer()
-{
- int rfd=pout[0];
- char buf[BUFSIZ];
- ssize_t r;
- unsigned long l = 1;
-
- ioctl(rfd, FIONBIO, &l); // set non-blocking I/O
-
- for (;fcntl(rfd, F_GETFL)!=-1;) {
- r = read(rfd, buf, sizeof(buf));
- if (r < 0 && (errno == EINTR || errno == EAGAIN)) {
- ::usleep(1000);
- continue;
- }
- if (r <= 0) {
- break;
- }
- buf[r]=0;
- std::string rv = std::string(buf,r); // TODO: check allocation strategy
- ReadStdout(rv, r);/* EMIT SIGNAL */
- }
- Terminated();/* EMIT SIGNAL */
-}
-
-void
-SystemExec::close_stdin()
-{
- if (pin[1]<0) return;
- close_fd(pin[0]);
- close_fd(pin[1]);
- close_fd(pout[0]);
- close_fd(pout[1]);
-}
-
-int
-SystemExec::write_to_stdin(std::string d, size_t len)
-{
- const char *data;
- ssize_t r;
- size_t c;
- ::pthread_mutex_lock(&write_lock);
-
- data=d.c_str();
- if (len == 0) {
- len=(d.length());
- }
- c=0;
- while (c < len) {
- for (;;) {
- r=::write(pin[1], data+c, len-c);
- if (r < 0 && (errno == EINTR || errno == EAGAIN)) {
- sleep(1);
- continue;
- }
- if ((size_t) r != (len-c)) {
- ::pthread_mutex_unlock(&write_lock);
- return c;
- }
- break;
- }
- c += r;
- }
- fsync(pin[1]);
- ::pthread_mutex_unlock(&write_lock);
- return c;
-}
-
-#endif // end UNIX process
diff --git a/gtk2_ardour/system_exec.h b/gtk2_ardour/system_exec.h
deleted file mode 100644
index cf8518f547..0000000000
--- a/gtk2_ardour/system_exec.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- Copyright (C) 2010 Paul Davis
- Author: Robin Gareus <robin@gareus.org>
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-#ifndef __ardour_system_exec_h__
-#define __ardour_system_exec_h__
-
-#ifndef STDIN_FILENO
-#define STDIN_FILENO 0
-#endif
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO 1
-#endif
-#ifndef STDERR_FILENO
-#define STDERR_FILENO 2
-#endif
-
-#include <string>
-#include <pthread.h>
-#include <signal.h>
-#ifdef NOPBD /* outside ardour */
-#include <sigc++/bind.h>
-#include <sigc++/signal.h>
-#else
-#include <pbd/signals.h>
-#endif
-
-/** @class: SystemExec
- * @brief execute an external command
- *
- * This class allows launche an external command-line application
- * opening a full-duplex connection to its standard I/O.
- *
- * In Ardour context it is used to launch xjadeo and ffmpeg.
- *
- * The \ref write_to_stdin function provides for injecting data into STDIN
- * of the child-application while output of the program to STDOUT/STDERR is
- * forwarded using the \ref ReadStdout signal.
- * \ref Terminated is sent if the child application exits.
- *
- */
-class SystemExec
-{
- public:
- /** prepare execution of a program with 'execve'
- *
- * This function takes over the existing environment variable and provides
- * an easy way to speciy command-line arguments for the new process.
- *
- * Note: The argument parser does not interpret quotation-marks and splits
- * arugments on whitespace. The argument string can be empty.
- * The alternative constructor below allows to specify quoted parameters
- * incl. whitespace.
- *
- * @param c program pathname that identifies the new process image file.
- * @param a string of commandline-arguments to be passed to the new program.
- */
- SystemExec (std::string c, std::string a = "");
- /** similar to \ref SystemExec but allows to specify custom arguments
- *
- * @param c program pathname that identifies the new process image file.
- * @param a array of argument strings passed to the new program as 'argv'.
- * it must be terminated by a null pointer (see the 'evecve'
- * POSIX-C documentation for more information)
- * The array must be dynamically allocated using malloc or strdup.
- * Unless they're NULL, the array itself and each of its content
- * memory is freed() in the destructor.
- *
- */
- SystemExec (std::string c, char ** a);
- virtual ~SystemExec ();
-
- /** fork and execute the given program
- *
- * @param stderr_mode select what to do with program's standard error
- * output:
- * '0': keep STDERR; mix it with parent-process' STDERR
- * '1': ignore STDERR of child-program
- * '2': merge STDERR into STDOUT and send it with the
- * ReadStdout signal.
- * @return If the process is already running or was launched successfully
- * the function returns zero (0). A negative number indicates an error.
- */
- int start (int stderr_mode = 1);
- /** kill running child-process
- *
- * if a child process exists trt to shut it down by closing its STDIN.
- * if the program dies not react try SIGTERM and eventually SIGKILL
- */
- void terminate ();
- /** check if the child programm is (still) running.
- *
- * This function calls waitpid(WNOHANG) to check the state of the
- * child-process.
- * @return true if the program is (still) running.
- */
- bool is_running ();
- /** call the waitpid system-call with the pid of the child-program
- *
- * Basically what \ref terminate uses internally.
- *
- * This function is only useful if you want to control application
- * termination yourself (eg timeouts or progress-dialog).
- * @param option flags - see waitpid manual
- * @return status info from waitpid call (not waitpid's return value)
- * or -1 if the child-program is not running.
- */
- int wait (int options=0);
- /** closes both STDIN and STDOUT connections to/from
- * the child-program.
- * With the output-interposer thread gone, the program
- * should terminate.
- * used by \ref terminate()
- */
- void close_stdin ();
- /** write into child-program's STDIN
- * @param d data to write
- * @param len length of data to write, if it is 0 (zero), d.length() is
- * used to determine the number of bytes to transmit.
- * @return number of bytes written.
- */
- int write_to_stdin (std::string d, size_t len=0);
-
- /** The ReadStdout signal is emitted when the application writes to STDOUT.
- * it passes the written data and its length in bytes as arguments to the bound
- * slot(s).
- */
-#ifdef NOPBD /* outside ardour */
- sigc::signal<void, std::string,size_t> ReadStdout;
-#else
- PBD::Signal2<void, std::string,size_t> ReadStdout;
-#endif
-
- /** The Terminated signal is emitted when application terminates. */
-#ifdef NOPBD /* outside ardour */
- sigc::signal<void> Terminated;
-#else
- PBD::Signal0<void> Terminated;
-#endif
-
- /** interposer to emit signal for writes to STDOUT/ERR.
- *
- * Thread that reads the stdout of the forked
- * process and signal-sends it to the main thread.
- * It also emits the Terminated() signal once
- * the the forked process closes it's stdout.
- *
- * Note: it's actually 'private' function but used
- * by the internal pthread, which only has a pointer
- * to this instance and thus can only access public fn.
- */
- void output_interposer ();
-
- protected:
- std::string cmd; ///< path to command - set when creating the class
- int nicelevel; ///< process nice level - defaults to 0
-
- void make_argp(std::string);
- void make_envp();
-
- char **argp;
- char **envp;
-
- private:
-#ifdef __WIN32__
- PROCESS_INFORMATION *pid;
- HANDLE stdinP[2];
- HANDLE stdoutP[2];
- HANDLE stderrP[2];
- char *w_args;
- void make_wargs(char **);
-#else
- pid_t pid;
-#endif
- pthread_mutex_t write_lock;
-
- int fdin; ///< file-descriptor for writing to child's STDIN. This variable is identical to pin[1] but also used as status check if the stdin pipe is open: <0 means closed.
- int pok[2];
- int pin[2];
- int pout[2];
-
- pthread_t thread_id_tt;
- bool thread_active;
-};
-
-#endif /* __ardour_system_exec_h__ */
diff --git a/gtk2_ardour/transcode_ffmpeg.h b/gtk2_ardour/transcode_ffmpeg.h
index 61267ac853..e25a68da91 100644
--- a/gtk2_ardour/transcode_ffmpeg.h
+++ b/gtk2_ardour/transcode_ffmpeg.h
@@ -22,7 +22,7 @@
#include <string>
#include "ardour/types.h"
-#include "system_exec.h"
+#include "pbd/system_exec.h"
/** @class TranscodeFfmpeg
diff --git a/gtk2_ardour/video_monitor.h b/gtk2_ardour/video_monitor.h
index 59264fa012..80273cf5e3 100644
--- a/gtk2_ardour/video_monitor.h
+++ b/gtk2_ardour/video_monitor.h
@@ -26,7 +26,7 @@
#include "ardour/types.h"
#include "ardour/session.h"
#include "ardour/session_handle.h"
-#include "system_exec.h"
+#include "pbd/system_exec.h"
namespace ARDOUR {
class Session;
diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript
index 9883fa49e2..aac1f3a49b 100644
--- a/gtk2_ardour/wscript
+++ b/gtk2_ardour/wscript
@@ -211,6 +211,7 @@ gtk2_ardour_sources = [
'shuttle_control.cc',
'simpleline.cc',
'simplerect.cc',
+ 'soundcloud_export_selector.cc',
'splash.cc',
'speaker_dialog.cc',
'startup.cc',
@@ -245,7 +246,6 @@ gtk2_ardour_sources = [
'add_video_dialog.cc',
'editor_videotimeline.cc',
'video_timeline.cc',
- 'system_exec.cc',
'video_monitor.cc',
'transcode_ffmpeg.cc',
'transcode_video_dialog.cc',