env=$HOME/osx-environment
sdk=$HOME/SDK
-export CPPFLAGS= LDFLAGS="-L$base/lib -L$env/lib -isysroot $sdk/MacOSX10.9.sdk -arch x86_64"
-export LINKFLAGS="-L$base/lib -L$env/lib -isysroot $sdk/MacOSX10.9.sdk -arch x86_64"
+export CPPFLAGS= LDFLAGS="-L$base/lib -L$env/64/lib -isysroot $sdk/MacOSX10.9.sdk -arch x86_64"
+export LINKFLAGS="-L$base/lib -L$env/64/lib -isysroot $sdk/MacOSX10.9.sdk -arch x86_64"
export MACOSX_DEPLOYMENT_TARGET=10.9
-export CXXFLAGS="-I$base/include -I$env/include -isysroot $sdk/MacOSX10.9.sdk -arch x86_64"
-export CFLAGS="-I$base/include -I$env/include -isysroot $sdk/MacOSX10.9.sdk -arch x86_64"
+export CXXFLAGS="-I$base/include -I$env/64/include -isysroot $sdk/MacOSX10.9.sdk -arch x86_64"
+export CFLAGS="-I$base/include -I$env/64/include -isysroot $sdk/MacOSX10.9.sdk -arch x86_64"
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$base/lib:$env/64/lib
export PATH=$env/64/bin:$PATH
export PKG_CONFIG_PATH=$env/64/lib/pkgconfig:$base/lib/pkgconfig
--- /dev/null
+user=cah
+container=371eb645f2c3
+src=/home/cah/src/dcpomatic-windows
+
+docker exec -u $user -e src=$src -i -t $container /bin/bash -c 'export CPPFLAGS= LD=x86_64-w64-mingw32.shared-ld PKG_CONFIG_LIBDIR=/opt/mxe/usr/x86_64-w64-mingw32.shared/lib/pkgconfig CC=x86_64-w64-mingw32.shared-gcc WINRC=x86_64-w64-mingw32.shared-windres RANLIB=x86_64-w64-mingw32.shared-ranlib CXXFLAGS="-I/opt/mxe/usr/x86_64-w64-mingw32.shared/include -I$src/include" CXX=x86_64-w64-mingw32.shared-g++ LDFLAGS="-L/opt/mxe/usr/x86_64-w64-mingw32.shared/lib -L$src/lib" PKG_CONFIG_PATH=$src/lib/pkgconfig:$src/bin/pkgconfig PATH=/opt/mxe/usr/x86_64-w64-mingw32.shared/bin:/opt/mxe/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:$srcbin LINKFLAGS="-L/opt/mxe/usr/x86_64-w64-mingw32.shared/lib -L$src/lib" ; cd $src/src/dcpomatic; ./waf'
+
--- /dev/null
+user=cah
+container=371eb645f2c3
+src=/home/cah/src/dcpomatic-windows
+
+docker exec -u $user -e src=$src -i -t $container /bin/bash -c 'export CPPFLAGS= LD=x86_64-w64-mingw32.shared-ld PKG_CONFIG_LIBDIR=/opt/mxe/usr/x86_64-w64-mingw32.shared/lib/pkgconfig CC=x86_64-w64-mingw32.shared-gcc WINRC=x86_64-w64-mingw32.shared-windres RANLIB=x86_64-w64-mingw32.shared-ranlib CXXFLAGS="-I/opt/mxe/usr/x86_64-w64-mingw32.shared/include -I$src/include" CXX=x86_64-w64-mingw32.shared-g++ LDFLAGS="-L/opt/mxe/usr/x86_64-w64-mingw32.shared/lib -L$src/lib" PKG_CONFIG_PATH=$src/lib/pkgconfig:$src/bin/pkgconfig PATH=/opt/mxe/usr/x86_64-w64-mingw32.shared/bin:/opt/mxe/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:$srcbin LINKFLAGS="-L/opt/mxe/usr/x86_64-w64-mingw32.shared/lib -L$src/lib" ; cd $src/src/dcpomatic; ./waf configure --target-windows --disable-tests'
+
#include <boost/filesystem.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/optional.hpp>
+#include <boost/function.hpp>
#ifdef DCPOMATIC_WINDOWS
#define WEXITSTATUS(w) (w)
boost::optional<std::string> _model;
};
+void disk_write_finished ();
+
#endif
}
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
+#include <boost/function.hpp>
#ifdef DCPOMATIC_DISK
#include <boost/dll/runtime_symbol_info.hpp>
#endif
using std::runtime_error;
using boost::shared_ptr;
using boost::optional;
+using boost::function;
/** @param s Number of seconds to sleep for */
void
bool
-Drive::unmount ()
+Drive::unmount ()
{
BOOST_FOREACH (boost::filesystem::path i, _mount_points) {
int const r = umount(i.string().c_str());
return p;
}
+
+void
+disk_write_finished ()
+{
+
+}
+
using std::cerr;
using std::cout;
using std::runtime_error;
+using std::map;
using boost::shared_ptr;
using boost::optional;
+using boost::function;
/** @param s Number of seconds to sleep for */
void
}
#ifdef DCPOMATIC_DISK
+/* Note: this isn't actually used at the moment as the disk writer is started as a service */
boost::filesystem::path
disk_writer_path ()
{
return whole_media;
}
-static bool
-is_mounted (CFDictionaryRef& description)
+static optional<boost::filesystem::path>
+mount_point (CFDictionaryRef& description)
{
CFURLRef volume_path_key = (CFURLRef) CFDictionaryGetValue (description, kDADiskDescriptionVolumePathKey);
char mount_path_buffer[1024];
- return CFURLGetFileSystemRepresentation(volume_path_key, false, (UInt8 *) mount_path_buffer, sizeof(mount_path_buffer));
+ if (!CFURLGetFileSystemRepresentation(volume_path_key, false, (UInt8 *) mount_path_buffer, sizeof(mount_path_buffer))) {
+ return boost::optional<boost::filesystem::path>();
+ }
+ return boost::filesystem::path(mount_path_buffer);
}
/* Here follows some rather intricate and (probably) fragile code to find the list of available
* "real" drives on macOS that we might want to write a DCP to.
*
- * We use the Disk Arbitration framework to give us a series of devices (/dev/disk0, /dev/disk1,
- * /dev/disk1s1 and so on) and we use the API to gather useful information about these devices into
+ * We use the Disk Arbitration framework to give us a series of mount_points (/dev/disk0, /dev/disk1,
+ * /dev/disk1s1 and so on) and we use the API to gather useful information about these mount_points into
* a vector of Disk structs.
*
* Then we read the Disks that we found and try to derive a list of drives that we should offer to the
* user, with details of whether those drives are currently mounted or not.
*
- * At the basic level we find the "disk"-level devices, looking at whether any of their partitions are mounted.
+ * At the basic level we find the "disk"-level mount_points, looking at whether any of their partitions are mounted.
*
* This is complicated enormously by recent-ish macOS versions' habit of making `synthesized' volumes which
* reflect data in `real' partitions. So, for example, we might have a real (physical) drive /dev/disk2 with
struct Disk
{
- string device;
+ string mount_point;
optional<string> vendor;
optional<string> model;
bool real;
string prt;
bool whole;
- bool mounted;
+ vector<boost::filesystem::path> mount_points;
unsigned long size;
};
Disk this_disk;
- this_disk.device = string("/dev/") + bsd_name;
+ this_disk.mount_point = string("/dev/") + bsd_name;
CFDictionaryRef description = DADiskCopyDescription (disk);
this_disk.real = media_path->real;
this_disk.prt = media_path->prt;
this_disk.whole = is_whole_drive (disk);
- this_disk.mounted = is_mounted (description);
- LOG_DISK("%1 prt %2 whole %3 mounted %4", this_disk.real ? "Real" : "Synth", this_disk.prt, this_disk.whole ? "whole" : "part", this_disk.mounted ? "mounted" : "unmounted");
+ optional<boost::filesystem::path> mp = mount_point (description);
+ if (mp) {
+ this_disk.mount_points.push_back (*mp);
+ }
+
+ LOG_DISK(
+ "%1 prt %2 whole %3 mounted %4",
+ this_disk.real ? "Real" : "Synth",
+ this_disk.prt,
+ this_disk.whole ? "whole" : "part",
+ mp ? ("mounted at " + mp->string()) : "unmounted"
+ );
CFNumberGetValue ((CFNumberRef) CFDictionaryGetValue (description, kDADiskDescriptionMediaSizeKey), kCFNumberLongType, &this_disk.size);
CFRelease (description);
}
vector<Drive>
-get_drives ()
+Drive::get ()
{
using namespace boost::algorithm;
vector<Disk> disks;
continue;
}
BOOST_FOREACH (Disk& j, disks) {
- if (j.mounted && starts_with(j.device, i.device)) {
- LOG_DISK("Marking %1 as mounted because %2 is", i.device, j.device);
- i.mounted = true;
+ if (!j.mount_points.empty() && starts_with(j.mount_point, i.mount_point)) {
+ LOG_DISK("Marking %1 as mounted because %2 is", i.mount_point, j.mount_point);
+ std::copy(j.mount_points.begin(), j.mount_points.end(), back_inserter(i.mount_points));
}
}
}
- /* Make a list of the PRT codes of mounted, synthesized disks */
- vector<string> mounted_synths;
+ /* Make a map of the PRT codes and mount points of mounted, synthesized disks */
+ map<string, vector<boost::filesystem::path> > mounted_synths;
BOOST_FOREACH (Disk& i, disks) {
- if (!i.real && i.mounted) {
- LOG_DISK("Found a mounted synth %1 with %2", i.device, i.prt);
- mounted_synths.push_back (i.prt);
+ if (!i.real && !i.mount_points.empty()) {
+ LOG_DISK("Found a mounted synth %1 with %2", i.mount_point, i.prt);
+ mounted_synths[i.prt] = i.mount_points;
}
}
/* Mark containers of those mounted synths as themselves mounted */
BOOST_FOREACH (Disk& i, disks) {
- if (i.real && find(mounted_synths.begin(), mounted_synths.end(), i.prt) != mounted_synths.end()) {
- LOG_DISK("Marking %1 (%2) as mounted because it contains a mounted synth", i.device, i.prt);
- i.mounted = true;
+ if (i.real) {
+ map<string, vector<boost::filesystem::path> >::const_iterator j = mounted_synths.find(i.prt);
+ if (j != mounted_synths.end()) {
+ LOG_DISK("Marking %1 (%2) as mounted because it contains a mounted synth", i.mount_point, i.prt);
+ std::copy(j->second.begin(), j->second.end(), back_inserter(i.mount_points));
+ }
}
}
BOOST_FOREACH (Disk& i, disks) {
if (i.whole) {
/* A whole disk that is not a container for a mounted synth */
- LOG_DISK("Adding drive: %1 %2 %3 %4 %5", i.device, i.size, i.mounted ? "mounted" : "unmounted", i.vendor.get_value_or("[none]"), i.model.get_value_or("[none]"));
- drives.push_back(Drive(i.device, i.size, i.mounted, i.vendor, i.model));
+ drives.push_back(Drive(i.mount_point, i.mount_points, i.size, i.vendor, i.model));
+ LOG_DISK_NC(drives.back().log_summary());
}
}
return drives;
return p;
}
+
+void done_callback(DADiskRef disk, DADissenterRef dissenter, void* context)
+{
+ LOG_DISK_NC("Unmount finished");
+ bool* success = reinterpret_cast<bool*> (context);
+ if (dissenter) {
+ LOG_DISK("Error: %1", DADissenterGetStatus(dissenter));
+ *success = false;
+ } else {
+ LOG_DISK_NC("Successful");
+ *success = true;
+ }
+}
+
+
bool
-unmount_device (string device)
+Drive::unmount ()
+{
+ LOG_DISK_NC("Unmount operation started");
+
+ DASessionRef session = DASessionCreate(kCFAllocatorDefault);
+ if (!session) {
+ return false;
+ }
+
+ DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, _device.c_str());
+ if (!disk) {
+ return false;
+ }
+ LOG_DISK("Requesting unmount of %1 from %2", _device, thread_id());
+ bool success = false;
+ DADiskUnmount(disk, kDADiskUnmountOptionWhole, &done_callback, &success);
+ CFRelease (disk);
+
+ CFRunLoopRef run_loop = CFRunLoopGetCurrent ();
+ DASessionScheduleWithRunLoop (session, run_loop, kCFRunLoopDefaultMode);
+ CFRunLoopStop (run_loop);
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, 0);
+ CFRelease(session);
+
+ LOG_DISK_NC("End of unmount");
+ return success;
+}
+
+
+void
+disk_write_finished ()
{
- int const r = umount(device.c_str());
- LOG_DISK("Tried to unmount %1 and got %2 and %3", device, r, errno);
- return r == 0;
}
+
#include <winioctl.h>
#include <ntdddisk.h>
#include <setupapi.h>
+#include <fileapi.h>
#undef DATADIR
#include <shlwapi.h>
#include <shellapi.h>
#include <fcntl.h>
#include <fstream>
+#include <map>
#include "i18n.h"
using std::cerr;
using std::cout;
using std::runtime_error;
+using std::map;
using boost::shared_ptr;
using boost::optional;
+static std::vector<pair<HANDLE, string> > locked_volumes;
+
/** @param s Number of seconds to sleep for */
void
dcpomatic_sleep_seconds (int s)
return device_number.DeviceNumber;
}
+typedef map<int, vector<boost::filesystem::path> > MountPoints;
+
/** Take a volume path (with a trailing \) and add any disk numbers related to that volume
* to @ref disks.
*/
static void
-add_volume_disk_number (wchar_t* volume, vector<int>& disks)
+add_volume_mount_points (wchar_t* volume, MountPoints& mount_points)
{
+ LOG_DISK("Looking at %1", wchar_to_utf8(volume));
+
+ wchar_t volume_path_names[512];
+ vector<boost::filesystem::path> mp;
+ DWORD returned;
+ if (GetVolumePathNamesForVolumeNameW(volume, volume_path_names, sizeof(volume_path_names) / sizeof(wchar_t), &returned)) {
+ wchar_t* p = volume_path_names;
+ while (*p != L'\0') {
+ mp.push_back (wchar_to_utf8(p));
+ LOG_DISK ("Found mount point %1", wchar_to_utf8(p));
+ p += wcslen(p) + 1;
+ }
+ }
+
/* Strip trailing \ */
size_t const len = wcslen (volume);
DCPOMATIC_ASSERT (len > 0);
return;
}
DCPOMATIC_ASSERT (extents.NumberOfDiskExtents == 1);
- return disks.push_back (extents.Extents[0].DiskNumber);
+
+ mount_points[extents.Extents[0].DiskNumber] = mp;
}
-/* Return a list of disk numbers that contain volumes; i.e. a list of disk numbers that should
- * not be offered as targets to write to as they are "mounted" (whatever that means on Windows).
- */
-vector<int>
-disk_numbers_with_volumes ()
+MountPoints
+find_mount_points ()
{
- vector<int> disks;
+ MountPoints mount_points;
wchar_t volume_name[512];
HANDLE volume = FindFirstVolumeW (volume_name, sizeof(volume_name) / sizeof(wchar_t));
if (volume == INVALID_HANDLE_VALUE) {
- return disks;
+ return MountPoints();
}
- add_volume_disk_number (volume_name, disks);
+ add_volume_mount_points (volume_name, mount_points);
while (true) {
if (!FindNextVolumeW(volume, volume_name, sizeof(volume_name) / sizeof(wchar_t))) {
break;
}
- add_volume_disk_number (volume_name, disks);
+ add_volume_mount_points (volume_name, mount_points);
}
FindVolumeClose (volume);
- return disks;
+ return mount_points;
}
vector<Drive>
-get_drives ()
+Drive::get ()
{
vector<Drive> drives;
- vector<int> disks_to_ignore = disk_numbers_with_volumes ();
+ MountPoints mount_points = find_mount_points ();
/* Get a `device information set' containing information about all disks */
HDEVINFO device_info = SetupDiGetClassDevsA (&GUID_DEVICE_INTERFACE_DISK, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
&geom, sizeof(geom), &returned, 0
);
- if (r && find(disks_to_ignore.begin(), disks_to_ignore.end(), *device_number) == disks_to_ignore.end()) {
+ LOG_DISK("Having a looky through %1 locked volumes", locked_volumes.size());
+ bool locked = false;
+ for (vector<pair<HANDLE, string> >::const_iterator i = locked_volumes.begin(); i != locked_volumes.end(); ++i) {
+ if (i->second == physical_drive) {
+ locked = true;
+ }
+ }
+
+ if (r) {
uint64_t const disk_size = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector;
- drives.push_back (Drive(physical_drive, disk_size, false, friendly_name, optional<string>()));
+ drives.push_back (Drive(physical_drive, locked ? vector<boost::filesystem::path>() : mount_points[*device_number], disk_size, friendly_name, optional<string>()));
+ LOG_DISK("Added drive %1%2", drives.back().log_summary(), locked ? "(locked by us)" : "");
}
CloseHandle (device);
return drives;
}
+
+bool
+Drive::unmount ()
+{
+ LOG_DISK("Unmounting %1 with %2 mount points XXX! MMMYEAH!", _device, _mount_points.size());
+ DCPOMATIC_ASSERT (_mount_points.size() == 1);
+ string const device_name = String::compose ("\\\\.\\%1", _mount_points.front());
+ string const truncated = device_name.substr (0, device_name.length() - 1);
+ //LOG_DISK("Actually opening %1", _device);
+ //HANDLE device = CreateFileA (_device.c_str(), (GENERIC_READ | GENERIC_WRITE), FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
+ LOG_DISK("Actually opening %1", truncated);
+ HANDLE device = CreateFileA (truncated.c_str(), (GENERIC_READ | GENERIC_WRITE), FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
+ if (device == INVALID_HANDLE_VALUE) {
+ LOG_DISK("Could not open %1 for unmount (%2)", truncated, GetLastError());
+ return false;
+ }
+ DWORD returned;
+ BOOL r = DeviceIoControl (device, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &returned, 0);
+ if (!r) {
+ LOG_DISK("Unmount of %1 failed (%2)", truncated, GetLastError());
+ return false;
+ }
+
+ LOG_DISK("Unmount of %1 succeeded", _device);
+ locked_volumes.push_back (make_pair(device, _device));
+
+ return true;
+}
+
+
boost::filesystem::path
config_path ()
{
p /= "dcpomatic2";
return p;
}
+
+void
+disk_write_finished ()
+{
+ for (vector<pair<HANDLE, string> >::const_iterator i = locked_volumes.begin(); i != locked_volumes.end(); ++i) {
+ CloseHandle (i->first);
+ }
+}
+
+
if (!_nanomsg.send(DISK_WRITER_UNMOUNT "\n", 2000)) {
throw CommunicationFailedError ();
}
- if (!_nanomsg.send(drive.as_xml() + "\n", 2000)) {
+ if (!_nanomsg.send(drive.as_xml(), 2000)) {
throw CommunicationFailedError ();
}
optional<string> reply = _nanomsg.receive (2000);
}
}
-
+
DriveWipeWarningDialog* d = new DriveWipeWarningDialog (this, _drive->GetString(_drive->GetSelection()));
int const r = d->ShowModal ();
bool ok = r == wxID_OK && d->confirmed();
JobManagerView* _jobs;
boost::optional<boost::filesystem::path> _dcp_path;
std::vector<Drive> _drives;
+#ifndef DCPOMATIC_OSX
boost::process::child* _writer;
+#endif
Nanomsg _nanomsg;
wxSizer* _sizer;
};
ev.Skip ();
}
+ void report_exception ()
+ {
+ try {
+ throw;
+ } catch (FileError& e) {
+ error_dialog (
+ 0,
+ wxString::Format (
+ _("An exception occurred: %s (%s)\n\n") + REPORT_PROBLEM,
+ std_to_wx (e.what()),
+ std_to_wx (e.file().string().c_str ())
+ )
+ );
+ } catch (exception& e) {
+ error_dialog (
+ 0,
+ wxString::Format (
+ _("An exception occurred: %s.\n\n") + REPORT_PROBLEM,
+ std_to_wx (e.what ())
+ )
+ );
+ } catch (...) {
+ error_dialog (0, _("An unknown exception occurred.") + " " + REPORT_PROBLEM);
+ }
+ }
+
+ bool OnExceptionInMainLoop ()
+ {
+ report_exception ();
+ /* This will terminate the program */
+ return false;
+ }
+
+ void OnUnhandledException ()
+ {
+ report_exception ();
+ }
+
DOMFrame* _frame;
};
uint8_t* buffer = new uint8_t[block_size];
Digester digester;
+ int progress_frequency = 5000;
+ int progress_count = 0;
uint64_t remaining = file_size (from);
while (remaining > 0) {
uint64_t const this_time = min(remaining, block_size);
}
remaining -= this_time;
total_remaining -= this_time;
- nanomsg->send(String::compose(DISK_WRITER_PROGRESS "\n%1\n", (1 - float(total_remaining) / total)), SHORT_TIMEOUT);
+
+ ++progress_count;
+ if ((progress_count % progress_frequency) == 0) {
+ nanomsg->send(String::compose(DISK_WRITER_PROGRESS "\n%1\n", (1 - float(total_remaining) / total)), SHORT_TIMEOUT);
+ }
}
fclose (in);
}
LOG_DISK_NC ("Wrote MBR");
-#ifdef DCPOMATIC_WINDOWS
struct ext4_mbr_bdevs bdevs;
r = ext4_mbr_scan (bd, &bdevs);
if (r != EOK) {
throw CopyError ("Failed to read MBR", r);
}
+#ifdef DCPOMATIC_WINDOWS
file_windows_partition_set (bdevs.partitions[0].part_offset, bdevs.partitions[0].part_size);
#endif
+ LOG_DISK ("Writing to partition at %1 size %2; bd part size is %3", bdevs.partitions[0].part_offset, bdevs.partitions[0].part_size, bd->part_size);
+
#ifdef DCPOMATIC_LINUX
/* Re-read the partition table */
int fd = open(device.c_str(), O_RDONLY);
if (!nanomsg->send(DISK_WRITER_OK "\n", LONG_TIMEOUT)) {
throw CommunicationFailedError ();
}
+
+ disk_write_finished ();
} catch (CopyError& e) {
LOG_DISK("CopyError (from write): %1 %2", e.message(), e.number().get_value_or(0));
nanomsg->send(String::compose(DISK_WRITER_ERROR "\n%1\n%2\n", e.message(), e.number().get_value_or(0)), LONG_TIMEOUT);
}
#endif
+
bool
idle ()
try
return true;
}
+ LOG_DISK("Writer receives command: %1", *s);
+
if (*s == DISK_WRITER_QUIT) {
exit (EXIT_SUCCESS);
} else if (*s == DISK_WRITER_UNMOUNT) {
optional<string> xml_head = nanomsg->receive (LONG_TIMEOUT);
optional<string> xml_body = nanomsg->receive (LONG_TIMEOUT);
if (!xml_head || !xml_body) {
+ LOG_DISK_NC("Failed to receive unmount request");
throw CommunicationFailedError ();
}
- if (Drive(*xml_head + *xml_body).unmount()) {
- if (!nanomsg->send (DISK_WRITER_OK "\n", LONG_TIMEOUT)) {
- throw CommunicationFailedError();
- }
- } else {
- if (!nanomsg->send (DISK_WRITER_ERROR "\n", LONG_TIMEOUT)) {
- throw CommunicationFailedError();
- }
+ bool const success = Drive(*xml_head + *xml_body).unmount();
+ if (!nanomsg->send (success ? (DISK_WRITER_OK "\n") : (DISK_WRITER_ERROR "\n"), LONG_TIMEOUT)) {
+ LOG_DISK_NC("CommunicationFailedError in unmount_finished");
+ throw CommunicationFailedError ();
}
- } else {
- optional<string> dcp_path = nanomsg->receive(LONG_TIMEOUT);
- optional<string> device = nanomsg->receive(LONG_TIMEOUT);
+ } else if (*s == DISK_WRITER_WRITE) {
+ optional<string> dcp_path = nanomsg->receive (LONG_TIMEOUT);
+ optional<string> device = nanomsg->receive (LONG_TIMEOUT);
if (!dcp_path || !device) {
+ LOG_DISK_NC("Failed to receive write request");
throw CommunicationFailedError();
}
#ifdef DCPOMATIC_OSX
if (!starts_with(*device, "/dev/disk")) {
LOG_DISK ("Will not write to %1", *device);
- nanomsg->try_send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n", LONG_TIMEOUT);
+ nanomsg->send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n", LONG_TIMEOUT);
return true;
}
#endif
#ifdef DCPOMATIC_WINDOWS
if (!starts_with(*device, "\\\\.\\PHYSICALDRIVE")) {
LOG_DISK ("Will not write to %1", *device);
- nanomsg->try_send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n", LONG_TIMEOUT);
+ nanomsg->send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n", LONG_TIMEOUT);
return true;
}
#endif
: wxDialog (parent, wxID_ANY, _("DCP-o-matic Disk Writer"))
{
wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL);
- wxStaticText* text = new StaticText (this, wxString::Format(_("The drive %s is mounted.\nIt must be unmounted before DCP-o-matic can write to it. Do you want to try to unmount it now?"), description));
+ wxStaticText* text = new StaticText (this, wxString::Format(_("The drive %s is mounted.\nIt must be unmounted before DCP-o-matic can write to it. Should DCP-o-matic try to unmount it now?"), description));
sizer->Add (text, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
wxSizer* buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL);