'libx264-155',
'libcurl4'])
-def build_dist(target):
- # We can build dcpomatic2_dist on platforms that have Boost process and can build the lwext4
+def build_disk(target):
+ # We can build dcpomatic2_disk on platforms that have Boost process and can build the lwext4
# library. For now, just whitelist good ones here.
#
# - Lots of Linux distros don't have a new enough boost (1.64 or above)
if options['variant'] == 'swaroop-studio':
print('%{_bindir}/dcpomatic2_ecinema', file=f)
print('%{_bindir}/dcpomatic2_uuid', file=f)
- if os.path.exists(os.path.join(tools, "dcpomatic2_dist")):
- print('%{_bindir}/dcpomatic2_dist', file=f)
- print('%{_bindir}/dcpomatic2_dist_writer', file=f)
+ if os.path.exists(os.path.join(tools, "dcpomatic2_disk")):
+ print('%{_bindir}/dcpomatic2_disk', file=f)
+ print('%{_bindir}/dcpomatic2_disk_writer', file=f)
print('%{_datadir}/applications/dcpomatic2.desktop', file=f)
print('%{_datadir}/applications/dcpomatic2_batch.desktop', file=f)
print('%{_datadir}/applications/dcpomatic2_server.desktop', file=f)
if target.debug and target.platform == 'windows':
opt += ' --static-dcpomatic'
- if build_dist(target):
- opt += ' --enable-dist'
+ if build_disk(target):
+ opt += ' --enable-disk'
return opt
override_dh_fixperms:
dh_fixperms --exclude usr/bin/dcpomatic2_uuid
- dh_fixperms --exclude usr/bin/dcpomatic2_dist_writer
+ dh_fixperms --exclude usr/bin/dcpomatic2_disk_writer
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="1066.6666"
+ height="1066.6666"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)"
+ sodipodi:docname="dcpomatic2_dist.svg"
+ viewBox="0 0 1000 1000">
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.34926264"
+ inkscape:cx="218.18331"
+ inkscape:cy="476.21434"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1680"
+ inkscape:window-height="995"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ inkscape:document-rotation="0"
+ inkscape:snap-global="false" />
+ <defs
+ id="defs4">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="573.17725 : 70.615423 : 0"
+ inkscape:vp_y="0 : 1048.4799 : 0"
+ inkscape:vp_z="1196.4109 : -308.5085 : 0"
+ inkscape:persp3d-origin="531.47195 : 173.77218 : 1"
+ id="perspective4530" />
+ <linearGradient
+ x1="-772.01001"
+ y1="742.5"
+ gradientTransform="matrix(-0.84033,-0.84033,-0.84033,0.84033,136.32259,-691.39649)"
+ x2="-886.76001"
+ gradientUnits="userSpaceOnUse"
+ y2="742.5"
+ id="linearGradient3594">
+ <stop
+ offset="0"
+ stop-color="#ffffff"
+ id="stop4687" />
+ <stop
+ offset="1"
+ stop-opacity="0"
+ stop-color="#ffffff"
+ id="stop4689" />
+ </linearGradient>
+ <linearGradient
+ x1="386.39001"
+ y1="63.870998"
+ gradientTransform="matrix(0.70711,-0.70711,0.70711,0.70711,-203.97741,756.21351)"
+ x2="385.04001"
+ gradientUnits="userSpaceOnUse"
+ y2="613.94"
+ id="linearGradient3601">
+ <stop
+ offset="0"
+ stop-color="#7f7f7f"
+ id="stop3797" />
+ <stop
+ offset="1"
+ stop-color="#6f6f6f"
+ id="stop3799" />
+ </linearGradient>
+ <linearGradient
+ gradientTransform="translate(-77.797413,384.00351)"
+ x1="409.38"
+ y1="358.29999"
+ x2="212.92999"
+ gradientUnits="userSpaceOnUse"
+ y2="161.84"
+ id="linearGradient3609">
+ <stop
+ offset="0"
+ stop-color="#6f6f6f"
+ id="stop4034" />
+ <stop
+ offset=".5"
+ stop-color="#6f6f6f"
+ id="stop3374" />
+ <stop
+ offset="1"
+ stop-color="#6f6f6f"
+ id="stop3376" />
+ </linearGradient>
+ <linearGradient
+ x1="403.63"
+ y1="448.35001"
+ gradientTransform="matrix(0.70711,-0.70711,0.70711,0.70711,-203.97741,756.21351)"
+ x2="382.89999"
+ gradientUnits="userSpaceOnUse"
+ y2="448.35001"
+ id="linearGradient3632">
+ <stop
+ offset="0"
+ stop-opacity=".39216"
+ stop-color="#7f7f7f"
+ id="stop3636" />
+ <stop
+ offset="1"
+ stop-opacity=".39216"
+ stop-color="#6f6f6f"
+ id="stop3638" />
+ </linearGradient>
+ </defs>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-52.362188)">
+ <image
+ sodipodi:absref="/home/carl/src/dcpomatic/graphics/src/dcpomatic.png"
+ xlink:href="dcpomatic.png"
+ y="80.386467"
+ x="10.670144"
+ width="960.00006"
+ height="960.00006"
+ preserveAspectRatio="none"
+ id="image4358"
+ style="stroke:#000000;stroke-opacity:1;stroke-width:2.5000001;stroke-miterlimit:4;stroke-dasharray:none;opacity:1" />
+ <g
+ id="g4865"
+ transform="matrix(1,0,0,0.7632365,969.89577,587.12592)"
+ style="stroke:#0b0000;stroke-width:8.01250839;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;opacity:0.691">
+ <path
+ sodipodi:nodetypes="ccccc"
+ d="m -213.36669,-76.521967 -237.25434,29.22973 v 131.7236 l 237.25434,-29.22973 z"
+ style="opacity:1;fill:#f2f2f2;fill-opacity:1;fill-rule:evenodd;stroke:#0b0000;stroke-width:8.01250839;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-end:none;paint-order:stroke fill markers"
+ id="path4664"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ d="m -512.46942,-153.6491 -237.25434,29.22973 300.80072,73.481127 235.55635,-25.583724 z"
+ style="opacity:1;fill:#767676;fill-opacity:1;fill-rule:evenodd;stroke:#0b0000;stroke-width:8.01250839;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-end:none;paint-order:stroke fill markers"
+ id="path4666"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ d="M -749.72376,-124.41937 V 7.3042426 l 299.10273,77.1271204 v -131.7236 z"
+ style="opacity:1;fill:#bcbcbc;fill-opacity:1;fill-rule:evenodd;stroke:#0b0000;stroke-width:8.01250839;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-end:none;paint-order:stroke fill markers"
+ id="path4668"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:#00ff00;stroke:#00ff00;stroke-width:15.00000095;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 536.48268,574.56478 38.71392,-3.11173"
+ id="path4867"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ inkscape:transform-center-x="-29.634214"
+ inkscape:transform-center-y="30.068191" />
+ </g>
+</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="1066.6666"
- height="1066.6666"
- id="svg2"
- version="1.1"
- inkscape:version="0.92.3 (2405546, 2018-03-11)"
- sodipodi:docname="dcpomatic2_dist.svg"
- viewBox="0 0 1000 1000">
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.34926264"
- inkscape:cx="218.18331"
- inkscape:cy="476.21434"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- showgrid="false"
- inkscape:window-width="1680"
- inkscape:window-height="995"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1"
- inkscape:document-rotation="0"
- inkscape:snap-global="false" />
- <defs
- id="defs4">
- <inkscape:perspective
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="573.17725 : 70.615423 : 0"
- inkscape:vp_y="0 : 1048.4799 : 0"
- inkscape:vp_z="1196.4109 : -308.5085 : 0"
- inkscape:persp3d-origin="531.47195 : 173.77218 : 1"
- id="perspective4530" />
- <linearGradient
- x1="-772.01001"
- y1="742.5"
- gradientTransform="matrix(-0.84033,-0.84033,-0.84033,0.84033,136.32259,-691.39649)"
- x2="-886.76001"
- gradientUnits="userSpaceOnUse"
- y2="742.5"
- id="linearGradient3594">
- <stop
- offset="0"
- stop-color="#ffffff"
- id="stop4687" />
- <stop
- offset="1"
- stop-opacity="0"
- stop-color="#ffffff"
- id="stop4689" />
- </linearGradient>
- <linearGradient
- x1="386.39001"
- y1="63.870998"
- gradientTransform="matrix(0.70711,-0.70711,0.70711,0.70711,-203.97741,756.21351)"
- x2="385.04001"
- gradientUnits="userSpaceOnUse"
- y2="613.94"
- id="linearGradient3601">
- <stop
- offset="0"
- stop-color="#7f7f7f"
- id="stop3797" />
- <stop
- offset="1"
- stop-color="#6f6f6f"
- id="stop3799" />
- </linearGradient>
- <linearGradient
- gradientTransform="translate(-77.797413,384.00351)"
- x1="409.38"
- y1="358.29999"
- x2="212.92999"
- gradientUnits="userSpaceOnUse"
- y2="161.84"
- id="linearGradient3609">
- <stop
- offset="0"
- stop-color="#6f6f6f"
- id="stop4034" />
- <stop
- offset=".5"
- stop-color="#6f6f6f"
- id="stop3374" />
- <stop
- offset="1"
- stop-color="#6f6f6f"
- id="stop3376" />
- </linearGradient>
- <linearGradient
- x1="403.63"
- y1="448.35001"
- gradientTransform="matrix(0.70711,-0.70711,0.70711,0.70711,-203.97741,756.21351)"
- x2="382.89999"
- gradientUnits="userSpaceOnUse"
- y2="448.35001"
- id="linearGradient3632">
- <stop
- offset="0"
- stop-opacity=".39216"
- stop-color="#7f7f7f"
- id="stop3636" />
- <stop
- offset="1"
- stop-opacity=".39216"
- stop-color="#6f6f6f"
- id="stop3638" />
- </linearGradient>
- </defs>
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-52.362188)">
- <image
- sodipodi:absref="/home/carl/src/dcpomatic/graphics/src/dcpomatic.png"
- xlink:href="dcpomatic.png"
- y="80.386467"
- x="10.670144"
- width="960.00006"
- height="960.00006"
- preserveAspectRatio="none"
- id="image4358"
- style="stroke:#000000;stroke-opacity:1;stroke-width:2.5000001;stroke-miterlimit:4;stroke-dasharray:none;opacity:1" />
- <g
- id="g4865"
- transform="matrix(1,0,0,0.7632365,969.89577,587.12592)"
- style="stroke:#0b0000;stroke-width:8.01250839;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;opacity:0.691">
- <path
- sodipodi:nodetypes="ccccc"
- d="m -213.36669,-76.521967 -237.25434,29.22973 v 131.7236 l 237.25434,-29.22973 z"
- style="opacity:1;fill:#f2f2f2;fill-opacity:1;fill-rule:evenodd;stroke:#0b0000;stroke-width:8.01250839;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-end:none;paint-order:stroke fill markers"
- id="path4664"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccc"
- d="m -512.46942,-153.6491 -237.25434,29.22973 300.80072,73.481127 235.55635,-25.583724 z"
- style="opacity:1;fill:#767676;fill-opacity:1;fill-rule:evenodd;stroke:#0b0000;stroke-width:8.01250839;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-end:none;paint-order:stroke fill markers"
- id="path4666"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccc"
- d="M -749.72376,-124.41937 V 7.3042426 l 299.10273,77.1271204 v -131.7236 z"
- style="opacity:1;fill:#bcbcbc;fill-opacity:1;fill-rule:evenodd;stroke:#0b0000;stroke-width:8.01250839;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-end:none;paint-order:stroke fill markers"
- id="path4668"
- inkscape:connector-curvature="0" />
- </g>
- <path
- style="fill:#00ff00;stroke:#00ff00;stroke-width:15.00000095;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 536.48268,574.56478 38.71392,-3.11173"
- id="path4867"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cc"
- inkscape:transform-center-x="-29.634214"
- inkscape:transform-center-y="30.068191" />
- </g>
-</svg>
exit 1
fi
-svg_apps="dcpomatic2_kdm dcpomatic2_server dcpomatic2_batch dcpomatic2_player dcpomatic2_playlist dcpomatic2_dist"
+svg_apps="dcpomatic2_kdm dcpomatic2_server dcpomatic2_batch dcpomatic2_player dcpomatic2_playlist dcpomatic2_disk"
if [ `uname -s` == "Darwin" ]; then
# Convert OS X icons using OS X-only iconutil
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>dcpomatic2_disk</string>
+ <key>CFBundleGetInfoString</key>
+ <string>DCP-o-matic 2 Disk Writer</string>
+ <key>CFBundleIconFile</key>
+ <string>dcpomatic2_disk.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.dcpomatic.disk</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>DCP-o-matic 2 Disk Writer</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersions</key>
+ <string>@VERSION@</string>
+ <key>CFBundleSignature</key>
+ <string>DOMC</string>
+ <key>CFBundleVersion</key>
+ <string>@VERSION@</string>
+ <key>CFBundleAllowMixedLocalizations</key>
+ <true/>
+ <key>LSUIElement</key>
+ <string>0</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>English</string>
- <key>CFBundleExecutable</key>
- <string>dcpomatic2_dist</string>
- <key>CFBundleGetInfoString</key>
- <string>DCP-o-matic 2 Disk Writer</string>
- <key>CFBundleIconFile</key>
- <string>dcpomatic2_dist.icns</string>
- <key>CFBundleIdentifier</key>
- <string>com.dcpomatic.dist</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string>DCP-o-matic 2 Disk Writer</string>
- <key>CFBundlePackageType</key>
- <string>APPL</string>
- <key>CFBundleShortVersions</key>
- <string>@VERSION@</string>
- <key>CFBundleSignature</key>
- <string>DOMC</string>
- <key>CFBundleVersion</key>
- <string>@VERSION@</string>
- <key>CFBundleAllowMixedLocalizations</key>
- <true/>
- <key>LSUIElement</key>
- <string>0</string>
- <key>NSMainNibFile</key>
- <string>MainMenu</string>
- <key>NSPrincipalClass</key>
- <string>NSApplication</string>
-</dict>
-</plist>
cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_player.icns "$dest"
cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_batch.icns "$dest"
cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_playlist.icns "$dest"
- cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_dist.icns "$dest"
+ cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_disk.icns "$dest"
cp $prefix/src/dcpomatic/graphics/osx/preferences/colour_conversions.png "$dest"
cp $prefix/src/dcpomatic/graphics/osx/preferences/defaults.png "$dest"
cp $prefix/src/dcpomatic/graphics/osx/preferences/kdm_email.png "$dest"
# DCP-o-matic Disk Writer
setup "DCP-o-matic 2 Disk Writer.app"
-copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_dist "$approot/MacOS"
-copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_dist_writer "$approot/MacOS"
-cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_dist.Info.plist "$approot/Info.plist"
-rl=("$approot/MacOS/dcpomatic2_dist" "$approot/Frameworks/"*.dylib)
+copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_disk "$approot/MacOS"
+copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_disk_writer "$approot/MacOS"
+cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_disk.Info.plist "$approot/Info.plist"
+rl=("$approot/MacOS/dcpomatic2_disk" "$approot/Frameworks/"*.dylib)
relink "${rl[@]}"
-rl=("$approot/MacOS/dcpomatic2_dist_writer" "$approot/Frameworks/"*.dylib)
+rl=("$approot/MacOS/dcpomatic2_disk_writer" "$approot/Frameworks/"*.dylib)
relink "${rl[@]}"
-make_dmg "$appdir" "DCP-o-matic Disk Writer" com.dcpomatic.dist
+make_dmg "$appdir" "DCP-o-matic Disk Writer" com.dcpomatic.disk
obj = bld(features='subst', source='dcpomatic2_batch.Info.plist.in', target='dcpomatic2_batch.Info.plist', version=bld.env.VERSION)
obj = bld(features='subst', source='dcpomatic2_player.Info.plist.in', target='dcpomatic2_player.Info.plist', version=bld.env.VERSION)
obj = bld(features='subst', source='dcpomatic2_playlist.Info.plist.in', target='dcpomatic2_playlist.Info.plist', version=bld.env.VERSION)
- obj = bld(features='subst', source='dcpomatic2_dist.Info.plist.in', target='dcpomatic2_dist.Info.plist', version=bld.env.VERSION)
+ obj = bld(features='subst', source='dcpomatic2_disk.Info.plist.in', target='dcpomatic2_disk.Info.plist', version=bld.env.VERSION)
--- /dev/null
+gdb.exe -x gdb_script dcpomatic2_disk.exe > %HOMEPATH%/Documents/dcpomatic_debug_log.txt
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">\r
+ <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="dcpomatic2_disk_writer" type="win32"/> \r
+ <description>DCP-o-matic Disk Writer</description> \r
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">\r
+ <security>\r
+ <requestedPrivileges>\r
+ <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>\r
+ </requestedPrivileges>\r
+ </security>\r
+ </trustInfo>\r
+</assembly>\r
+++ /dev/null
-gdb.exe -x gdb_script dcpomatic2_dist.exe > %HOMEPATH%/Documents/dcpomatic_debug_log.txt
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">\r
- <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="dcpomatic2_dist_writer" type="win32"/> \r
- <description>DCP-o-matic Disk Writer</description> \r
- <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">\r
- <security>\r
- <requestedPrivileges>\r
- <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>\r
- </requestedPrivileges>\r
- </security>\r
- </trustInfo>\r
-</assembly>\r
--- /dev/null
+id ICON "../../graphics/windows/dcpomatic2_disk.ico"
+#include "wx-3.0/wx/msw/wx.rc"
--- /dev/null
+#include "winuser.h"\r
+1 RT_MANIFEST "dcpomatic2_disk_writer.exe.manifest"\r
+++ /dev/null
-id ICON "../../graphics/windows/dcpomatic2_dist.ico"
-#include "wx-3.0/wx/msw/wx.rc"
+++ /dev/null
-#include "winuser.h"\r
-1 RT_MANIFEST "dcpomatic2_dist_writer.exe.manifest"\r
from __future__ import print_function
import os
-def write_installer(bits, windows_version, dcpomatic_version, debug, variant, dist):
+def write_installer(bits, windows_version, dcpomatic_version, debug, variant, disk):
try:
os.makedirs('build/platform/windows')
except:
File "%cdist_deps%/bin/kumu-carl.dll"
""", file=f)
- if dist:
+ if disk:
print("""
File "%static_deps%/bin/libnanomsg.dll"
File "%cdist_deps%/lib/libblockdev.dll"
print('File "%resources%/dcpomatic2_batch_debug.bat"', file=f)
print('File "%resources%/dcpomatic2_kdm_debug.bat"', file=f)
print('File "%resources%/dcpomatic2_player_debug.bat"', file=f)
- if dist:
- print('File "%resources%/dcpomatic2_dist_debug.bat"', file=f)
+ if disk:
+ print('File "%resources%/dcpomatic2_disk_debug.bat"', file=f)
print('File "%mingw%/bin/gdb.exe"', file=f)
else:
print('File "%binaries%/src/wx/dcpomatic2-wx.dll"', file=f)
File "%binaries%/src/tools/dcpomatic2_kdm_cli.exe"
""", file=f)
- if dist:
+ if disk:
print("""
-File "%binaries%/src/tools/dcpomatic2_dist.exe"
-File "%binaries%/src/tools/dcpomatic2_dist_writer.exe"
-File "%resources%/dcpomatic2_dist_writer.exe.manifest"
+File "%binaries%/src/tools/dcpomatic2_disk.exe"
+File "%binaries%/src/tools/dcpomatic2_disk_writer.exe"
+File "%resources%/dcpomatic2_disk_writer.exe.manifest"
""", file=f)
print("""
print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2 debug\\DCP-o-matic 2 debug.lnk" "$INSTDIR\\bin\\dcpomatic2_debug.bat"', file=f)
print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2 debug\\DCP-o-matic 2 Batch Converter debug.lnk" "$INSTDIR\\bin\\dcpomatic2_batch_debug.bat" ""', file=f)
print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2 debug\\DCP-o-matic 2 KDM Creator debug.lnk" "$INSTDIR\\bin\\dcpomatic2_kdm_debug.bat" ""', file=f)
- if dist:
- print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2 debug\\DCP-o-matic 2 Disk Writer debug.lnk" "$INSTDIR\\bin\\dcpomatic2_dist_debug.bat" ""', file=f)
+ if disk:
+ print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2 debug\\DCP-o-matic 2 Disk Writer debug.lnk" "$INSTDIR\\bin\\dcpomatic2_disk_debug.bat" ""', file=f)
print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2 debug\\Uninstall DCP-o-matic 2 debug.lnk" "$INSTDIR\\Uninstall.exe"', file=f)
print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2 debug\\DCP-o-matic 2 Player debug.lnk" "$INSTDIR\\bin\\dcpomatic2_player_debug.bat" ""', file=f)
print('WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic 2 debug" "DisplayName" "DCP-o-matic 2 debug (remove only)"', file=f)
print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\DCP-o-matic 2.lnk" "$INSTDIR\\bin\\dcpomatic2.exe"', file=f)
print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\DCP-o-matic 2 Batch Converter.lnk" "$INSTDIR\\bin\\dcpomatic2_batch.exe"', file=f)
print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\DCP-o-matic 2 KDM Creator.lnk" "$INSTDIR\\bin\\dcpomatic2_kdm.exe"', file=f)
- if dist:
- print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\DCP-o-matic 2 Disk Writer.lnk" "$INSTDIR\\bin\\dcpomatic2_dist.exe"', file=f)
+ if disk:
+ print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\DCP-o-matic 2 Disk Writer.lnk" "$INSTDIR\\bin\\dcpomatic2_disk.exe"', file=f)
print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\Uninstall DCP-o-matic 2.lnk" "$INSTDIR\\Uninstall.exe"', file=f)
print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\DCP-o-matic 2 Player.lnk" "$INSTDIR\\bin\\dcpomatic2_player.exe"', file=f)
print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\DCP-o-matic 2 Playlist Editor.lnk" "$INSTDIR\\bin\\dcpomatic2_playlist.exe"', file=f)
print('CreateShortCut "$DESKTOP\\DCP-o-matic 2 debug.lnk" "$INSTDIR\\bin\\dcpomatic2_debug.bat" ""', file=f)
print('CreateShortCut "$DESKTOP\\DCP-o-matic 2 Batch Converter debug.lnk" "$INSTDIR\\bin\\dcpomatic2_batch_debug.bat" ""', file=f)
print('CreateShortCut "$DESKTOP\\DCP-o-matic 2 KDM Creator debug.lnk" "$INSTDIR\\bin\\dcpomatic2_kdm_debug.bat" ""', file=f)
- if dist:
- print('CreateShortCut "$DESKTOP\\DCP-o-matic 2 Disk Writer debug.lnk" "$INSTDIR\\bin\\dcpomatic2_dist_debug.bat" ""', file=f)
+ if disk:
+ print('CreateShortCut "$DESKTOP\\DCP-o-matic 2 Disk Writer debug.lnk" "$INSTDIR\\bin\\dcpomatic2_disk_debug.bat" ""', file=f)
else:
print('Section "DCP-o-matic 2 desktop shortcuts" SEC_MASTER_DESKTOP', file=f)
print('CreateShortCut "$DESKTOP\\DCP-o-matic 2 Player.lnk" "$INSTDIR\\bin\\dcpomatic2_player.exe"', file=f)
print('CreateShortCut "$DESKTOP\\DCP-o-matic 2.lnk" "$INSTDIR\\bin\\dcpomatic2.exe" ""', file=f)
print('CreateShortCut "$DESKTOP\\DCP-o-matic 2 Batch Converter.lnk" "$INSTDIR\\bin\\dcpomatic2_batch.exe"', file=f)
print('CreateShortCut "$DESKTOP\\DCP-o-matic 2 KDM Creator.lnk" "$INSTDIR\\bin\\dcpomatic2_kdm.exe"', file=f)
- if dist:
- print('CreateShortCut "$DESKTOP\\DCP-o-matic 2 Disk Writer.lnk" "$INSTDIR\\bin\\dcpomatic2_dist.exe"', file=f)
+ if disk:
+ print('CreateShortCut "$DESKTOP\\DCP-o-matic 2 Disk Writer.lnk" "$INSTDIR\\bin\\dcpomatic2_disk.exe"', file=f)
print("SectionEnd", file=f)
def build(bld):
- write_installer(32, None, bld.env.VERSION, bld.env.DEBUG, bld.env.VARIANT, bld.env.ENABLE_DIST)
- write_installer(64, None, bld.env.VERSION, bld.env.DEBUG, bld.env.VARIANT, bld.env.ENABLE_DIST)
- write_installer(32, 'xp', bld.env.VERSION, bld.env.DEBUG, bld.env.VARIANT, bld.env.ENABLE_DIST)
- write_installer(64, 'xp', bld.env.VERSION, bld.env.DEBUG, bld.env.VARIANT, bld.env.ENABLE_DIST)
+ write_installer(32, None, bld.env.VERSION, bld.env.DEBUG, bld.env.VARIANT, bld.env.ENABLE_DISK)
+ write_installer(64, None, bld.env.VERSION, bld.env.DEBUG, bld.env.VARIANT, bld.env.ENABLE_DISK)
+ write_installer(32, 'xp', bld.env.VERSION, bld.env.DEBUG, bld.env.VARIANT, bld.env.ENABLE_DISK)
+ write_installer(64, 'xp', bld.env.VERSION, bld.env.DEBUG, bld.env.VARIANT, bld.env.ENABLE_DISK)
--- /dev/null
+#!/bin/bash
+
+export LD_LIBRARY_PATH=build/src/lib:build/src/wx:build/src/asdcplib/src:$LD_LIBRARY_PATH
+export DYLD_LIBRARY_PATH=build/src/lib:build/src/wx:build/src/asdcplib/src:/Users/carl/Environments/dcpomatic/64/lib
+if [ "$1" == "--debug" ]; then
+ shift
+ gdb --args build/src/tools/dcpomatic2_disk $*
+elif [ "$1" == "--valgrind" ]; then
+ shift
+ valgrind --tool="memcheck" --suppressions=suppressions --track-fds=yes --show-leak-kinds=all --leak-check=full build/src/tools/dcpomatic2_disk $*
+elif [ "$1" == "--callgrind" ]; then
+ shift
+ valgrind --tool="callgrind" build/src/tools/dcpomatic2_disk $*
+elif [ "$1" == "--massif" ]; then
+ shift
+ valgrind --tool="massif" build/src/tools/dcpomatic2_disk $*
+elif [ "$1" == "--i18n" ]; then
+ shift
+ LANGUAGE=de_DE.UTF8 LANG=de_DE.UTF8 LC_ALL=de_DE.UTF8 build/src/tools/dcpomatic2_disk "$*"
+elif [ "$1" == "--perf" ]; then
+ shift
+ perf record build/src/tools/dcpomatic2_disk $*
+elif [ "$1" == "--scaled" ]; then
+ shift
+ ~/src/run_scaled/run_scaled --sleep=5 --scale=0.5 build/src/tools/dcpomatic2_disk $*
+else
+ build/src/tools/dcpomatic2_disk $*
+fi
--- /dev/null
+#!/bin/bash
+
+export LD_LIBRARY_PATH=build/src/lib:build/src/wx:build/src/asdcplib/src:$LD_LIBRARY_PATH
+export DYLD_LIBRARY_PATH=build/src/lib:build/src/wx:build/src/asdcplib/src:/Users/carl/Environments/dcpomatic/64/lib
+exe=build/src/tools/dcpomatic2_disk_writer
+sudo chown root:root $exe
+sudo chmod 4755 $exe
+if [ "$1" == "--debug" ]; then
+ shift
+ gdb --args $exe $*
+elif [ "$1" == "--valgrind" ]; then
+ shift
+ valgrind --tool="memcheck" --suppressions=suppressions --track-fds=yes --show-leak-kinds=all --leak-check=full $exe $*
+elif [ "$1" == "--callgrind" ]; then
+ shift
+ valgrind --tool="callgrind" $exe $*
+elif [ "$1" == "--massif" ]; then
+ shift
+ valgrind --tool="massif" $exe $*
+elif [ "$1" == "--i18n" ]; then
+ shift
+ LANGUAGE=de_DE.UTF8 LANG=de_DE.UTF8 LC_ALL=de_DE.UTF8 $exe "$*"
+elif [ "$1" == "--perf" ]; then
+ shift
+ perf record $exe $*
+elif [ "$1" == "--scaled" ]; then
+ shift
+ ~/src/run_scaled/run_scaled --sleep=5 --scale=0.5 $exe $*
+else
+ $exe $*
+fi
+++ /dev/null
-#!/bin/bash
-
-export LD_LIBRARY_PATH=build/src/lib:build/src/wx:build/src/asdcplib/src:/home/c.hetherington/lib:$LD_LIBRARY_PATH
-export DYLD_LIBRARY_PATH=build/src/lib:build/src/wx:build/src/asdcplib/src:/Users/carl/Environments/dcpomatic/64/lib
-if [ "$1" == "--debug" ]; then
- shift
- gdb --args build/src/tools/dcpomatic2_dist $*
-elif [ "$1" == "--valgrind" ]; then
- shift
- valgrind --tool="memcheck" --suppressions=suppressions --track-fds=yes --show-leak-kinds=all --leak-check=full build/src/tools/dcpomatic2_dist $*
-elif [ "$1" == "--callgrind" ]; then
- shift
- valgrind --tool="callgrind" build/src/tools/dcpomatic2_dist $*
-elif [ "$1" == "--massif" ]; then
- shift
- valgrind --tool="massif" build/src/tools/dcpomatic2_dist $*
-elif [ "$1" == "--i18n" ]; then
- shift
- LANGUAGE=de_DE.UTF8 LANG=de_DE.UTF8 LC_ALL=de_DE.UTF8 build/src/tools/dcpomatic2_dist "$*"
-elif [ "$1" == "--perf" ]; then
- shift
- perf record build/src/tools/dcpomatic2_dist $*
-elif [ "$1" == "--scaled" ]; then
- shift
- ~/src/run_scaled/run_scaled --sleep=5 --scale=0.5 build/src/tools/dcpomatic2_dist $*
-else
- build/src/tools/dcpomatic2_dist $*
-fi
+++ /dev/null
-#!/bin/bash
-
-export LD_LIBRARY_PATH=build/src/lib:build/src/wx:build/src/asdcplib/src:/home/c.hetherington/lib:$LD_LIBRARY_PATH
-export DYLD_LIBRARY_PATH=build/src/lib:build/src/wx:build/src/asdcplib/src:/Users/carl/Environments/dcpomatic/64/lib
-exe=build/src/tools/dcpomatic2_dist_writer
-sudo chown root:root $exe
-sudo chmod 4755 $exe
-if [ "$1" == "--debug" ]; then
- shift
- gdb --args $exe $*
-elif [ "$1" == "--valgrind" ]; then
- shift
- valgrind --tool="memcheck" --suppressions=suppressions --track-fds=yes --show-leak-kinds=all --leak-check=full $exe $*
-elif [ "$1" == "--callgrind" ]; then
- shift
- valgrind --tool="callgrind" $exe $*
-elif [ "$1" == "--massif" ]; then
- shift
- valgrind --tool="massif" $exe $*
-elif [ "$1" == "--i18n" ]; then
- shift
- LANGUAGE=de_DE.UTF8 LANG=de_DE.UTF8 LC_ALL=de_DE.UTF8 $exe "$*"
-elif [ "$1" == "--perf" ]; then
- shift
- perf record $exe $*
-elif [ "$1" == "--scaled" ]; then
- shift
- ~/src/run_scaled/run_scaled --sleep=5 --scale=0.5 $exe $*
-else
- $exe $*
-fi
while (true) {
bool formatting = false;
string s = _nanomsg.blocking_get ();
- if (s == DIST_WRITER_OK) {
+ if (s == DISK_WRITER_OK) {
set_state (FINISHED_OK);
return;
- } else if (s == DIST_WRITER_ERROR) {
+ } else if (s == DISK_WRITER_ERROR) {
string const m = _nanomsg.blocking_get ();
string const n = _nanomsg.blocking_get ();
throw CopyError (m, raw_convert<int>(n));
- } else if (s == DIST_WRITER_FORMATTING) {
+ } else if (s == DISK_WRITER_FORMATTING) {
sub ("Formatting drive");
set_progress_unknown ();
formatting = true;
- } else if (s == DIST_WRITER_PROGRESS) {
+ } else if (s == DISK_WRITER_PROGRESS) {
if (formatting) {
sub ("Copying DCP");
formatting = false;
extern void run_ffprobe (boost::filesystem::path, boost::filesystem::path);
extern std::list<std::pair<std::string, std::string> > mount_info ();
extern boost::filesystem::path openssl_path ();
-extern boost::filesystem::path dist_writer_path ();
+extern boost::filesystem::path disk_writer_path ();
#ifdef DCPOMATIC_OSX
extern boost::filesystem::path app_contents ();
#endif
}
boost::filesystem::path
-dist_writer_path ()
+disk_writer_path ()
{
- return boost::dll::program_location().parent_path() / "dcpomatic2_dist_writer";
+ return boost::dll::program_location().parent_path() / "dcpomatic2_disk_writer";
}
/* Apparently there is no way to create an ofstream using a UTF-8
boost::algorithm::split (bits, line, boost::is_any_of(" "));
if (bits.size() > 0 && boost::algorithm::starts_with(bits[0], "/dev/")) {
mounted_devices.push_back(bits[0]);
- LOG_DIST("Mounted device %1", bits[0]);
+ LOG_DISK("Mounted device %1", bits[0]);
}
}
}
}
drives.push_back(Drive("/dev/" + i->path().filename().string(), size, mounted, vendor, model));
- LOG_DIST("Block device %1 size %2 %3 vendor %4 model %5", name, size, mounted ? "mounted" : "not mounted", vendor.get_value_or("[none]"), model.get_value_or("[none]"));
+ LOG_DISK("Block device %1 size %2 %3 vendor %4 model %5", name, size, mounted ? "mounted" : "not mounted", vendor.get_value_or("[none]"), model.get_value_or("[none]"));
}
}
}
boost::filesystem::path
-dist_writer_path ()
+disk_writer_path ()
{
boost::filesystem::path path = app_contents();
path /= "MacOS";
- path /= "dcpomatic2_dist_writer";
+ path /= "dcpomatic2_disk_writer";
return path;
}
}
boost::filesystem::path
-dist_writer_path ()
+disk_writer_path ()
{
- return executable_path() / "dcpomatic2_dist_writer.exe";
+ return executable_path() / "dcpomatic2_disk_writer.exe";
}
/* Apparently there is no way to create an ofstream using a UTF-8
BOOL r = SetupDiEnumDeviceInterfaces (device_info, device_info_data, &GUID_DEVICE_INTERFACE_DISK, 0, &device_interface_data);
if (!r) {
- LOG_DIST("SetupDiEnumDeviceInterfaces failed (%1)", GetLastError());
+ LOG_DISK("SetupDiEnumDeviceInterfaces failed (%1)", GetLastError());
return optional<int>();
}
r = SetupDiGetDeviceInterfaceDetailW(device_info, &device_interface_data, 0, 0, &size, 0);
PSP_DEVICE_INTERFACE_DETAIL_DATA_W device_detail_data = static_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA_W> (malloc(size));
if (!device_detail_data) {
- LOG_DIST_NC("malloc failed");
+ LOG_DISK_NC("malloc failed");
return optional<int>();
}
/* And get the path */
r = SetupDiGetDeviceInterfaceDetailW (device_info, &device_interface_data, device_detail_data, size, &size, 0);
if (!r) {
- LOG_DIST_NC("SetupDiGetDeviceInterfaceDetailW failed");
+ LOG_DISK_NC("SetupDiGetDeviceInterfaceDetailW failed");
free (device_detail_data);
return optional<int>();
}
free (device_detail_data);
if (device == INVALID_HANDLE_VALUE) {
- LOG_DIST("CreateFileW failed with %1", GetLastError());
+ LOG_DISK("CreateFileW failed with %1", GetLastError());
return optional<int>();
}
/* Get a `device information set' containing information about all disks */
HDEVINFO device_info = SetupDiGetClassDevsA (&GUID_DEVICE_INTERFACE_DISK, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (device_info == INVALID_HANDLE_VALUE) {
- LOG_DIST_NC ("SetupDiClassDevsA failed");
+ LOG_DISK_NC ("SetupDiClassDevsA failed");
return drives;
}
if (!SetupDiEnumDeviceInfo(device_info, i, &device_info_data)) {
DWORD e = GetLastError();
if (e != ERROR_NO_MORE_ITEMS) {
- LOG_DIST ("SetupDiEnumDeviceInfo failed (%1)", GetLastError());
+ LOG_DISK ("SetupDiEnumDeviceInfo failed (%1)", GetLastError());
}
break;
}
);
if (device == INVALID_HANDLE_VALUE) {
- LOG_DIST_NC("Could not open PHYSICALDRIVE");
+ LOG_DISK_NC("Could not open PHYSICALDRIVE");
continue;
}
#define LOG_DEBUG_PLAYER(...) dcpomatic_log->log(String::compose(__VA_ARGS__), LogEntry::TYPE_DEBUG_PLAYER);
#define LOG_DEBUG_THREED(...) dcpomatic_log->log(String::compose(__VA_ARGS__), LogEntry::TYPE_DEBUG_THREED);
#define LOG_DEBUG_THREED_NC(...) dcpomatic_log->log(__VA_ARGS__, LogEntry::TYPE_DEBUG_THREED);
-#define LOG_DIST(...) dcpomatic_log->log(String::compose(__VA_ARGS__), LogEntry::TYPE_DIST);
-#define LOG_DIST_NC(...) dcpomatic_log->log(__VA_ARGS__, LogEntry::TYPE_DIST);
+#define LOG_DISK(...) dcpomatic_log->log(String::compose(__VA_ARGS__), LogEntry::TYPE_DISK);
+#define LOG_DISK_NC(...) dcpomatic_log->log(__VA_ARGS__, LogEntry::TYPE_DISK);
--- /dev/null
+/*
+ Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+/* dcpomatic_disk_writer receives
+
+DCP pathname\n
+Internal name of drive to write to\n
+
+ Then responds with one of the following.
+*/
+
+/** Write finished and everything was OK, e.g.
+
+D\n
+
+*/
+#define DISK_WRITER_OK "D"
+
+/** There was an error. Following this will come
+
+error message\n
+error number\n
+
+e.g.
+
+E\n
+Disc full\n
+42\n
+
+*/
+#define DISK_WRITER_ERROR "E"
+
+/** The disk writer is formatting the drive. It is not possible
+ * to give progress reports on this so the writer just tells us
+ * it's happening. This is finished when DISK_WRITER_PROGRESS
+ * messages start arriving
+ */
+#define DISK_WRITER_FORMATTING "F"
+
+/** Some progress has been made in the main "copy" part of the task.
+ * Following this will come
+
+progress as a float from 0 to 1\n
+
+e.g.
+
+P\n
+0.3\n
+
+*/
+#define DISK_WRITER_PROGRESS "P"
+
+/** dcpomatic_disk_writer may also receive
+
+Q\n
+
+as a request to quit.
+*/
+#define DISK_WRITER_QUIT "Q"
+
+++ /dev/null
-/*
- Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
-
- This file is part of DCP-o-matic.
-
- DCP-o-matic 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.
-
- DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-/* dcpomatic_dist_writer receives
-
-DCP pathname\n
-Internal name of drive to write to\n
-
- Then responds with one of the following.
-*/
-
-/** Write finished and everything was OK, e.g.
-
-D\n
-
-*/
-#define DIST_WRITER_OK "D"
-
-/** There was an error. Following this will come
-
-error message\n
-error number\n
-
-e.g.
-
-E\n
-Disc full\n
-42\n
-
-*/
-#define DIST_WRITER_ERROR "E"
-
-/** The disk writer is formatting the drive. It is not possible
- * to give progress reports on this so the writer just tells us
- * it's happening. This is finished when DIST_WRITER_PROGRESS
- * messages start arriving
- */
-#define DIST_WRITER_FORMATTING "F"
-
-/** Some progress has been made in the main "copy" part of the task.
- * Following this will come
-
-progress as a float from 0 to 1\n
-
-e.g.
-
-P\n
-0.3\n
-
-*/
-#define DIST_WRITER_PROGRESS "P"
-
-/** dcpomatic_dist_writer may also receive
-
-Q\n
-
-as a request to quit.
-*/
-#define DIST_WRITER_QUIT "Q"
-
int const LogEntry::TYPE_TIMING = 0x020;
int const LogEntry::TYPE_DEBUG_EMAIL = 0x040;
int const LogEntry::TYPE_DEBUG_PLAYER = 0x080;
-int const LogEntry::TYPE_DIST = 0x100;
+int const LogEntry::TYPE_DISK = 0x100;
using std::string;
static const int TYPE_TIMING;
static const int TYPE_DEBUG_EMAIL;
static const int TYPE_DEBUG_PLAYER;
- static const int TYPE_DIST;
+ static const int TYPE_DISK;
explicit LogEntry (int type);
virtual ~LogEntry () {}
if bld.env.VARIANT == 'swaroop-theater' or bld.env.VARIANT == 'swaroop-studio':
obj.source += ' swaroop_spl.cc swaroop_spl_entry.cc'
- if bld.env.ENABLE_DIST:
+ if bld.env.ENABLE_DISK:
obj.source += ' copy_to_drive_job.cc'
obj.uselib += ' LWEXT4 NANOMSG'
if bld.env.TARGET_LINUX:
--- /dev/null
+/*
+ Copyright (C) 2019-2020 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "wx/wx_signal_manager.h"
+#include "wx/wx_util.h"
+#include "wx/job_manager_view.h"
+#include "wx/drive_wipe_warning_dialog.h"
+#include "lib/file_log.h"
+#include "lib/dcpomatic_log.h"
+#include "lib/util.h"
+#include "lib/config.h"
+#include "lib/signal_manager.h"
+#include "lib/cross.h"
+#include "lib/copy_to_drive_job.h"
+#include "lib/job_manager.h"
+#include "lib/disk_writer_messages.h"
+#include <wx/wx.h>
+#include <boost/process.hpp>
+#ifdef DCPOMATIC_WINDOWS
+#include <boost/process/windows.hpp>
+#endif
+#ifdef DCPOMATIC_OSX
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+using std::string;
+using std::exception;
+using std::cout;
+using std::cerr;
+using std::runtime_error;
+using boost::shared_ptr;
+
+class DOMFrame : public wxFrame
+{
+public:
+ explicit DOMFrame (wxString const & title)
+ : wxFrame (0, -1, title)
+ , _nanomsg (true)
+ , _sizer (new wxBoxSizer(wxVERTICAL))
+ {
+ /* Use a panel as the only child of the Frame so that we avoid
+ the dark-grey background on Windows.
+ */
+ wxPanel* overall_panel = new wxPanel (this);
+ wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+ s->Add (overall_panel, 1, wxEXPAND);
+ SetSizer (s);
+
+ wxGridBagSizer* grid = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
+
+ int r = 0;
+ add_label_to_sizer (grid, overall_panel, _("DCP"), true, wxGBPosition(r, 0));
+ wxBoxSizer* dcp_name_sizer = new wxBoxSizer (wxHORIZONTAL);
+ _dcp_name = new wxStaticText (overall_panel, wxID_ANY, wxEmptyString);
+ dcp_name_sizer->Add (_dcp_name, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, DCPOMATIC_SIZER_X_GAP);
+ _dcp_open = new wxButton (overall_panel, wxID_ANY, _("Open..."));
+ dcp_name_sizer->Add (_dcp_open, 0);
+ grid->Add (dcp_name_sizer, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND);
+ ++r;
+
+ add_label_to_sizer (grid, overall_panel, _("Drive"), true, wxGBPosition(r, 0));
+ wxBoxSizer* drive_sizer = new wxBoxSizer (wxHORIZONTAL);
+ _drive = new wxChoice (overall_panel, wxID_ANY);
+ drive_sizer->Add (_drive, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, DCPOMATIC_SIZER_X_GAP);
+ _drive_refresh = new wxButton (overall_panel, wxID_ANY, _("Refresh"));
+ drive_sizer->Add (_drive_refresh, 0);
+ grid->Add (drive_sizer, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND);
+ ++r;
+
+ _jobs = new JobManagerView (overall_panel, false);
+ grid->Add (_jobs, wxGBPosition(r, 0), wxGBSpan(6, 2), wxEXPAND);
+ r += 6;
+
+ _copy = new wxButton (overall_panel, wxID_ANY, _("Copy DCP"));
+ grid->Add (_copy, wxGBPosition(r, 0), wxGBSpan(1, 2), wxEXPAND);
+ ++r;
+
+ grid->AddGrowableCol (1);
+
+ _dcp_open->Bind (wxEVT_BUTTON, boost::bind(&DOMFrame::open, this));
+ _copy->Bind (wxEVT_BUTTON, boost::bind(&DOMFrame::copy, this));
+ _drive->Bind (wxEVT_CHOICE, boost::bind(&DOMFrame::setup_sensitivity, this));
+ _drive_refresh->Bind (wxEVT_BUTTON, boost::bind(&DOMFrame::drive_refresh, this));
+
+ _sizer->Add (grid, 1, wxALL | wxEXPAND, DCPOMATIC_DIALOG_BORDER);
+ overall_panel->SetSizer (_sizer);
+ Fit ();
+ SetSize (768, GetSize().GetHeight() + 32);
+
+ /* XXX: this is a hack, but I expect we'll need logs and I'm not sure if there's
+ * a better place to put them.
+ */
+ dcpomatic_log.reset(new FileLog(config_path() / "disk.log"));
+ dcpomatic_log->set_types (dcpomatic_log->types() | LogEntry::TYPE_DISK);
+ LOG_DISK_NC("dcpomatic_disk started");
+
+ drive_refresh ();
+
+ Bind (wxEVT_SIZE, boost::bind (&DOMFrame::sized, this, _1));
+
+ JobManager::instance()->ActiveJobsChanged.connect(boost::bind(&DOMFrame::setup_sensitivity, this));
+
+#ifdef DCPOMATIC_WINDOWS
+ /* We must use ::shell here, it seems, to avoid error code 740 (related to privilege escalation) */
+ _writer = new boost::process::child (disk_writer_path(), boost::process::shell, boost::process::windows::hide);
+#else
+ LOG_DISK("Starting writer process %1", disk_writer_path().string());
+ _writer = new boost::process::child (disk_writer_path());
+#endif
+ }
+
+ ~DOMFrame ()
+ {
+ _nanomsg.blocking_send(DISK_WRITER_QUIT "\n");
+ }
+
+private:
+ void sized (wxSizeEvent& ev)
+ {
+ _sizer->Layout ();
+ ev.Skip ();
+ }
+
+ void open ()
+ {
+ wxDirDialog* d = new wxDirDialog (this, _("Choose a DCP folder"), wxT(""), wxDD_DIR_MUST_EXIST);
+ int r = d->ShowModal ();
+ boost::filesystem::path const path (wx_to_std(d->GetPath()));
+ d->Destroy ();
+
+ if (r != wxID_OK) {
+ return;
+ }
+
+ _dcp_path = path;
+ _dcp_name->SetLabel (std_to_wx(_dcp_path->filename().string()));
+ setup_sensitivity ();
+ }
+
+ void copy ()
+ {
+ DCPOMATIC_ASSERT (_drive->GetSelection() != wxNOT_FOUND);
+ DCPOMATIC_ASSERT (static_cast<bool>(_dcp_path));
+ DriveWipeWarningDialog* d = new DriveWipeWarningDialog (this, _drive->GetString(_drive->GetSelection()));
+ int const r = d->ShowModal ();
+ bool ok = r == wxID_OK && d->confirmed();
+ d->Destroy ();
+
+ if (!ok) {
+ return;
+ }
+
+ JobManager::instance()->add(shared_ptr<Job>(new CopyToDriveJob(*_dcp_path, _drives[_drive->GetSelection()], _nanomsg)));
+ setup_sensitivity ();
+ }
+
+ void drive_refresh ()
+ {
+ int const sel = _drive->GetSelection ();
+ wxString current;
+ if (sel != wxNOT_FOUND) {
+ current = _drive->GetString (sel);
+ }
+ _drive->Clear ();
+ int re_select = wxNOT_FOUND;
+ int j = 0;
+ _drives.clear ();
+ BOOST_FOREACH (Drive i, get_drives()) {
+ if (!i.mounted()) {
+ _drives.push_back (i);
+ }
+ }
+ BOOST_FOREACH (Drive i, _drives) {
+ wxString const s = std_to_wx(i.description());
+ if (s == current) {
+ re_select = j;
+ }
+ _drive->Append(s);
+ ++j;
+ }
+ _drive->SetSelection (re_select);
+ setup_sensitivity ();
+ }
+
+ void setup_sensitivity ()
+ {
+ _copy->Enable (static_cast<bool>(_dcp_path) && _drive->GetSelection() != wxNOT_FOUND && !JobManager::instance()->work_to_do());
+ }
+
+ wxStaticText* _dcp_name;
+ wxButton* _dcp_open;
+ wxChoice* _drive;
+ wxButton* _drive_refresh;
+ wxButton* _copy;
+ JobManagerView* _jobs;
+ boost::optional<boost::filesystem::path> _dcp_path;
+ std::vector<Drive> _drives;
+ boost::process::child* _writer;
+ Nanomsg _nanomsg;
+ wxSizer* _sizer;
+};
+
+class App : public wxApp
+{
+public:
+ App ()
+ : _frame (0)
+ {}
+
+ bool OnInit ()
+ {
+ try {
+ Config::FailedToLoad.connect (boost::bind (&App::config_failed_to_load, this));
+ Config::Warning.connect (boost::bind (&App::config_warning, this, _1));
+
+ SetAppName (_("DCP-o-matic Disk Writer"));
+
+ if (!wxApp::OnInit()) {
+ return false;
+ }
+
+#ifdef DCPOMATIC_LINUX
+ unsetenv ("UBUNTU_MENUPROXY");
+#endif
+
+#ifdef __WXOSX__
+ ProcessSerialNumber serial;
+ GetCurrentProcess (&serial);
+ TransformProcessType (&serial, kProcessTransformToForegroundApplication);
+#endif
+
+ dcpomatic_setup_path_encoding ();
+
+ /* Enable i18n; this will create a Config object
+ to look for a force-configured language. This Config
+ object will be wrong, however, because dcpomatic_setup
+ hasn't yet been called and there aren't any filters etc.
+ set up yet.
+ */
+ dcpomatic_setup_i18n ();
+
+ /* Set things up, including filters etc.
+ which will now be internationalised correctly.
+ */
+ dcpomatic_setup ();
+
+ /* Force the configuration to be re-loaded correctly next
+ time it is needed.
+ */
+ Config::drop ();
+
+ _frame = new DOMFrame (_("DCP-o-matic Disk Writer"));
+ SetTopWindow (_frame);
+
+ _frame->Show ();
+
+ signal_manager = new wxSignalManager (this);
+ Bind (wxEVT_IDLE, boost::bind (&App::idle, this, _1));
+ }
+ catch (exception& e)
+ {
+ error_dialog (0, wxString::Format ("DCP-o-matic could not start."), std_to_wx(e.what()));
+ }
+
+ return true;
+ }
+
+ void config_failed_to_load ()
+ {
+ message_dialog (_frame, _("The existing configuration failed to load. Default values will be used instead. These may take a short time to create."));
+ }
+
+ void config_warning (string m)
+ {
+ message_dialog (_frame, std_to_wx(m));
+ }
+
+ void idle (wxIdleEvent& ev)
+ {
+ signal_manager->ui_idle ();
+ ev.Skip ();
+ }
+
+ DOMFrame* _frame;
+};
+
+IMPLEMENT_APP (App)
--- /dev/null
+/*
+ Copyright (C) 2019-2020 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "lib/disk_writer_messages.h"
+#include "lib/compose.hpp"
+#include "lib/exceptions.h"
+#include "lib/cross.h"
+#include "lib/digester.h"
+#include "lib/file_log.h"
+#include "lib/dcpomatic_log.h"
+#include "lib/nanomsg.h"
+extern "C" {
+#include <lwext4/ext4_mbr.h>
+#include <lwext4/ext4_fs.h>
+#include <lwext4/ext4_mkfs.h>
+#include <lwext4/ext4_errno.h>
+#include <lwext4/ext4_debug.h>
+#include <lwext4/ext4.h>
+}
+
+#ifdef DCPOMATIC_POSIX
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+#ifdef DCPOMATIC_OSX
+#undef nil
+extern "C" {
+#include <lwext4/file_dev.h>
+}
+#endif
+
+#ifdef DCPOMATIC_LINUX
+#include <linux/fs.h>
+#include <polkit/polkit.h>
+extern "C" {
+#include <lwext4/file_dev.h>
+}
+#include <poll.h>
+#endif
+
+#ifdef DCPOMATIC_WINDOWS
+extern "C" {
+#include <lwext4/file_windows.h>
+}
+#endif
+
+#include <glibmm.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <boost/filesystem.hpp>
+#include <iostream>
+
+using std::cin;
+using std::min;
+using std::string;
+using std::runtime_error;
+using std::exception;
+using boost::optional;
+
+#ifdef DCPOMATIC_LINUX
+static PolkitAuthority* polkit_authority = 0;
+#endif
+static boost::filesystem::path dcp_path;
+static std::string device;
+static uint64_t const block_size = 4096;
+static Nanomsg* nanomsg = 0;
+
+static
+void
+count (boost::filesystem::path dir, uint64_t& total_bytes)
+{
+ using namespace boost::filesystem;
+ for (directory_iterator i = directory_iterator(dir); i != directory_iterator(); ++i) {
+ if (is_directory(*i)) {
+ count (*i, total_bytes);
+ } else {
+ total_bytes += file_size (*i);
+ }
+ }
+}
+
+static
+string
+write (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total_remaining, uint64_t total)
+{
+ ext4_file out;
+ int r = ext4_fopen(&out, to.generic_string().c_str(), "wb");
+ if (r != EOK) {
+ throw CopyError (String::compose("Failed to open file %1", to.generic_string()), r);
+ }
+
+ FILE* in = fopen_boost (from, "rb");
+ if (!in) {
+ ext4_fclose (&out);
+ throw CopyError (String::compose("Failed to open file %1", from.string()), 0);
+ }
+
+ uint8_t* buffer = new uint8_t[block_size];
+ Digester digester;
+
+ uint64_t remaining = file_size (from);
+ while (remaining > 0) {
+ uint64_t const this_time = min(remaining, block_size);
+ size_t read = fread (buffer, 1, this_time, in);
+ if (read != this_time) {
+ fclose (in);
+ ext4_fclose (&out);
+ delete[] buffer;
+ throw CopyError (String::compose("Short read; expected %1 but read %2", this_time, read), 0);
+ }
+
+ digester.add (buffer, this_time);
+
+ size_t written;
+ r = ext4_fwrite (&out, buffer, this_time, &written);
+ if (r != EOK) {
+ fclose (in);
+ ext4_fclose (&out);
+ delete[] buffer;
+ throw CopyError ("Write failed", r);
+ }
+ if (written != this_time) {
+ fclose (in);
+ ext4_fclose (&out);
+ delete[] buffer;
+ throw CopyError (String::compose("Short write; expected %1 but wrote %2", this_time, written), 0);
+ }
+ remaining -= this_time;
+ total_remaining -= this_time;
+ nanomsg->blocking_send(String::compose(DISK_WRITER_PROGRESS "\n%1\n", (1 - float(total_remaining) / total)));
+ }
+
+ fclose (in);
+ ext4_fclose (&out);
+ delete[] buffer;
+
+ return digester.get ();
+}
+
+static
+string
+read (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total_remaining, uint64_t total)
+{
+ ext4_file in;
+ LOG_DISK("Opening %1 for read", to.generic_string());
+ int r = ext4_fopen(&in, to.generic_string().c_str(), "rb");
+ if (r != EOK) {
+ throw VerifyError (String::compose("Failed to open file %1", to.generic_string()), r);
+ }
+ LOG_DISK("Opened %1 for read", to.generic_string());
+
+ uint8_t* buffer = new uint8_t[block_size];
+ Digester digester;
+
+ uint64_t remaining = file_size (from);
+ while (remaining > 0) {
+ uint64_t const this_time = min(remaining, block_size);
+ size_t read;
+ r = ext4_fread (&in, buffer, this_time, &read);
+ if (read != this_time) {
+ ext4_fclose (&in);
+ delete[] buffer;
+ throw VerifyError (String::compose("Short read; expected %1 but read %2", this_time, read), 0);
+ }
+
+ digester.add (buffer, this_time);
+ remaining -= this_time;
+ total_remaining -= this_time;
+ nanomsg->blocking_send(String::compose(DISK_WRITER_PROGRESS "\n%1\n", (1 - float(total_remaining) / total)));
+ }
+
+ ext4_fclose (&in);
+ delete[] buffer;
+
+ return digester.get ();
+}
+
+
+/** @param from File to copy from.
+ * @param to Directory to copy to.
+ */
+static
+void
+copy (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total_remaining, uint64_t total)
+{
+ LOG_DISK ("Copy %1 -> %2", from.string(), to.generic_string());
+
+ using namespace boost::filesystem;
+
+ path const cr = to / from.filename();
+
+ if (is_directory(from)) {
+ int r = ext4_dir_mk (cr.generic_string().c_str());
+ if (r != EOK) {
+ throw CopyError (String::compose("Failed to create directory %1", cr.generic_string()), r);
+ }
+
+ for (directory_iterator i = directory_iterator(from); i != directory_iterator(); ++i) {
+ copy (i->path(), cr, total_remaining, total);
+ }
+ } else {
+ string const write_digest = write (from, cr, total_remaining, total);
+ LOG_DISK ("Wrote %1 %2 with %3", from.string(), cr.generic_string(), write_digest);
+ string const read_digest = read (from, cr, total_remaining, total);
+ LOG_DISK ("Read %1 %2 with %3", from.string(), cr.generic_string(), write_digest);
+ if (write_digest != read_digest) {
+ throw VerifyError ("Hash of written data is incorrect", 0);
+ }
+ }
+}
+
+static
+void
+write ()
+try
+{
+// ext4_dmask_set (DEBUG_ALL);
+
+ /* We rely on static initialization for these */
+ static struct ext4_fs fs;
+ static struct ext4_mkfs_info info;
+ info.block_size = 1024;
+ info.inode_size = 128;
+ info.journal = false;
+
+#ifdef WIN32
+ file_windows_name_set(device.c_str());
+ struct ext4_blockdev* bd = file_windows_dev_get();
+#else
+ file_dev_name_set (device.c_str());
+ struct ext4_blockdev* bd = file_dev_get ();
+#endif
+
+ if (!bd) {
+ throw CopyError ("Failed to open drive", 0);
+ }
+ LOG_DISK_NC ("Opened drive");
+
+ struct ext4_mbr_parts parts;
+ parts.division[0] = 100;
+ parts.division[1] = 0;
+ parts.division[2] = 0;
+ parts.division[3] = 0;
+
+#ifdef DCPOMATIC_LINUX
+ PrivilegeEscalator e;
+#endif
+
+ /* XXX: not sure if disk_id matters */
+ int r = ext4_mbr_write (bd, &parts, 0);
+
+ if (r) {
+ throw CopyError ("Failed to write MBR", r);
+ }
+ 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);
+ }
+
+ file_windows_partition_set (bdevs.partitions[0].part_offset, bdevs.partitions[0].part_size);
+#endif
+
+#ifdef DCPOMATIC_LINUX
+ /* Re-read the partition table */
+ int fd = open(device.c_str(), O_RDONLY);
+ ioctl(fd, BLKRRPART, NULL);
+ close(fd);
+#endif
+
+#ifdef DCPOMATIC_POSIX
+ string partition = device;
+ /* XXX: don't know if this logic is sensible */
+ if (partition.size() > 0 && isdigit(partition[partition.length() - 1])) {
+ partition += "p1";
+ } else {
+ partition += "1";
+ }
+ file_dev_name_set (partition.c_str());
+ bd = file_dev_get ();
+#endif
+
+ if (!bd) {
+ throw CopyError ("Failed to open partition", 0);
+ }
+ LOG_DISK_NC ("Opened partition");
+
+ nanomsg->blocking_send(DISK_WRITER_FORMATTING "\n");
+
+ r = ext4_mkfs(&fs, bd, &info, F_SET_EXT4);
+ if (r != EOK) {
+ throw CopyError ("Failed to make filesystem", r);
+ }
+ LOG_DISK_NC ("Made filesystem");
+
+ r = ext4_device_register(bd, "ext4_fs");
+ if (r != EOK) {
+ throw CopyError ("Failed to register device", r);
+ }
+ LOG_DISK_NC ("Registered device");
+
+ r = ext4_mount("ext4_fs", "/mp/", false);
+ if (r != EOK) {
+ throw CopyError ("Failed to mount device", r);
+ }
+ LOG_DISK_NC ("Mounted device");
+
+ uint64_t total_bytes = 0;
+ count (dcp_path, total_bytes);
+
+ /* XXX: this is a hack. We are going to "treat" every byte twice; write it, and then verify it. Double the
+ * bytes totals so that progress works itself out (assuming write is the same speed as read).
+ */
+ total_bytes *= 2;
+ copy (dcp_path, "/mp", total_bytes, total_bytes);
+
+ r = ext4_umount("/mp/");
+ if (r != EOK) {
+ throw CopyError ("Failed to unmount device", r);
+ }
+
+ nanomsg->blocking_send(DISK_WRITER_OK "\n");
+} catch (CopyError& e) {
+ LOG_DISK("CopyError: %1 %2", e.message(), e.number());
+ nanomsg->blocking_send(String::compose(DISK_WRITER_ERROR "\n%1\n%2\n", e.message(), e.number()));
+} catch (VerifyError& e) {
+ LOG_DISK("VerifyError: %1 %2", e.message(), e.number());
+ nanomsg->blocking_send(String::compose(DISK_WRITER_ERROR "\n%1\n%2\n", e.message(), e.number()));
+} catch (exception& e) {
+ LOG_DISK("Exception: %1", e.what());
+ nanomsg->blocking_send(String::compose(DISK_WRITER_ERROR "\n%1\n0\n", e.what()));
+}
+
+#ifdef DCPOMATIC_LINUX
+static
+void
+polkit_callback (GObject *, GAsyncResult* res, gpointer)
+{
+ PolkitAuthorizationResult* result = polkit_authority_check_authorization_finish (polkit_authority, res, 0);
+ if (result && polkit_authorization_result_get_is_authorized(result)) {
+ write ();
+ }
+ if (result) {
+ g_object_unref (result);
+ }
+}
+#endif
+
+bool
+idle ()
+{
+ optional<string> s = nanomsg->nonblocking_get ();
+ if (!s) {
+ return true;
+ }
+
+ if (*s == "Q") {
+ exit (EXIT_SUCCESS);
+ } else if (*s == "W") {
+ dcp_path = nanomsg->blocking_get();
+ device = nanomsg->blocking_get();
+
+ LOG_DISK ("Here we go writing %1 to %2", dcp_path, device);
+
+#ifdef DCPOMATIC_LINUX
+ polkit_authority = polkit_authority_get_sync (0, 0);
+ PolkitSubject* subject = polkit_unix_process_new (getppid());
+ polkit_authority_check_authorization (
+ polkit_authority, subject, "com.dcpomatic.write-drive", 0, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, 0, polkit_callback, 0
+ );
+#else
+ write ();
+#endif
+ }
+
+ return true;
+}
+
+int
+main ()
+{
+ /* XXX: this is a hack, but I expect we'll need logs and I'm not sure if there's
+ * a better place to put them.
+ */
+ dcpomatic_log.reset(new FileLog(config_path() / "disk_writer.log"));
+ dcpomatic_log->set_types (dcpomatic_log->types() | LogEntry::TYPE_DISK);
+ LOG_DISK_NC("dcpomatic_disk_writer started");
+
+ try {
+ nanomsg = new Nanomsg (false);
+ } catch (runtime_error& e) {
+ LOG_DISK_NC("Could not set up nanomsg socket");
+ exit (EXIT_FAILURE);
+ }
+
+ Glib::RefPtr<Glib::MainLoop> ml = Glib::MainLoop::create ();
+ Glib::signal_timeout().connect(sigc::ptr_fun(&idle), 500);
+ ml->run ();
+}
+++ /dev/null
-/*
- Copyright (C) 2019-2020 Carl Hetherington <cth@carlh.net>
-
- This file is part of DCP-o-matic.
-
- DCP-o-matic 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.
-
- DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include "wx/wx_signal_manager.h"
-#include "wx/wx_util.h"
-#include "wx/job_manager_view.h"
-#include "wx/drive_wipe_warning_dialog.h"
-#include "lib/file_log.h"
-#include "lib/dcpomatic_log.h"
-#include "lib/util.h"
-#include "lib/config.h"
-#include "lib/signal_manager.h"
-#include "lib/cross.h"
-#include "lib/copy_to_drive_job.h"
-#include "lib/job_manager.h"
-#include "lib/dist_writer_messages.h"
-#include <wx/wx.h>
-#include <boost/process.hpp>
-#ifdef DCPOMATIC_WINDOWS
-#include <boost/process/windows.hpp>
-#endif
-#ifdef DCPOMATIC_OSX
-#include <ApplicationServices/ApplicationServices.h>
-#endif
-
-using std::string;
-using std::exception;
-using std::cout;
-using std::cerr;
-using std::runtime_error;
-using boost::shared_ptr;
-
-class DOMFrame : public wxFrame
-{
-public:
- explicit DOMFrame (wxString const & title)
- : wxFrame (0, -1, title)
- , _nanomsg (true)
- , _sizer (new wxBoxSizer(wxVERTICAL))
- {
- /* Use a panel as the only child of the Frame so that we avoid
- the dark-grey background on Windows.
- */
- wxPanel* overall_panel = new wxPanel (this);
- wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
- s->Add (overall_panel, 1, wxEXPAND);
- SetSizer (s);
-
- wxGridBagSizer* grid = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
-
- int r = 0;
- add_label_to_sizer (grid, overall_panel, _("DCP"), true, wxGBPosition(r, 0));
- wxBoxSizer* dcp_name_sizer = new wxBoxSizer (wxHORIZONTAL);
- _dcp_name = new wxStaticText (overall_panel, wxID_ANY, wxEmptyString);
- dcp_name_sizer->Add (_dcp_name, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, DCPOMATIC_SIZER_X_GAP);
- _dcp_open = new wxButton (overall_panel, wxID_ANY, _("Open..."));
- dcp_name_sizer->Add (_dcp_open, 0);
- grid->Add (dcp_name_sizer, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND);
- ++r;
-
- add_label_to_sizer (grid, overall_panel, _("Drive"), true, wxGBPosition(r, 0));
- wxBoxSizer* drive_sizer = new wxBoxSizer (wxHORIZONTAL);
- _drive = new wxChoice (overall_panel, wxID_ANY);
- drive_sizer->Add (_drive, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, DCPOMATIC_SIZER_X_GAP);
- _drive_refresh = new wxButton (overall_panel, wxID_ANY, _("Refresh"));
- drive_sizer->Add (_drive_refresh, 0);
- grid->Add (drive_sizer, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND);
- ++r;
-
- _jobs = new JobManagerView (overall_panel, false);
- grid->Add (_jobs, wxGBPosition(r, 0), wxGBSpan(6, 2), wxEXPAND);
- r += 6;
-
- _copy = new wxButton (overall_panel, wxID_ANY, _("Copy DCP"));
- grid->Add (_copy, wxGBPosition(r, 0), wxGBSpan(1, 2), wxEXPAND);
- ++r;
-
- grid->AddGrowableCol (1);
-
- _dcp_open->Bind (wxEVT_BUTTON, boost::bind(&DOMFrame::open, this));
- _copy->Bind (wxEVT_BUTTON, boost::bind(&DOMFrame::copy, this));
- _drive->Bind (wxEVT_CHOICE, boost::bind(&DOMFrame::setup_sensitivity, this));
- _drive_refresh->Bind (wxEVT_BUTTON, boost::bind(&DOMFrame::drive_refresh, this));
-
- _sizer->Add (grid, 1, wxALL | wxEXPAND, DCPOMATIC_DIALOG_BORDER);
- overall_panel->SetSizer (_sizer);
- Fit ();
- SetSize (768, GetSize().GetHeight() + 32);
-
- /* XXX: this is a hack, but I expect we'll need logs and I'm not sure if there's
- * a better place to put them.
- */
- dcpomatic_log.reset(new FileLog(config_path() / "dist.log"));
- dcpomatic_log->set_types (dcpomatic_log->types() | LogEntry::TYPE_DIST);
- LOG_DIST_NC("dcpomatic_dist started");
-
- drive_refresh ();
-
- Bind (wxEVT_SIZE, boost::bind (&DOMFrame::sized, this, _1));
-
- JobManager::instance()->ActiveJobsChanged.connect(boost::bind(&DOMFrame::setup_sensitivity, this));
-
-#ifdef DCPOMATIC_WINDOWS
- /* We must use ::shell here, it seems, to avoid error code 740 (related to privilege escalation) */
- _writer = new boost::process::child (dist_writer_path(), boost::process::shell, boost::process::windows::hide);
-#else
- LOG_DIST("Starting writer process %1", dist_writer_path().string());
- _writer = new boost::process::child (dist_writer_path());
-#endif
- }
-
- ~DOMFrame ()
- {
- _nanomsg.blocking_send(DIST_WRITER_QUIT "\n");
- }
-
-private:
- void sized (wxSizeEvent& ev)
- {
- _sizer->Layout ();
- ev.Skip ();
- }
-
- void open ()
- {
- wxDirDialog* d = new wxDirDialog (this, _("Choose a DCP folder"), wxT(""), wxDD_DIR_MUST_EXIST);
- int r = d->ShowModal ();
- boost::filesystem::path const path (wx_to_std(d->GetPath()));
- d->Destroy ();
-
- if (r != wxID_OK) {
- return;
- }
-
- _dcp_path = path;
- _dcp_name->SetLabel (std_to_wx(_dcp_path->filename().string()));
- setup_sensitivity ();
- }
-
- void copy ()
- {
- DCPOMATIC_ASSERT (_drive->GetSelection() != wxNOT_FOUND);
- DCPOMATIC_ASSERT (static_cast<bool>(_dcp_path));
- DriveWipeWarningDialog* d = new DriveWipeWarningDialog (this, _drive->GetString(_drive->GetSelection()));
- int const r = d->ShowModal ();
- bool ok = r == wxID_OK && d->confirmed();
- d->Destroy ();
-
- if (!ok) {
- return;
- }
-
- JobManager::instance()->add(shared_ptr<Job>(new CopyToDriveJob(*_dcp_path, _drives[_drive->GetSelection()], _nanomsg)));
- setup_sensitivity ();
- }
-
- void drive_refresh ()
- {
- int const sel = _drive->GetSelection ();
- wxString current;
- if (sel != wxNOT_FOUND) {
- current = _drive->GetString (sel);
- }
- _drive->Clear ();
- int re_select = wxNOT_FOUND;
- int j = 0;
- _drives.clear ();
- BOOST_FOREACH (Drive i, get_drives()) {
- if (!i.mounted()) {
- _drives.push_back (i);
- }
- }
- BOOST_FOREACH (Drive i, _drives) {
- wxString const s = std_to_wx(i.description());
- if (s == current) {
- re_select = j;
- }
- _drive->Append(s);
- ++j;
- }
- _drive->SetSelection (re_select);
- setup_sensitivity ();
- }
-
- void setup_sensitivity ()
- {
- _copy->Enable (static_cast<bool>(_dcp_path) && _drive->GetSelection() != wxNOT_FOUND && !JobManager::instance()->work_to_do());
- }
-
- wxStaticText* _dcp_name;
- wxButton* _dcp_open;
- wxChoice* _drive;
- wxButton* _drive_refresh;
- wxButton* _copy;
- JobManagerView* _jobs;
- boost::optional<boost::filesystem::path> _dcp_path;
- std::vector<Drive> _drives;
- boost::process::child* _writer;
- Nanomsg _nanomsg;
- wxSizer* _sizer;
-};
-
-class App : public wxApp
-{
-public:
- App ()
- : _frame (0)
- {}
-
- bool OnInit ()
- {
- try {
- Config::FailedToLoad.connect (boost::bind (&App::config_failed_to_load, this));
- Config::Warning.connect (boost::bind (&App::config_warning, this, _1));
-
- SetAppName (_("DCP-o-matic Disk Writer"));
-
- if (!wxApp::OnInit()) {
- return false;
- }
-
-#ifdef DCPOMATIC_LINUX
- unsetenv ("UBUNTU_MENUPROXY");
-#endif
-
-#ifdef __WXOSX__
- ProcessSerialNumber serial;
- GetCurrentProcess (&serial);
- TransformProcessType (&serial, kProcessTransformToForegroundApplication);
-#endif
-
- dcpomatic_setup_path_encoding ();
-
- /* Enable i18n; this will create a Config object
- to look for a force-configured language. This Config
- object will be wrong, however, because dcpomatic_setup
- hasn't yet been called and there aren't any filters etc.
- set up yet.
- */
- dcpomatic_setup_i18n ();
-
- /* Set things up, including filters etc.
- which will now be internationalised correctly.
- */
- dcpomatic_setup ();
-
- /* Force the configuration to be re-loaded correctly next
- time it is needed.
- */
- Config::drop ();
-
- _frame = new DOMFrame (_("DCP-o-matic Disk Writer"));
- SetTopWindow (_frame);
-
- _frame->Show ();
-
- signal_manager = new wxSignalManager (this);
- Bind (wxEVT_IDLE, boost::bind (&App::idle, this, _1));
- }
- catch (exception& e)
- {
- error_dialog (0, wxString::Format ("DCP-o-matic could not start."), std_to_wx(e.what()));
- }
-
- return true;
- }
-
- void config_failed_to_load ()
- {
- message_dialog (_frame, _("The existing configuration failed to load. Default values will be used instead. These may take a short time to create."));
- }
-
- void config_warning (string m)
- {
- message_dialog (_frame, std_to_wx(m));
- }
-
- void idle (wxIdleEvent& ev)
- {
- signal_manager->ui_idle ();
- ev.Skip ();
- }
-
- DOMFrame* _frame;
-};
-
-IMPLEMENT_APP (App)
+++ /dev/null
-/*
- Copyright (C) 2019-2020 Carl Hetherington <cth@carlh.net>
-
- This file is part of DCP-o-matic.
-
- DCP-o-matic 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.
-
- DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include "lib/dist_writer_messages.h"
-#include "lib/compose.hpp"
-#include "lib/exceptions.h"
-#include "lib/cross.h"
-#include "lib/digester.h"
-#include "lib/file_log.h"
-#include "lib/dcpomatic_log.h"
-#include "lib/nanomsg.h"
-extern "C" {
-#include <lwext4/ext4_mbr.h>
-#include <lwext4/ext4_fs.h>
-#include <lwext4/ext4_mkfs.h>
-#include <lwext4/ext4_errno.h>
-#include <lwext4/ext4_debug.h>
-#include <lwext4/ext4.h>
-}
-
-#ifdef DCPOMATIC_POSIX
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#endif
-
-#ifdef DCPOMATIC_OSX
-#undef nil
-extern "C" {
-#include <lwext4/file_dev.h>
-}
-#endif
-
-#ifdef DCPOMATIC_LINUX
-#include <linux/fs.h>
-#include <polkit/polkit.h>
-extern "C" {
-#include <lwext4/file_dev.h>
-}
-#include <poll.h>
-#endif
-
-#ifdef DCPOMATIC_WINDOWS
-extern "C" {
-#include <lwext4/file_windows.h>
-}
-#endif
-
-#include <glibmm.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <boost/filesystem.hpp>
-#include <iostream>
-
-using std::cin;
-using std::min;
-using std::string;
-using std::runtime_error;
-using std::exception;
-using boost::optional;
-
-#ifdef DCPOMATIC_LINUX
-static PolkitAuthority* polkit_authority = 0;
-#endif
-static boost::filesystem::path dcp_path;
-static std::string device;
-static uint64_t const block_size = 4096;
-static Nanomsg* nanomsg = 0;
-
-static
-void
-count (boost::filesystem::path dir, uint64_t& total_bytes)
-{
- using namespace boost::filesystem;
- for (directory_iterator i = directory_iterator(dir); i != directory_iterator(); ++i) {
- if (is_directory(*i)) {
- count (*i, total_bytes);
- } else {
- total_bytes += file_size (*i);
- }
- }
-}
-
-static
-string
-write (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total_remaining, uint64_t total)
-{
- ext4_file out;
- int r = ext4_fopen(&out, to.generic_string().c_str(), "wb");
- if (r != EOK) {
- throw CopyError (String::compose("Failed to open file %1", to.generic_string()), r);
- }
-
- FILE* in = fopen_boost (from, "rb");
- if (!in) {
- ext4_fclose (&out);
- throw CopyError (String::compose("Failed to open file %1", from.string()), 0);
- }
-
- uint8_t* buffer = new uint8_t[block_size];
- Digester digester;
-
- uint64_t remaining = file_size (from);
- while (remaining > 0) {
- uint64_t const this_time = min(remaining, block_size);
- size_t read = fread (buffer, 1, this_time, in);
- if (read != this_time) {
- fclose (in);
- ext4_fclose (&out);
- delete[] buffer;
- throw CopyError (String::compose("Short read; expected %1 but read %2", this_time, read), 0);
- }
-
- digester.add (buffer, this_time);
-
- size_t written;
- r = ext4_fwrite (&out, buffer, this_time, &written);
- if (r != EOK) {
- fclose (in);
- ext4_fclose (&out);
- delete[] buffer;
- throw CopyError ("Write failed", r);
- }
- if (written != this_time) {
- fclose (in);
- ext4_fclose (&out);
- delete[] buffer;
- throw CopyError (String::compose("Short write; expected %1 but wrote %2", this_time, written), 0);
- }
- remaining -= this_time;
- total_remaining -= this_time;
- nanomsg->blocking_send(String::compose(DIST_WRITER_PROGRESS "\n%1\n", (1 - float(total_remaining) / total)));
- }
-
- fclose (in);
- ext4_fclose (&out);
- delete[] buffer;
-
- return digester.get ();
-}
-
-static
-string
-read (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total_remaining, uint64_t total)
-{
- ext4_file in;
- LOG_DIST("Opening %1 for read", to.generic_string());
- int r = ext4_fopen(&in, to.generic_string().c_str(), "rb");
- if (r != EOK) {
- throw VerifyError (String::compose("Failed to open file %1", to.generic_string()), r);
- }
- LOG_DIST("Opened %1 for read", to.generic_string());
-
- uint8_t* buffer = new uint8_t[block_size];
- Digester digester;
-
- uint64_t remaining = file_size (from);
- while (remaining > 0) {
- uint64_t const this_time = min(remaining, block_size);
- size_t read;
- r = ext4_fread (&in, buffer, this_time, &read);
- if (read != this_time) {
- ext4_fclose (&in);
- delete[] buffer;
- throw VerifyError (String::compose("Short read; expected %1 but read %2", this_time, read), 0);
- }
-
- digester.add (buffer, this_time);
- remaining -= this_time;
- total_remaining -= this_time;
- nanomsg->blocking_send(String::compose(DIST_WRITER_PROGRESS "\n%1\n", (1 - float(total_remaining) / total)));
- }
-
- ext4_fclose (&in);
- delete[] buffer;
-
- return digester.get ();
-}
-
-
-/** @param from File to copy from.
- * @param to Directory to copy to.
- */
-static
-void
-copy (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total_remaining, uint64_t total)
-{
- LOG_DIST ("Copy %1 -> %2", from.string(), to.generic_string());
-
- using namespace boost::filesystem;
-
- path const cr = to / from.filename();
-
- if (is_directory(from)) {
- int r = ext4_dir_mk (cr.generic_string().c_str());
- if (r != EOK) {
- throw CopyError (String::compose("Failed to create directory %1", cr.generic_string()), r);
- }
-
- for (directory_iterator i = directory_iterator(from); i != directory_iterator(); ++i) {
- copy (i->path(), cr, total_remaining, total);
- }
- } else {
- string const write_digest = write (from, cr, total_remaining, total);
- LOG_DIST ("Wrote %1 %2 with %3", from.string(), cr.generic_string(), write_digest);
- string const read_digest = read (from, cr, total_remaining, total);
- LOG_DIST ("Read %1 %2 with %3", from.string(), cr.generic_string(), write_digest);
- if (write_digest != read_digest) {
- throw VerifyError ("Hash of written data is incorrect", 0);
- }
- }
-}
-
-static
-void
-write ()
-try
-{
-// ext4_dmask_set (DEBUG_ALL);
-
- /* We rely on static initialization for these */
- static struct ext4_fs fs;
- static struct ext4_mkfs_info info;
- info.block_size = 1024;
- info.inode_size = 128;
- info.journal = false;
-
-#ifdef WIN32
- file_windows_name_set(device.c_str());
- struct ext4_blockdev* bd = file_windows_dev_get();
-#else
- file_dev_name_set (device.c_str());
- struct ext4_blockdev* bd = file_dev_get ();
-#endif
-
- if (!bd) {
- throw CopyError ("Failed to open drive", 0);
- }
- LOG_DIST_NC ("Opened drive");
-
- struct ext4_mbr_parts parts;
- parts.division[0] = 100;
- parts.division[1] = 0;
- parts.division[2] = 0;
- parts.division[3] = 0;
-
-#ifdef DCPOMATIC_LINUX
- PrivilegeEscalator e;
-#endif
-
- /* XXX: not sure if disk_id matters */
- int r = ext4_mbr_write (bd, &parts, 0);
-
- if (r) {
- throw CopyError ("Failed to write MBR", r);
- }
- LOG_DIST_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);
- }
-
- file_windows_partition_set (bdevs.partitions[0].part_offset, bdevs.partitions[0].part_size);
-#endif
-
-#ifdef DCPOMATIC_LINUX
- /* Re-read the partition table */
- int fd = open(device.c_str(), O_RDONLY);
- ioctl(fd, BLKRRPART, NULL);
- close(fd);
-#endif
-
-#ifdef DCPOMATIC_POSIX
- string partition = device;
- /* XXX: don't know if this logic is sensible */
- if (partition.size() > 0 && isdigit(partition[partition.length() - 1])) {
- partition += "p1";
- } else {
- partition += "1";
- }
- file_dev_name_set (partition.c_str());
- bd = file_dev_get ();
-#endif
-
- if (!bd) {
- throw CopyError ("Failed to open partition", 0);
- }
- LOG_DIST_NC ("Opened partition");
-
- nanomsg->blocking_send(DIST_WRITER_FORMATTING "\n");
-
- r = ext4_mkfs(&fs, bd, &info, F_SET_EXT4);
- if (r != EOK) {
- throw CopyError ("Failed to make filesystem", r);
- }
- LOG_DIST_NC ("Made filesystem");
-
- r = ext4_device_register(bd, "ext4_fs");
- if (r != EOK) {
- throw CopyError ("Failed to register device", r);
- }
- LOG_DIST_NC ("Registered device");
-
- r = ext4_mount("ext4_fs", "/mp/", false);
- if (r != EOK) {
- throw CopyError ("Failed to mount device", r);
- }
- LOG_DIST_NC ("Mounted device");
-
- uint64_t total_bytes = 0;
- count (dcp_path, total_bytes);
-
- /* XXX: this is a hack. We are going to "treat" every byte twice; write it, and then verify it. Double the
- * bytes totals so that progress works itself out (assuming write is the same speed as read).
- */
- total_bytes *= 2;
- copy (dcp_path, "/mp", total_bytes, total_bytes);
-
- r = ext4_umount("/mp/");
- if (r != EOK) {
- throw CopyError ("Failed to unmount device", r);
- }
-
- nanomsg->blocking_send(DIST_WRITER_OK "\n");
-} catch (CopyError& e) {
- LOG_DIST("CopyError: %1 %2", e.message(), e.number());
- nanomsg->blocking_send(String::compose(DIST_WRITER_ERROR "\n%1\n%2\n", e.message(), e.number()));
-} catch (VerifyError& e) {
- LOG_DIST("VerifyError: %1 %2", e.message(), e.number());
- nanomsg->blocking_send(String::compose(DIST_WRITER_ERROR "\n%1\n%2\n", e.message(), e.number()));
-} catch (exception& e) {
- LOG_DIST("Exception: %1", e.what());
- nanomsg->blocking_send(String::compose(DIST_WRITER_ERROR "\n%1\n0\n", e.what()));
-}
-
-#ifdef DCPOMATIC_LINUX
-static
-void
-polkit_callback (GObject *, GAsyncResult* res, gpointer)
-{
- PolkitAuthorizationResult* result = polkit_authority_check_authorization_finish (polkit_authority, res, 0);
- if (result && polkit_authorization_result_get_is_authorized(result)) {
- write ();
- }
- if (result) {
- g_object_unref (result);
- }
-}
-#endif
-
-bool
-idle ()
-{
- optional<string> s = nanomsg->nonblocking_get ();
- if (!s) {
- return true;
- }
-
- if (*s == "Q") {
- exit (EXIT_SUCCESS);
- } else if (*s == "W") {
- dcp_path = nanomsg->blocking_get();
- device = nanomsg->blocking_get();
-
- LOG_DIST ("Here we go writing %1 to %2", dcp_path, device);
-
-#ifdef DCPOMATIC_LINUX
- polkit_authority = polkit_authority_get_sync (0, 0);
- PolkitSubject* subject = polkit_unix_process_new (getppid());
- polkit_authority_check_authorization (
- polkit_authority, subject, "com.dcpomatic.write-drive", 0, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, 0, polkit_callback, 0
- );
-#else
- write ();
-#endif
- }
-
- return true;
-}
-
-int
-main ()
-{
- /* XXX: this is a hack, but I expect we'll need logs and I'm not sure if there's
- * a better place to put them.
- */
- dcpomatic_log.reset(new FileLog(config_path() / "dist_writer.log"));
- dcpomatic_log->set_types (dcpomatic_log->types() | LogEntry::TYPE_DIST);
- LOG_DIST_NC("dcpomatic_dist_writer started");
-
- try {
- nanomsg = new Nanomsg (false);
- } catch (runtime_error& e) {
- LOG_DIST_NC("Could not set up nanomsg socket");
- exit (EXIT_FAILURE);
- }
-
- Glib::RefPtr<Glib::MainLoop> ml = Glib::MainLoop::create ();
- Glib::signal_timeout().connect(sigc::ptr_fun(&idle), 500);
- ml->run ();
-}
uselib += 'AVUTIL SWSCALE SWRESAMPLE POSTPROC CURL BOOST_FILESYSTEM SSH ZIP CAIROMM FONTCONFIG PANGOMM SUB '
uselib += 'SNDFILE SAMPLERATE BOOST_REGEX ICU NETTLE RTAUDIO PNG '
- if bld.env.ENABLE_DIST:
+ if bld.env.ENABLE_DISK:
if bld.env.TARGET_LINUX:
uselib += 'POLKIT '
uselib += 'LWEXT4 NANOMSG '
cli_tools = ['dcpomatic_cli', 'dcpomatic_server_cli', 'server_test', 'dcpomatic_kdm_cli', 'dcpomatic_create', 'swaroop_dcpomatic_ecinema', 'swaroop_dcpomatic_uuid']
else:
cli_tools = ['dcpomatic_cli', 'dcpomatic_server_cli', 'server_test', 'dcpomatic_kdm_cli', 'dcpomatic_create']
- if bld.env.ENABLE_DIST:
- cli_tools.append('dcpomatic_dist_writer')
+ if bld.env.ENABLE_DISK:
+ cli_tools.append('dcpomatic_disk_writer')
for t in cli_tools:
obj = bld(features='cxx cxxprogram')
obj.includes = ['..']
obj.use = ['libdcpomatic2']
obj.source = '%s.cc' % t
- if bld.env.TARGET_WINDOWS and t == 'dcpomatic_dist_writer':
+ if bld.env.TARGET_WINDOWS and t == 'dcpomatic_disk_writer':
obj.source += ' ../../platform/windows/%s.rc' % t
- # Prevent a console window opening when we start dcpomatic2_dist_writer
+ # Prevent a console window opening when we start dcpomatic2_disk_writer
bld.env.LINKFLAGS.append('-Wl,-subsystem,windows')
obj.target = t.replace('dcpomatic', 'dcpomatic2').replace('swaroop_', '')
if t == 'server_test':
gui_tools = ['dcpomatic', 'dcpomatic_batch', 'dcpomatic_server', 'dcpomatic_kdm', 'dcpomatic_player', 'swaroop_dcpomatic_playlist']
else:
gui_tools = ['dcpomatic', 'dcpomatic_batch', 'dcpomatic_server', 'dcpomatic_kdm', 'dcpomatic_player', 'dcpomatic_playlist']
- if bld.env.ENABLE_DIST:
- gui_tools.append('dcpomatic_dist')
+ if bld.env.ENABLE_DISK:
+ gui_tools.append('dcpomatic_disk')
for t in gui_tools:
obj = bld(features='cxx cxxprogram')
opt.add_option('--force-cpp11', action='store_true', default=False, help='force use of C++11')
opt.add_option('--variant', help='build variant (swaroop-studio, swaroop-theater)', choices=['swaroop-studio', 'swaroop-theater'])
opt.add_option('--use-lld', action='store_true', default=False, help='use lld linker')
- opt.add_option('--enable-dist', action='store_true', default=False, help='build dcpomatic2_dist tool; requires Boost process and lwext4 libraries')
+ opt.add_option('--enable-disk', action='store_true', default=False, help='build dcpomatic2_disk tool; requires Boost process and lwext4 libraries')
def configure(conf):
conf.load('compiler_cxx')
conf.env.VERSION = VERSION
conf.env.DEBUG = conf.options.enable_debug
conf.env.STATIC_DCPOMATIC = conf.options.static_dcpomatic
- conf.env.ENABLE_DIST = conf.options.enable_dist
+ conf.env.ENABLE_DISK = conf.options.enable_disk
if conf.options.install_prefix is None:
conf.env.INSTALL_PREFIX = conf.env.PREFIX
else:
conf.check_cfg(package='libpng', args='--cflags --libs', uselib_store='PNG', mandatory=True)
# lwext4
- if conf.options.enable_dist:
+ if conf.options.enable_disk:
conf.check_cxx(fragment="""
#include <lwext4/ext4.h>\n
int main() { ext4_mount("ext4_fs", "/mp/", false); }\n
lib=['lwext4', 'blockdev'],
uselib_store='LWEXT4')
- if conf.env.TARGET_LINUX and conf.options.enable_dist:
+ if conf.env.TARGET_LINUX and conf.options.enable_disk:
conf.check_cfg(package='polkit-gobject-1', args='--cflags --libs', uselib_store='POLKIT', mandatory=True)
# nanomsg
- if conf.options.enable_dist:
+ if conf.options.enable_disk:
if conf.check_cfg(package='nanomsg', args='--cflags --libs', uselib_store='NANOMSG', mandatory=False) is None:
conf.check_cfg(package='libnanomsg', args='--cflags --libs', uselib_store='NANOMSG', mandatory=True)
# Really just checking for the header here (there's no associated library) but the test
# program has to link with boost_system so I'm doing it this way.
- if conf.options.enable_dist:
+ if conf.options.enable_disk:
deps = ['boost_system%s' % boost_lib_suffix]
if conf.env.TARGET_WINDOWS:
deps.append('ws2_32')
if ctx.cmd == 'install' and ctx.env.TARGET_LINUX:
ctx.exec_command('/sbin/ldconfig')
# setuid root executables
- for e in ['dcpomatic2_uuid', 'dcpomatic2_dist_writer']:
+ for e in ['dcpomatic2_uuid', 'dcpomatic2_disk_writer']:
# I can't find anything which tells me where things have been installed to,
# so here's some nasty hacks to guess.
debian = os.path.join(ctx.out_dir, '../debian/dcpomatic/usr/bin/%s' % e)